diff --git a/src/AttributeSystem/AggregateType.cs b/src/AttributeSystem/AggregateType.cs index 660211fff..6eca97d23 100644 --- a/src/AttributeSystem/AggregateType.cs +++ b/src/AttributeSystem/AggregateType.cs @@ -15,7 +15,7 @@ public enum AggregateType AddRaw, /// - /// Multiplicates the value. + /// Multiplicates by the raw value. /// Multiplicate, diff --git a/src/AttributeSystem/AttributeRelationship.cs b/src/AttributeSystem/AttributeRelationship.cs index af75c07f1..551254a76 100644 --- a/src/AttributeSystem/AttributeRelationship.cs +++ b/src/AttributeSystem/AttributeRelationship.cs @@ -12,24 +12,34 @@ namespace MUnique.OpenMU.AttributeSystem; public enum InputOperator { /// - /// The is multiplied with the before adding to the . + /// The is multiplied with the before effecting the . /// Multiply, /// - /// The is increased by the before adding to the . + /// The is increased by the before effecting the . /// Add, /// - /// The is exponentiated by the before adding to the . + /// The is exponentiated by the before effecting the . /// Exponentiate, /// - /// The is exponentiated by the before adding to the . + /// The is exponentiated by the before effecting the . /// ExponentiateByAttribute, + + /// + /// The minimum between and is taken before effecting the . + /// + Minimum, + + /// + /// The maximum between and is taken before effecting the . + /// + Maximum, } /// @@ -54,8 +64,10 @@ public AttributeRelationship() /// The target attribute. /// The multiplier. /// The input attribute. - public AttributeRelationship(AttributeDefinition targetAttribute, float inputOperand, AttributeDefinition inputAttribute) - : this(targetAttribute, inputOperand, inputAttribute, InputOperator.Multiply) + /// The type of the aggregate on the . + /// The calculation stage on the . + public AttributeRelationship(AttributeDefinition targetAttribute, float inputOperand, AttributeDefinition inputAttribute, AggregateType aggregateType, byte stage) + : this(targetAttribute, inputOperand, inputAttribute, InputOperator.Multiply, default, aggregateType, stage) { } @@ -65,8 +77,10 @@ public AttributeRelationship(AttributeDefinition targetAttribute, float inputOpe /// The target attribute. /// The multiplier. /// The input attribute. - public AttributeRelationship(AttributeDefinition targetAttribute, AttributeDefinition inputOperand, AttributeDefinition inputAttribute) - : this(targetAttribute, 1, inputAttribute, InputOperator.Multiply, inputOperand) + /// The type of the aggregate on the . + /// The calculation stage on the . + public AttributeRelationship(AttributeDefinition targetAttribute, AttributeDefinition inputOperand, AttributeDefinition inputAttribute, AggregateType aggregateType, byte stage) + : this(targetAttribute, 1, inputAttribute, InputOperator.Multiply, inputOperand, aggregateType, stage) { } @@ -78,10 +92,14 @@ public AttributeRelationship(AttributeDefinition targetAttribute, AttributeDefin /// The input attribute. /// The input operator. /// The operand attribute. - public AttributeRelationship(AttributeDefinition targetAttribute, float inputOperand, AttributeDefinition inputAttribute, InputOperator inputOperator, AttributeDefinition? operandAttribute = null) + /// The type of the aggregate on the . + /// The calculation stage on the . + public AttributeRelationship(AttributeDefinition targetAttribute, float inputOperand, AttributeDefinition inputAttribute, InputOperator inputOperator, AttributeDefinition? operandAttribute = null, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { this.InputOperand = inputOperand; this.InputOperator = inputOperator; + this.AggregateType = aggregateType; + this.Stage = stage; this._targetAttribute = targetAttribute; this._inputAttribute = inputAttribute; this._operandAttribute = operandAttribute; @@ -125,6 +143,16 @@ public virtual AttributeDefinition? OperandAttribute /// public float InputOperand { get; set; } + /// + /// Gets or sets the aggregate type with which the relationship should effect the target attribute. + /// + public AggregateType AggregateType { get; set; } + + /// + /// Gets or sets the calculation stage at which the relationship should effect the target attribute. + /// + public byte Stage { get; set; } + /// public override string ToString() { @@ -135,9 +163,9 @@ public override string ToString() if (this.InputOperator == InputOperator.ExponentiateByAttribute) { - return $"{this.TargetAttribute} += {this.OperandAttribute?.ToString() ?? this.InputOperand.ToString(CultureInfo.InvariantCulture)} {this.InputOperator.AsString()} {this.InputAttribute}"; + return $"{this.TargetAttribute} {(this.AggregateType == AggregateType.Multiplicate ? "*" : "+")}= {this.OperandAttribute?.ToString() ?? this.InputOperand.ToString(CultureInfo.InvariantCulture)} {this.InputOperator.AsString()} {this.InputAttribute}"; } - return $"{this.TargetAttribute} += {this.InputAttribute} {this.InputOperator.AsString()} {this.OperandAttribute?.ToString() ?? this.InputOperand.ToString(CultureInfo.InvariantCulture)}"; + return $"{this.TargetAttribute} {(this.AggregateType == AggregateType.Multiplicate ? "*" : "+")}= {this.InputAttribute} {this.InputOperator.AsString()} {this.OperandAttribute?.ToString() ?? this.InputOperand.ToString(CultureInfo.InvariantCulture)}"; } } \ No newline at end of file diff --git a/src/AttributeSystem/AttributeRelationshipElement.cs b/src/AttributeSystem/AttributeRelationshipElement.cs index 3b30ad5f0..e1b552b99 100644 --- a/src/AttributeSystem/AttributeRelationshipElement.cs +++ b/src/AttributeSystem/AttributeRelationshipElement.cs @@ -76,7 +76,13 @@ private float CalculateValue() InputOperator.ExponentiateByAttribute => (float)Math.Pow( this.InputOperand.Value, this.InputElements.Sum(a => a.Value)), - _ => throw new InvalidOperationException($"Input operator {this.InputOperator} unknown") + InputOperator.Minimum => Math.Min( + this.InputElements.Sum(a => a.Value), + this.InputOperand.Value), + InputOperator.Maximum => Math.Max( + this.InputElements.Sum(a => a.Value), + this.InputOperand.Value), + _ => throw new InvalidOperationException($"Input operator {this.InputOperator} unknown"), }; } } \ No newline at end of file diff --git a/src/AttributeSystem/AttributeSystem.cs b/src/AttributeSystem/AttributeSystem.cs index 7f707a6f9..755254f95 100644 --- a/src/AttributeSystem/AttributeSystem.cs +++ b/src/AttributeSystem/AttributeSystem.cs @@ -70,6 +70,7 @@ public IElement CreateRelatedAttribute(AttributeRelationship relationship, IAttr return new AttributeRelationshipElement(inputElements, relationship.GetOperandElement(sourceAttributeHolder), relationship.InputOperator) { AggregateType = aggregateType, + Stage = relationship.Stage, }; } @@ -238,7 +239,7 @@ protected virtual void OnAttributeRemoved(IAttribute attribute) /// The combination. private void AddAttributeRelationship(AttributeRelationship combination) { - this.AddAttributeRelationship(combination, this, AggregateType.AddRaw); + this.AddAttributeRelationship(combination, this, combination.AggregateType); } private IElement? GetAttribute(AttributeDefinition? attributeDefinition) diff --git a/src/AttributeSystem/BaseAttribute.cs b/src/AttributeSystem/BaseAttribute.cs index b4f8c6414..778fba699 100644 --- a/src/AttributeSystem/BaseAttribute.cs +++ b/src/AttributeSystem/BaseAttribute.cs @@ -38,6 +38,9 @@ public virtual AttributeDefinition Definition /// public AggregateType AggregateType { get; } + /// + public byte Stage { get; } + /// public override string ToString() { diff --git a/src/AttributeSystem/CombinedElement.cs b/src/AttributeSystem/CombinedElement.cs index 650c14a1d..2506336c4 100644 --- a/src/AttributeSystem/CombinedElement.cs +++ b/src/AttributeSystem/CombinedElement.cs @@ -40,9 +40,12 @@ public CombinedElement(IElement element1, IElement element2) /// public AggregateType AggregateType => this._element1.AggregateType; + /// + public byte Stage => this._element1.Stage; + /// public override string ToString() { - return $"{this.Value} ({this.AggregateType})"; + return $"{this.Value} ({this.AggregateType}) @{this.Stage}"; } } \ No newline at end of file diff --git a/src/AttributeSystem/ComposableAttribute.cs b/src/AttributeSystem/ComposableAttribute.cs index 405020505..af41c13d4 100644 --- a/src/AttributeSystem/ComposableAttribute.cs +++ b/src/AttributeSystem/ComposableAttribute.cs @@ -58,26 +58,34 @@ private float GetAndCacheValue() return 0; } - var rawValues = this.Elements.Where(e => e.AggregateType == AggregateType.AddRaw).Sum(e => e.Value); - var multiValues = this.Elements.Where(e => e.AggregateType == AggregateType.Multiplicate).Select(e => e.Value).Concat(Enumerable.Repeat(1.0F, 1)).Aggregate((a, b) => a * b); - var finalValues = this.Elements.Where(e => e.AggregateType == AggregateType.AddFinal).Sum(e => e.Value); - var maxValues = this.Elements.Where(e => e.AggregateType == AggregateType.Maximum).MaxBy(e => e.Value)?.Value ?? 0; - rawValues += maxValues; - - if (multiValues == 0 && this.Elements.All(e => e.AggregateType != AggregateType.Multiplicate)) - { - multiValues = 1; - } - else if (rawValues == 0 && multiValues != 0 && this.Elements.All(e => e.AggregateType != AggregateType.AddRaw)) - { - rawValues = 1; - } - else + var highestStage = this._elementList.Max(e => e.Stage); + float newValue = 0; + for (int i = 0; i <= highestStage; i++) { - // nothing to do + var stageElements = this._elementList.Where(e => e.Stage == i); + + var rawValues = stageElements.Where(e => e.AggregateType == AggregateType.AddRaw).Sum(e => e.Value); + var multiValues = stageElements.Where(e => e.AggregateType == AggregateType.Multiplicate).Select(e => e.Value).Concat(Enumerable.Repeat(1.0F, 1)).Aggregate((a, b) => a * b); + var finalValues = stageElements.Where(e => e.AggregateType == AggregateType.AddFinal).Sum(e => e.Value); + var maxValues = stageElements.Where(e => e.AggregateType == AggregateType.Maximum).MaxBy(e => e.Value)?.Value ?? 0; + rawValues += maxValues; + + if (multiValues == 0 && stageElements.All(e => e.AggregateType != AggregateType.Multiplicate)) + { + multiValues = 1; + } + else if (newValue + rawValues == 0 && multiValues != 0 && stageElements.All(e => e.AggregateType == AggregateType.Multiplicate)) + { + rawValues = 1; + } + else + { + // nothing to do + } + + newValue = ((newValue + rawValues) * multiValues) + finalValues; } - var newValue = (rawValues * multiValues) + finalValues; if (this.Definition.MaximumValue.HasValue) { newValue = Math.Min(this.Definition.MaximumValue.Value, newValue); diff --git a/src/AttributeSystem/ConstValueAttribute.cs b/src/AttributeSystem/ConstValueAttribute.cs index 038d864a5..e417cecd8 100644 --- a/src/AttributeSystem/ConstValueAttribute.cs +++ b/src/AttributeSystem/ConstValueAttribute.cs @@ -16,10 +16,14 @@ public class ConstValueAttribute : IAttribute /// /// The value. /// The definition. - public ConstValueAttribute(float value, AttributeDefinition definition) + /// The type of the aggregate on the . + /// The calculation stage on the . + public ConstValueAttribute(float value, AttributeDefinition definition, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { this.Value = value; this._definition = definition; + this.AggregateType = aggregateType; + this.Stage = stage; } /// @@ -57,11 +61,14 @@ public virtual AttributeDefinition Definition public float Value { get; protected set; } /// - public AggregateType AggregateType => AggregateType.AddRaw; + public AggregateType AggregateType { get; protected set; } + + /// + public byte Stage { get; protected set; } /// public override string ToString() { - return $"{this.Definition.Designation}: {this.Value}"; + return $"{this.Definition.Designation}: {this.Value} ({this.AggregateType}) @{this.Stage}"; } } \ No newline at end of file diff --git a/src/AttributeSystem/ConstantElement.cs b/src/AttributeSystem/ConstantElement.cs index 022d0a59a..f16c2b839 100644 --- a/src/AttributeSystem/ConstantElement.cs +++ b/src/AttributeSystem/ConstantElement.cs @@ -14,10 +14,12 @@ public class ConstantElement : IElement /// /// The constant value. /// Type of the aggregate. - public ConstantElement(float value, AggregateType aggregateType = AggregateType.AddRaw) + /// The calculation stage. + public ConstantElement(float value, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { this.Value = value; this.AggregateType = aggregateType; + this.Stage = stage; } /// @@ -42,9 +44,12 @@ public event EventHandler? ValueChanged /// public AggregateType AggregateType { get; } + /// + public byte Stage { get; } + /// public override string ToString() { - return $"{this.Value} ({this.AggregateType})"; + return $"{this.Value} ({this.AggregateType}) @{this.Stage}"; } } \ No newline at end of file diff --git a/src/AttributeSystem/Extensions.cs b/src/AttributeSystem/Extensions.cs index d6ce87ba0..3e8ec843f 100644 --- a/src/AttributeSystem/Extensions.cs +++ b/src/AttributeSystem/Extensions.cs @@ -22,6 +22,8 @@ public static string AsString(this InputOperator inputOperator) InputOperator.Multiply => "*", InputOperator.Exponentiate => "^", InputOperator.ExponentiateByAttribute => "^", + InputOperator.Minimum => "", + InputOperator.Maximum => "", _ => string.Empty, }; } diff --git a/src/AttributeSystem/IElement.cs b/src/AttributeSystem/IElement.cs index 6e3022b77..ed7cdb55e 100644 --- a/src/AttributeSystem/IElement.cs +++ b/src/AttributeSystem/IElement.cs @@ -23,4 +23,12 @@ public interface IElement /// Gets the type of the aggregate. /// AggregateType AggregateType { get; } + + /// + /// Gets the stage at which the element value is calculated when part of a , if any. + /// + /// Useful for attributes which have several rounds of addition and multiplication elements, like the min/max base type damages. + /// For example, (a * b + c) * d + e would be a two-stage calculation, with a, b, c comprising the first stage, and d, e the second. + /// In such a case a represents an value; b and d an values; c and e an values. + byte Stage { get; } } \ No newline at end of file diff --git a/src/AttributeSystem/SimpleElement.cs b/src/AttributeSystem/SimpleElement.cs index 2a3dc1692..93a76da57 100644 --- a/src/AttributeSystem/SimpleElement.cs +++ b/src/AttributeSystem/SimpleElement.cs @@ -11,6 +11,7 @@ public class SimpleElement : IElement { private float _value; private AggregateType _aggregateType; + private byte _stage; /// /// Initializes a new instance of the class. @@ -24,10 +25,12 @@ public SimpleElement() /// /// The value. /// Type of the aggregate. - public SimpleElement(float value, AggregateType aggregateType) + /// The calculation stage. + public SimpleElement(float value, AggregateType aggregateType, byte stage = 0) { this._value = value; this._aggregateType = aggregateType; + this._stage = stage; } /// @@ -63,10 +66,25 @@ public AggregateType AggregateType } } + /// + public byte Stage + { + get => this._stage; + + set + { + if (this._stage != value) + { + this._stage = value; + this.RaiseValueChanged(); + } + } + } + /// public override string ToString() { - return $"{this.Value} ({this.AggregateType})"; + return $"{this.Value} ({this.AggregateType}) @{this.Stage}"; } /// diff --git a/src/DataModel/Attributes/PowerUpDefinition.cs b/src/DataModel/Attributes/PowerUpDefinition.cs index dcdcd4536..771f3a502 100644 --- a/src/DataModel/Attributes/PowerUpDefinition.cs +++ b/src/DataModel/Attributes/PowerUpDefinition.cs @@ -9,7 +9,7 @@ namespace MUnique.OpenMU.DataModel.Attributes; using MUnique.OpenMU.AttributeSystem; /// -/// The power up definition which describes the boost of an target attribute. +/// The power up definition which describes the boost of a target attribute. /// [Cloneable] public partial class PowerUpDefinition diff --git a/src/DataModel/Configuration/Items/ItemBasePowerUpDefinition.cs b/src/DataModel/Configuration/Items/ItemBasePowerUpDefinition.cs index edab4030e..31dae944b 100644 --- a/src/DataModel/Configuration/Items/ItemBasePowerUpDefinition.cs +++ b/src/DataModel/Configuration/Items/ItemBasePowerUpDefinition.cs @@ -16,6 +16,7 @@ public partial class ItemBasePowerUpDefinition private ConstantElement? _baseValueElement; private float _baseValue; private AggregateType _aggregateType; + private byte _stage; /// /// Gets or sets the target attribute. @@ -26,7 +27,7 @@ public partial class ItemBasePowerUpDefinition /// Gets the base value. /// [Transient] - public ConstantElement BaseValueElement => this._baseValueElement ??= new ConstantElement(this.BaseValue, this.AggregateType); + public ConstantElement BaseValueElement => this._baseValueElement ??= new ConstantElement(this.BaseValue, this.AggregateType, this.Stage); /// /// Gets or sets the bonus per level. @@ -59,6 +60,19 @@ public AggregateType AggregateType } } + /// + /// Gets or sets the calculation stage. + /// + public byte Stage + { + get => this._stage; + set + { + this._stage = value; + this._baseValueElement = null; + } + } + /// public override string ToString() { diff --git a/src/DataModel/Configuration/Items/ItemOptionTypes.cs b/src/DataModel/Configuration/Items/ItemOptionTypes.cs index e21339a5b..15c166d80 100644 --- a/src/DataModel/Configuration/Items/ItemOptionTypes.cs +++ b/src/DataModel/Configuration/Items/ItemOptionTypes.cs @@ -76,4 +76,10 @@ public static class ItemOptionTypes /// /// Applies only to the fenrir pet. public static ItemOptionType GoldFenrir { get; } = new () { Name = "Gold Fenrir Option", Id = new Guid("{78E6DB0B-AC53-454C-956F-CD2B5467856E}"), IsVisible = true }; + + /// + /// Gets the dark horse option type. + /// + /// Applies only to the dark horse pet. + public static ItemOptionType DarkHorse { get; } = new() { Name = "Dark Horse Option", Id = new Guid("{D2295C44-E458-40F8-8555-87CFD9626616}"), IsVisible = true }; } \ No newline at end of file diff --git a/src/DataModel/Configuration/MagicEffectDefinition.cs b/src/DataModel/Configuration/MagicEffectDefinition.cs index f3a9e9501..2db33a8cb 100644 --- a/src/DataModel/Configuration/MagicEffectDefinition.cs +++ b/src/DataModel/Configuration/MagicEffectDefinition.cs @@ -8,7 +8,7 @@ namespace MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.DataModel.Attributes; /// -/// Magic Effect Definition. It can be an effect from an consumed item, or by a buff. +/// Magic Effect Definition. It can be an effect from a consumed item, or by a buff or skill. /// [Cloneable] public partial class MagicEffectDefinition diff --git a/src/DataModel/Configuration/MasterSkillDefinition.cs b/src/DataModel/Configuration/MasterSkillDefinition.cs index 9984e075a..d4af0b21f 100644 --- a/src/DataModel/Configuration/MasterSkillDefinition.cs +++ b/src/DataModel/Configuration/MasterSkillDefinition.cs @@ -29,7 +29,7 @@ public partial class MasterSkillDefinition /// /// Gets or sets the rank. - /// The rang determines on which level the skill is located. + /// The rank determines on which level the skill is located. /// A skill at a higher rank can be learned, if there is at least /// one skill of the same tree root at the direct rank below, /// with a level same or greater than 10. @@ -84,6 +84,11 @@ public partial class MasterSkillDefinition /// public virtual Skill? ReplacedSkill { get; set; } + /// + /// Gets or sets a value indicating whether the applies to the duration of the . + /// + public bool ExtendsDuration { get; set; } + /// public override string ToString() { diff --git a/src/DataModel/Configuration/Skill.cs b/src/DataModel/Configuration/Skill.cs index 6c1aa63b2..1723c48bf 100644 --- a/src/DataModel/Configuration/Skill.cs +++ b/src/DataModel/Configuration/Skill.cs @@ -47,6 +47,32 @@ public enum DamageType /// All damage types. /// All = 5, + + /// + /// The electric spike (DL) skill damage type. + /// + ElectricSpike = 6, + + /// + /// The dark horse's earthshake skill damage type. + /// + Earthshake = 7, + + /// + /// The chaotic diseier (DL) skill damage type. + /// + ChaoticDiseier = 8, + + /// + /// The generic dark lord offensive skill damage type. + /// + /// Any DL skill other than electric spike, chaotic diseier, and earthshake. + DarkLordGenericSkill = 9, + + /// + /// The multishot (Elf) skill damage type. + /// + MultiShot = 10, } /// @@ -55,7 +81,7 @@ public enum DamageType public enum SkillType { /// - /// The skill hit its target directly. + /// The skill hits its target directly. /// DirectHit = 0, @@ -65,7 +91,7 @@ public enum SkillType CastleSiegeSpecial = 1, /// - /// Same as but only applyable during castle siege event. + /// Same as but only applicable during castle siege event. /// CastleSiegeSkill = 2, diff --git a/src/GameLogic/AttackableExtensions.cs b/src/GameLogic/AttackableExtensions.cs index 70226e434..d40857c48 100644 --- a/src/GameLogic/AttackableExtensions.cs +++ b/src/GameLogic/AttackableExtensions.cs @@ -6,10 +6,11 @@ namespace MUnique.OpenMU.GameLogic; using MUnique.OpenMU.AttributeSystem; using MUnique.OpenMU.DataModel.Attributes; +using MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.DataModel.Configuration.Items; using MUnique.OpenMU.GameLogic.Attributes; using MUnique.OpenMU.GameLogic.NPC; -using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.GameLogic.Pet; using MUnique.OpenMU.GameLogic.Views.World; using MUnique.OpenMU.Pathfinding; @@ -43,80 +44,237 @@ public static async ValueTask CalculateDamageAsync(this IAttacker attac return new HitInfo(0, 0, DamageAttributes.Undefined); } + Player? attackerPlayer = attacker is AttackerSurrogate surrogate ? surrogate.Owner : (attacker is Player player ? player : null); + bool isPvp = attackerPlayer is not null && defender is Player; + bool isClassicPvp = isPvp && defender.Attributes[Stats.MaximumShield] > 0; + bool isClassicPvpDuel = isClassicPvp && attackerPlayer!.DuelRoom?.Opponent == defender; + var classicPvpDuelDmgDec = isClassicPvpDuel ? 0.6 : 1; + DamageAttributes attributes = DamageAttributes.Undefined; bool isCriticalHit = Rand.NextRandomBool(attacker.Attributes[Stats.CriticalDamageChance]); bool isExcellentHit = Rand.NextRandomBool(attacker.Attributes[Stats.ExcellentDamageChance]); bool isIgnoringDefense = Rand.NextRandomBool(attacker.Attributes[Stats.DefenseIgnoreChance]); - attacker.GetBaseDmg(skill, out int baseMinDamage, out int baseMaxDamage); - int dmg; - if (isExcellentHit) + + var defense = 0; + if (isIgnoringDefense) { - dmg = (int)(baseMaxDamage * 1.2); - attributes |= DamageAttributes.Excellent; + attributes |= DamageAttributes.IgnoreDefense; } - else if (isCriticalHit) + else { - dmg = baseMaxDamage + (int)attacker.Attributes[Stats.CriticalDamageBonus]; - attributes |= DamageAttributes.Critical; + var defenseAttribute = defender.GetDefenseAttribute(attacker); + defense = (int)defender.Attributes[defenseAttribute]; } - else if (baseMaxDamage <= baseMinDamage) + + attacker.GetBaseDmg(skill, out int baseMinDamage, out int baseMaxDamage, out DamageType damageType); + int dmg; + if (damageType == DamageType.Physical) { - dmg = baseMinDamage; + if (isExcellentHit) + { + dmg = (int)((baseMaxDamage * 1.2) + attacker.Attributes[Stats.ExcellentDamageBonus]); + dmg += (int)(attacker.Attributes[Stats.CriticalDamageBonus] + attacker.Attributes[Stats.BerserkerMaxPhysDmgBonus]); + attributes |= DamageAttributes.Excellent; + } + else if (isCriticalHit) + { + dmg = baseMaxDamage + (int)(attacker.Attributes[Stats.CriticalDamageBonus] + attacker.Attributes[Stats.BerserkerMaxPhysDmgBonus]); + attributes |= DamageAttributes.Critical; + } + else + { + baseMinDamage += (int)attacker.Attributes[Stats.BerserkerMinPhysDmgBonus]; + baseMaxDamage += (int)attacker.Attributes[Stats.BerserkerMaxPhysDmgBonus]; + + if (baseMaxDamage <= baseMinDamage) + { + dmg = baseMinDamage; + } + else + { + dmg = Rand.NextInt(baseMinDamage, baseMaxDamage); + } + } + + if (attacker.Attributes[Stats.HasDoubleWield] > 0) + { + // double wield => 110% dmg (55% + 55%) + dmg += dmg; + /* There is an ancient set option critical damage subtraction here*/ + } + + dmg = (int)((dmg * classicPvpDuelDmgDec) - defense); + dmg += GetMasterSkillTreePhysicalPassiveDamageBonus(attacker, true); + + if (attacker.Attributes[Stats.IsTwoHandedWeaponEquipped] > 0) + { + dmg += (int)(dmg * attacker.Attributes[Stats.TwoHandedWeaponDamageIncrease]); + } + + if (attacker is AttackerSurrogate) + { + dmg += (int)attacker.Attributes[Stats.RavenBonusDamage]; + + if (attributes is not (DamageAttributes.Excellent or DamageAttributes.Critical)) + { + dmg = (int)(dmg / 1.5); + } + } } else { - dmg = Rand.NextInt(baseMinDamage, baseMaxDamage); + // Wizardry, Curse, and Fenrir + if (damageType == DamageType.Fenrir) + { + classicPvpDuelDmgDec = 1; + } + + if (isExcellentHit) + { + dmg = (int)((baseMaxDamage * classicPvpDuelDmgDec) - defense); + dmg = (int)((dmg * 1.2) + attacker.Attributes[Stats.ExcellentDamageBonus]); + attributes |= DamageAttributes.Excellent; + } + else if (isCriticalHit) + { + dmg = (int)((baseMaxDamage * classicPvpDuelDmgDec) - defense); + dmg += (int)attacker.Attributes[Stats.CriticalDamageBonus]; + attributes |= DamageAttributes.Critical; + } + else + { + if (baseMaxDamage <= baseMinDamage) + { + dmg = baseMinDamage; + } + else + { + dmg = Rand.NextInt(baseMinDamage, baseMaxDamage); + } + + dmg = (int)((dmg * classicPvpDuelDmgDec) - defense); + } } - if (!isIgnoringDefense) + dmg += (int)attacker.Attributes[Stats.GreaterDamageBonus]; + + /*Scroll of Wrath/Wizardry and Remedy of Love go here (but for now they don't exist)*/ + + if (damageType == DamageType.Wizardry || damageType == DamageType.Curse) { - var defenseAttribute = defender.GetDefenseAttribute(attacker); - var defense = (int)defender.Attributes[defenseAttribute]; - dmg -= defense; + dmg += (int)(dmg * attacker.Attributes[Stats.BerserkerProficiencyMultiplier]); + } + else if (damageType == DamageType.Physical) + { + dmg -= (int)(dmg * attacker.Attributes[Stats.WeaknessPhysDmgDecrement]); // check if it's a mob attacking + dmg += GetMasterSkillTreePhysicalPassiveDamageBonus(attacker, false); } else { - attributes |= DamageAttributes.IgnoreDefense; + // nothing to do } - dmg = Math.Max(dmg, 0); + /*Scroll of Battle (crit dmg)/Strengthener (exc dmg) go here (but for now they don't exist)*/ + + if (!isPvp && defender.Overrates(attacker)) + { + dmg = (int)(dmg * 0.3); + } + + dmg -= (int)(dmg * defender.Attributes[Stats.ArmorDamageDecrease]); + + var attackerLevel = attacker is Player ? attacker.Attributes[Stats.TotalLevel] : + attacker is AttackerSurrogate ? attackerPlayer!.Attributes![Stats.Level] : attacker.Attributes[Stats.Level]; + var minLevelDmg = Math.Max(1, (int)attackerLevel / 10); + if (dmg < minLevelDmg) + { + dmg = minLevelDmg; + } + + dmg -= (int)(dmg * defender.Attributes[Stats.ShieldSkillReceiveDecrement]); + + // dmg to defender's pet goes here (SpriteDamage(lpTargetObj, AttackDamage)) + // self dmg effects from imp go here + dmg += (int)(dmg * attacker.Attributes[Stats.ImpAttackDamageIncrease]); + dmg -= (int)(dmg * defender.Attributes[Stats.GuardianReceiveDecrement]); + + dmg += (int)attacker.Attributes[Stats.PandaRingDamageBonus]; dmg = (int)(dmg * defender.Attributes[Stats.DamageReceiveDecrement]); dmg = (int)(dmg * attacker.Attributes[Stats.AttackDamageIncrease]); if (skill != null) { - dmg += (int)attacker.Attributes[Stats.SkillDamageBonus]; - dmg = (int)(dmg * attacker.Attributes[Stats.SkillMultiplier]); + ApplySkillMultipliersOrLateStageBonus(attacker, defender, skill, ref dmg, damageFactor); + } + else if (attacker.Attributes[Stats.IsDinorantEquipped] > 0) + { + dmg = (int)(dmg * 1.3); + } + else + { + // Nothing to do } - if (attacker.Attributes[Stats.IsTwoHandedWeaponEquipped] > 0) + var soulBarrierManaToll = defender.Attributes[Stats.SoulBarrierManaTollPerHit]; + if (soulBarrierManaToll > 0 && defender.Attributes[Stats.CurrentMana] > soulBarrierManaToll) { - dmg = (int)(dmg * attacker.Attributes[Stats.TwoHandedWeaponDamageIncrease]); + defender.Attributes[Stats.CurrentMana] -= soulBarrierManaToll; + dmg -= (int)(dmg * defender.Attributes[Stats.SoulBarrierReceiveDecrement]); } - if (attacker is Player && defender is Player) + dmg += (int)attacker.Attributes[Stats.FinalDamageBonus]; + + if (isPvp && attacker is not AttackerSurrogate) { dmg += (int)attacker.Attributes[Stats.FinalDamageIncreasePvp]; + + if (attackerPlayer!.CurrentMiniGame?.Definition.Type == MiniGameType.ChaosCastle) + { + // In Chaos Castle damage is halved (except for raven) + dmg /= 2; + } } - if (isCombo) + /* CS Castle Gates and Satus PvM Damage & item durability reductions go here*/ + + dmg += (int)(dmg * attacker.Attributes[Stats.InfinityArrowStrMultiplier]); + + dmg += (int)(dmg * attacker.Attributes[Stats.FenrirAttackDamageIncrease]); + dmg -= (int)(dmg * defender.Attributes[Stats.FenrirDamageReceiveDecrement]); + + /* If is Fenrir skill attack, there is a strong reduction of the defender's item durability here */ + + if (isPvp) { - dmg += (int)attacker.Attributes[Stats.ComboBonus]; - attributes |= DamageAttributes.Combo; + dmg += GetMasterSkillTreeMasteryPvpDamageBonus(attacker); } - bool isDoubleDamage = Rand.NextRandomBool(attacker.Attributes[Stats.DoubleDamageChance]); - if (isDoubleDamage) + if (dmg > 0) { - dmg *= 2; - attributes |= DamageAttributes.Double; - } + // Ice arrow magic effect duration is reduced by 1s for every successful hit (dmg >0) + // Sleep magic effect is canceled for successful hit (dmg > 0) + if (isCombo) + { + dmg += (int)attacker.Attributes[Stats.ComboBonus]; + attributes |= DamageAttributes.Combo; + } - dmg = (int)(dmg * damageFactor); + bool isDoubleDamage = Rand.NextRandomBool(attacker.Attributes[Stats.DoubleDamageChance]); + if (isDoubleDamage) + { + dmg *= 2; + attributes |= DamageAttributes.Double; + } + + if (isClassicPvp && attackerPlayer!.CurrentMiniGame?.Definition.Type == MiniGameType.ChaosCastle) + { + // Further halve damage in Chaos Castle for classic PvP + dmg /= 2; + } + } - var minimumDamage = attacker.Attributes[Stats.Level] / 10; - return defender.GetHitInfo(Math.Max((uint)dmg, (uint)minimumDamage), attributes, attacker); + return defender.GetHitInfo((uint)dmg, attributes, attacker); } /// @@ -428,7 +586,7 @@ private static float GetHitChanceTo(this IAttacker attacker, IAttackable defende private static AttributeDefinition GetDefenseAttribute(this IAttackable defender, IAttacker attacker) { - if (attacker is Player && defender is Player) + if (attacker is Player or AttackerSurrogate && defender is Player) { return Stats.DefensePvp; } @@ -436,6 +594,11 @@ private static AttributeDefinition GetDefenseAttribute(this IAttackable defender return Stats.DefensePvm; } + private static bool Overrates(this IAttackable defender, IAttacker attacker) + { + return defender.Attributes[Stats.DefenseRatePvm] > attacker.Attributes[Stats.AttackRatePvm]; + } + private static int GetDamage(this SkillEntry skill) { skill.ThrowNotInitializedProperty(skill.Skill is null, nameof(skill.Skill)); @@ -456,70 +619,135 @@ private static int GetDamage(this SkillEntry skill) /// Skill which is used. /// Minimum base damage. /// Maximum base damage. - private static void GetBaseDmg(this IAttacker attacker, SkillEntry? skill, out int minimumBaseDamage, out int maximumBaseDamage) + /// The damage type. + private static void GetBaseDmg(this IAttacker attacker, SkillEntry? skill, out int minimumBaseDamage, out int maximumBaseDamage, out DamageType damageType) { + minimumBaseDamage = 0; + maximumBaseDamage = 0; + var skillMinimumDamage = 0; + var skillMaximumDamage = 0; var attackerStats = attacker.Attributes; - minimumBaseDamage = (int)(attackerStats[Stats.BaseDamageBonus] + attackerStats[Stats.BaseMinDamageBonus]); - maximumBaseDamage = (int)(attackerStats[Stats.BaseDamageBonus] + attackerStats[Stats.BaseMaxDamageBonus]); + bool isSummonerSkill = false; - DamageType damageType = DamageType.Physical; + damageType = DamageType.Physical; if (skill?.Skill != null) { damageType = skill.Skill.DamageType; + isSummonerSkill = attackerStats[Stats.MinimumCurseBaseDmg] > 0 && damageType != DamageType.Fenrir; var skillDamage = skill.GetDamage(); - minimumBaseDamage += skillDamage; - maximumBaseDamage += skillDamage + (skillDamage / 2); + skillMinimumDamage += skillDamage; + skillMaximumDamage += skillDamage + (skillDamage / 2); if (skill.Skill.SkillType == SkillType.Nova) { var novaDamage = (int)(attackerStats[Stats.NovaBonusDamage] + attackerStats[Stats.NovaStageDamage]); - minimumBaseDamage += novaDamage; - maximumBaseDamage += novaDamage; + skillMinimumDamage += novaDamage; + skillMaximumDamage += novaDamage; + } + + if (!isSummonerSkill && damageType != DamageType.Fenrir) + { + // For Summoner, the skill bonus gets added last + skillMinimumDamage += (int)attackerStats[Stats.SkillDamageBonus]; + skillMaximumDamage += (int)attackerStats[Stats.SkillDamageBonus]; + } + + switch (damageType) + { + case DamageType.ElectricSpike: + var nearbyPartyMembers = attacker.Party?.PartyList.Where(p => p == attacker || p.Observers.Contains((IWorldObserver)attacker)).Count() ?? 0; + skillMinimumDamage += (int)attackerStats[Stats.ElectricSpikeBonusDmg] + (nearbyPartyMembers * 50); + skillMaximumDamage += (int)attackerStats[Stats.ElectricSpikeBonusDmg] + (nearbyPartyMembers * 50); + damageType = DamageType.Physical; + break; + case DamageType.Earthshake: + skillMinimumDamage += (int)attackerStats[Stats.EarthshakeBonusDmg]; + skillMaximumDamage += (int)attackerStats[Stats.EarthshakeBonusDmg]; + damageType = DamageType.Physical; + break; + case DamageType.ChaoticDiseier: + skillMinimumDamage += (int)attackerStats[Stats.ChaoticDiseierBonusDmg]; + skillMaximumDamage += (int)attackerStats[Stats.ChaoticDiseierBonusDmg]; + damageType = DamageType.Physical; + break; + case DamageType.DarkLordGenericSkill: + skillMinimumDamage += (int)attackerStats[Stats.DarkLordGenericSkillBonusDmg]; + skillMaximumDamage += (int)attackerStats[Stats.DarkLordGenericSkillBonusDmg]; + damageType = DamageType.Physical; + break; + case DamageType.MultiShot: + skillMinimumDamage = (int)(skillMinimumDamage * 0.8); + skillMaximumDamage = (int)(skillMaximumDamage * 0.8); + damageType = DamageType.Physical; + break; + + case DamageType.Physical: + if (attackerStats[Stats.HasDoubleWield] > 0) + { // Because double wield dmg will be doubled later, we only take half of the skill dmg here (the skill is from a single weapon) + skillMinimumDamage /= 2; + skillMaximumDamage /= 2; + } + + break; + + default: + // Nothing to do here + break; + } + } + + if (isSummonerSkill) + { + minimumBaseDamage += (int)(attackerStats[Stats.WizardryAndCurseDmgBonus] + attackerStats[Stats.MinWizardryAndCurseDmgBonus]); + maximumBaseDamage += (int)attackerStats[Stats.WizardryAndCurseDmgBonus]; + + if (damageType == DamageType.Wizardry) + { + minimumBaseDamage += (int)attackerStats[Stats.BerserkerMinWizDmgBonus]; + maximumBaseDamage += (int)attackerStats[Stats.BerserkerMaxWizDmgBonus]; + } + else + { + minimumBaseDamage += (int)attackerStats[Stats.BerserkerMinCurseDmgBonus]; + maximumBaseDamage += (int)attackerStats[Stats.BerserkerMaxCurseDmgBonus]; } } switch (damageType) { + // Common damage types case DamageType.Wizardry: - minimumBaseDamage = (int)((minimumBaseDamage + attackerStats[Stats.MinimumWizBaseDmg]) * attackerStats[Stats.WizardryAttackDamageIncrease]); - maximumBaseDamage = (int)((maximumBaseDamage + attackerStats[Stats.MaximumWizBaseDmg]) * attackerStats[Stats.WizardryAttackDamageIncrease]); - + minimumBaseDamage = (int)((minimumBaseDamage + attackerStats[Stats.MinimumWizBaseDmg] + skillMinimumDamage) * attackerStats[Stats.WizardryAttackDamageIncrease]); + maximumBaseDamage = (int)((maximumBaseDamage + attackerStats[Stats.MaximumWizBaseDmg] + skillMaximumDamage) * attackerStats[Stats.WizardryAttackDamageIncrease]); break; case DamageType.Curse: - minimumBaseDamage += (int)((minimumBaseDamage + attackerStats[Stats.MinimumCurseBaseDmg]) * attackerStats[Stats.CurseAttackDamageIncrease]); - maximumBaseDamage += (int)((maximumBaseDamage + attackerStats[Stats.MaximumCurseBaseDmg]) * attackerStats[Stats.CurseAttackDamageIncrease]); - + minimumBaseDamage = (int)((minimumBaseDamage + attackerStats[Stats.MinimumCurseBaseDmg] + skillMinimumDamage) * attackerStats[Stats.CurseAttackDamageIncrease]); + maximumBaseDamage = (int)((maximumBaseDamage + attackerStats[Stats.MaximumCurseBaseDmg] + skillMaximumDamage) * attackerStats[Stats.CurseAttackDamageIncrease]); break; case DamageType.Physical: - minimumBaseDamage += (int)attackerStats[Stats.MinimumPhysBaseDmg]; - maximumBaseDamage += (int)attackerStats[Stats.MaximumPhysBaseDmg]; - break; - case DamageType.All: - minimumBaseDamage += Math.Max( - Math.Max( - (int)(attackerStats[Stats.MinimumWizBaseDmg] * attackerStats[Stats.WizardryAttackDamageIncrease]), - (int)(attackerStats[Stats.MinimumCurseBaseDmg] * attackerStats[Stats.CurseAttackDamageIncrease])), - (int)attackerStats[Stats.MinimumPhysBaseDmg]); - maximumBaseDamage += Math.Max( - Math.Max( - (int)(attackerStats[Stats.MaximumWizBaseDmg] * attackerStats[Stats.WizardryAttackDamageIncrease]), - (int)(attackerStats[Stats.MaximumCurseBaseDmg] * attackerStats[Stats.CurseAttackDamageIncrease])), - (int)attackerStats[Stats.MaximumPhysBaseDmg]); + minimumBaseDamage = (int)attackerStats[Stats.MinimumPhysBaseDmg] + skillMinimumDamage; + maximumBaseDamage = (int)attackerStats[Stats.MaximumPhysBaseDmg] + skillMaximumDamage; break; case DamageType.Fenrir: - minimumBaseDamage += (int)attackerStats[Stats.FenrirBaseDmg]; - maximumBaseDamage += (int)attackerStats[Stats.FenrirBaseDmg]; + minimumBaseDamage = (int)attackerStats[Stats.FenrirBaseDmg] + skillMinimumDamage; + maximumBaseDamage = (int)attackerStats[Stats.FenrirBaseDmg] + skillMaximumDamage; break; default: // the skill has some other damage type defined which is not applicable to this calculation break; } + + if (isSummonerSkill) + { + minimumBaseDamage += (int)attackerStats[Stats.SkillDamageBonus]; + maximumBaseDamage += (int)attackerStats[Stats.SkillDamageBonus]; + } } /// - /// Applies the magic effect of the attackers skill to the target. + /// Applies the magic effect of the attacker's skill to the target. /// /// The target. /// The attacker. @@ -548,4 +776,260 @@ private static async ValueTask ApplyMagicEffectAsync(this IAttackable target, IA } } } + + private static int GetMasterSkillTreePhysicalPassiveDamageBonus(IAttacker attacker, bool preBuffsStage) + { + if (preBuffsStage) + { + if (attacker.Attributes[Stats.IsBowEquipped] > 0) + { + return (int)attacker.Attributes[Stats.BowStrBonusDamage]; + } + else if (attacker.Attributes[Stats.IsCrossBowEquipped] > 0) + { + return (int)attacker.Attributes[Stats.CrossBowStrBonusDamage]; + } + else if (attacker.Attributes[Stats.IsTwoHandedSwordEquipped] > 0) + { + return (int)attacker.Attributes[Stats.TwoHandedSwordStrBonusDamage]; + } + else + { + return 0; + } + } + else + { + int bonusDamage = 0; + + if (attacker.Attributes[Stats.IsSpearEquipped] > 0) // always two-handed + { + bonusDamage = (int)attacker.Attributes[Stats.SpearBonusDamage]; + } + else if (attacker.Attributes[Stats.IsScepterEquipped] > 0) // impossible to double wield + { + bonusDamage = (int)attacker.Attributes[Stats.ScepterStrBonusDamage]; + } + else if (attacker.Attributes[Stats.IsGloveWeaponEquipped] > 0) // impossible to double wield + { + bonusDamage = (int)attacker.Attributes[Stats.GloveWeaponBonusDamage]; + } + else + { + if (attacker.Attributes[Stats.IsOneHandedSwordEquipped] > 0) + { + bonusDamage = (int)attacker.Attributes[Stats.OneHandedSwordBonusDamage]; + } + + if (attacker.Attributes[Stats.IsMaceEquipped] > 0) + { + // In case of a double wield with different possible bonuses, take the average + bonusDamage = (int)(bonusDamage == 0 + ? attacker.Attributes[Stats.MaceBonusDamage] + : (bonusDamage + attacker.Attributes[Stats.MaceBonusDamage]) / 2); + } + } + + return bonusDamage + (int)attacker.Attributes[Stats.MasterSkillPhysBonusDmg]; + } + } + + private static int GetMasterSkillTreeMasteryPvpDamageBonus(IAttacker attacker) + { + if (attacker.Attributes[Stats.IsTwoHandedSwordEquipped] > 0) + { + return (int)attacker.Attributes[Stats.TwoHandedSwordMasteryBonusDamage]; + } + else if (attacker.Attributes[Stats.IsTwoHandedStaffEquipped] > 0) + { + return (int)attacker.Attributes[Stats.TwoHandedStaffMasteryBonusDamage]; + } + else if (attacker.Attributes[Stats.IsCrossBowEquipped] > 0) + { + return (int)attacker.Attributes[Stats.CrossBowMasteryBonusDamage]; + } + else if (attacker.Attributes[Stats.IsStickEquipped] > 0) + { + return (int)attacker.Attributes[Stats.StickMasteryBonusDamage]; + } + else if (attacker.Attributes[Stats.IsScepterEquipped] > 0) + { + return (int)attacker.Attributes[Stats.ScepterMasteryBonusDamage]; + } + else + { + return 0; + } + } + + private static int ApplySkillMultipliersOrLateStageBonus(IAttacker attacker, IAttackable defender, SkillEntry skill, ref int dmg, double damageFactor) + { + var skillMultiplier = attacker.Attributes[Stats.SkillMultiplier]; + + // Not all character's skills get multiplied (e.g., elf's TripleShot and MultiShot), so default case should be empty. + // Switch cases ordering kept close to source's for reference, with new season (NS) skills included. + switch (skill.Skill?.Number) + { + case 19: // FallingSlash + case 20: // Lunge + case 21: // Uppercut + case 22: // Cyclone + case 23: // Slash + if (attacker.Attributes[Stats.TotalLeadership] > 0 || attacker.Attributes[Stats.VitalitySkillMultiplier] > 0) + { + skillMultiplier = 2; + } + + dmg = (int)(dmg * skillMultiplier); + break; + case 41: // TwistingSlash + case 42: // RagefulBlow + case 43: // DeathStab + case 44: // CrescentMoonSlash (CS) + case 49: // FireBreath (Dino) + case 55: // FireSlash + case 57: // SpiralSlash (CS) + case 47: // Impale (mount & spear) + case 56: // PowerSlash + /* Elf */ + case 46: // Starfall (CS) + case 51: // IceArrow + case 52: // Penetration + /* DL */ + case 60: // Force + case 66: // ForceWave + case 61: // FireBurst + case 62: // Earthshake + case 65: // ElectricSpike + case 74: // FireBlast (CS) + case 78: // FireScream + /* DK & MG */ + case 232: // StrikeofDestruction + case 236: // FlameStrike + case 330: // TwistingSlashStreng + case 332: // TwistingSlashMastery + case 481: // TwistingSlashStrengthenerDuelMaster + case 326: // CycloneStrengthener + case 479: // CycloneStrengthenerDuelMaster + case 327: // SlashStrengthener + case 328: // FallingSlashStreng + case 329: // LungeStrengthener + case 337: // StrikeofDestrStr + case 340: // StrikeofDestrProf (NS) + case 343: // StrikeofDestrMast (NS) + /* Elf */ + case 416: // PenetrationStrengthener + case 424: // IceArrowStrengthener + /* DL */ + case 516: // EarthshakeMastery + case 514: // FireBurstMastery + case 509: // ForceWaveStreng + case 5090: // ForceWaveStreng Alt + case 512: // EarthshakeStreng + case 508: // FireBurstStreng + /* DK */ + case 336: // DeathStabStrengthener + case 339: // DeathStabProficiency (NS) + case 342: // DeathStabMastery (NS) + case 331: // RagefulBlowStreng + case 333: // RagefulBlowMastery + /* MG */ + case 490: // BloodAttackStrengthen + case 493: // FireSlashMastery (NS) + case 492: // FlameStrikeStrengthen (NS) + case 494: // FlameStrikeMastery (NS) + case 482: // PowerSlashStreng + /* DL */ + case 518: // FireScreamStren + case 520: // FireScreamMastery (NS) + /* DK */ + case 344: // BloodStorm (NS) + case 346: // BloodStormStrengthener (NS) + /* Elf */ + case 427: // PoisonArrow (NS) + case 434: // PoisonArrowStr (NS) + dmg = (int)(dmg * skillMultiplier); + break; + case 76: // PlasmaStorm (fenrir) + var levelBonus = Math.Max(0, attacker.Attributes[Stats.TotalLevel] - 300) / 5; + dmg = (int)(dmg * ((levelBonus / 100) + 2)); + break; + /* Summoner */ + case 215: // ChainLightning + case 455: // ChainLightningStr + dmg = (int)(dmg * damageFactor); + break; + /* DL */ + case 238: // ChaoticDiseier + case 523: // ChaoticDiseierStr (NS) + dmg = (int)(dmg * skillMultiplier / 1.25f); + break; + /* Selupan (Raklion boss) */ + case 250: + dmg = (int)(dmg * skillMultiplier); + break; + case 251: + skillMultiplier += 0.2f; + goto case 250; + case 252: + skillMultiplier += 0.3f; + goto case 250; + case 253: + skillMultiplier += 0.5f; + goto case 250; + /* RF */ + case 260: // KillingBlow + case 261: // BeastUppercut + case 262: // ChainDrive + case 269: // Charge (CS) + case 551: // KillingBlowStrengthener + case 554: // KillingBlowMastery + case 552: // BeastUppercutStrengthener + case 555: // BeastUppercutMastery + case 558: // ChainDriveStrengthener + case 562: // Chain drive mastery (NS) + dmg = (int)(dmg * attacker.Attributes[Stats.VitalitySkillMultiplier]); + break; + case 270: // PhoenixShot + dmg = (int)(dmg * (1.5 + attacker.Attributes[Stats.VitalitySkillMultiplier])); + break; + case 263: // DarkSide + case 559: // DarkSideStrengthener + case 563: // Dark side mastery (NS) + dmg = (int)(dmg * (0.5 + (attacker.Attributes[Stats.TotalAgility] / 800) + skillMultiplier)); + break; + case 264: // DragonRoar + case 560: // DragonRoarStrengthener + case 561: // Dragon roar mastery (NS) + dmg = (int)(dmg * skillMultiplier); + break; + case 265: // DragonSlasher + case 564: // Dragon slasher strengthener (NS) + case 566: // Dragon slasher mastery (NS) + if (defender is Player) + { + dmg = (int)(dmg * skillMultiplier); + } + else + { + dmg = (int)(((dmg * skillMultiplier) + 100) * 3); + } + + break; + /* Summoner's book skill bonuses */ + case 223: // Explosion223 (Samut) + dmg += (int)attacker.Attributes[Stats.ExplosionBonusDmg]; + break; + case 224: // Requiem (Neil) + dmg += (int)attacker.Attributes[Stats.RequiemBonusDmg]; + break; + case 225: // Pollution (Lagle) + dmg += (int)attacker.Attributes[Stats.PollutionBonusDmg]; + break; + default: + break; + } + + return dmg; + } } \ No newline at end of file diff --git a/src/GameLogic/Attributes/AttributeSystemExtensions.cs b/src/GameLogic/Attributes/AttributeSystemExtensions.cs index bb75c8116..ba612da9d 100644 --- a/src/GameLogic/Attributes/AttributeSystemExtensions.cs +++ b/src/GameLogic/Attributes/AttributeSystemExtensions.cs @@ -62,6 +62,7 @@ public static IElement CreateElement(this IAttributeSystem attributeSystem, Powe r.InputOperator) { AggregateType = result.AggregateType, + Stage = result.Stage, }) .Cast(); diff --git a/src/GameLogic/Attributes/PowerUpWrapper.cs b/src/GameLogic/Attributes/PowerUpWrapper.cs index 7e50e2b93..513f74a0c 100644 --- a/src/GameLogic/Attributes/PowerUpWrapper.cs +++ b/src/GameLogic/Attributes/PowerUpWrapper.cs @@ -44,6 +44,9 @@ public PowerUpWrapper(IElement element, AttributeDefinition targetAttribute, Att /// public AggregateType AggregateType => this._element.AggregateType; + /// + public byte Stage => this._element.Stage; + /// /// Creates elements by a . /// diff --git a/src/GameLogic/Attributes/Stats.cs b/src/GameLogic/Attributes/Stats.cs index 125fde185..0fad4f4d6 100644 --- a/src/GameLogic/Attributes/Stats.cs +++ b/src/GameLogic/Attributes/Stats.cs @@ -86,6 +86,11 @@ public class Stats /// public static AttributeDefinition TotalLeadershipRequirementValue { get; } = new(new Guid("E38A897E-ED6F-4C06-AE11-7CAA7EAEC5A9"), "Total Leadership Requirement Value", "The total leadership requirement value of an item, which is used to calculate the required total leadership of a character to equip an item. The required total leadership depends on the options, drop level and level of the item."); + /// + /// Gets the total strength and agility attribute definition. + /// + public static AttributeDefinition TotalStrengthAndAgility { get; } = new(new Guid("4DFA4E4A-D185-4BCE-952C-5E78A92DC4AF"), "Total Strength and Agility", string.Empty); + /// /// Gets the level attribute definition. /// @@ -116,6 +121,11 @@ public class Stats /// public static AttributeDefinition MasterExperienceRate { get; } = new(new Guid("E367A231-C8A4-4F92-B553-C665F98DB1FC"), "Master Experience Rate", string.Empty); + /// + /// Gets the level plus master level attribute definition. + /// + public static AttributeDefinition TotalLevel { get; } = new(new Guid("AAB627F1-9150-4B03-8C51-48E4348B4E7D"), "Total Level", "The level plus the master level of the character."); + /// /// Gets the reset quantity attribute definition. /// @@ -174,6 +184,8 @@ public class Stats /// /// Gets the attack rate PVM attribute definition. /// + /// Calculated in a single stage: + /// Stage 0: base attack rate from level and stats; ancient set option multiplier; MST PvM attack rate increase bonus as final value. public static AttributeDefinition AttackRatePvm { get; } = new(new Guid("1129442A-E1C7-4240-8866-B781C2838C25"), "Attack Rate (PvM)", string.Empty); /// @@ -191,36 +203,94 @@ public class Stats /// public static AttributeDefinition MaximumPhysBaseDmgByWeapon { get; } = new(new Guid("EC0D70BE-839C-4BAD-9FC5-1AD7438C75F8"), "Maximum Physical Base Damage By Weapon", string.Empty); + /// + /// Gets the minimum physical base DMG by right hand weapon attribute definition. + /// + /// Used to isolate RH weapon min damage for double weapon wield logic. + /// On a staff-sword (mixed) or double-staff wield (MG), the LH weapon alone dictates the "attack type": + /// LH: staff; RH: sword or staff => LH physical damage and rise (ene-MG). + /// LH: sword; RH: staff => LH physical damage (str-MG). + /// Other than these, it's a "true" double wield (two one-handed physical weapons) and both weapons' damage attributes count. + /// Summoner can also double weapon wield (stick and book), but books have no damage. + public static AttributeDefinition MinPhysBaseDmgByRightWeapon { get; } = new(new Guid("99F42E8D-2C03-4D23-94F8-F920DCF032B4"), "Minimum Physical Base Damage By Right Weapon", string.Empty); + + /// + /// Gets the maximum physical base DMG by right hand weapon attribute definition. + /// + /// Used to isolate RH weapon max damage for double weapon wield logic. Refer to for remarks. + public static AttributeDefinition MaxPhysBaseDmgByRightWeapon { get; } = new(new Guid("84F794AE-D7EB-4AC6-B56B-79D1E9FF3AF4"), "Maximum Physical Base Damage By Right Weapon", string.Empty); + /// /// Gets the minimum physical base DMG attribute definition. /// + /// The "resting" physical minimum base damage. Calculated in several stages: + /// Stage 0: stats; MST physical min, max bonuses; wing and weapon physical dmg options; wizard's ring, pet skeleton multipliers. + /// Stage 1: transformation rings' bonuses; demon pet multiplier. + /// Stage 2: JoH phys base, min, max dmg options; socket base, min, max dmg options; exc lvl/20 phys dmg opt; exc 2% phys dmg opt multiplier. + /// Stage 3: ancient set base, min, max dmg options; bolt/arrow or double wield dmg multipliers. + /// Stage 4: . public static AttributeDefinition MinimumPhysBaseDmg { get; } = new(new Guid("3E8D6A02-E973-4AE4-9DF3-CDDC3D3183B3"), "Minimum Physical Base Damage", string.Empty); /// /// Gets the maximum physical base DMG attribute definition. /// + /// The "resting" physical maximum base damage. Refer to for base DMG stage calculations breakdown. public static AttributeDefinition MaximumPhysBaseDmg { get; } = new(new Guid("8A918EA2-893A-48B2-A684-3E71526CA71F"), "Maximum Physical Base Damage", string.Empty); /// /// Gets the min and max physical base DMG attribute definition. /// + /// Includes the physical DMG item option from weapons and wings. public static AttributeDefinition PhysicalBaseDmg { get; } = new(new Guid("DD1E13E4-BFFD-45B5-9B91-9080710324B2"), "Physical Base Damage (min and max)", string.Empty); + /// + /// Gets the excellent option min and max wiz base DMG attribute definition. + /// + public static AttributeDefinition ExcellentPhysBaseDmg { get; } = new(new Guid("93B56B1F-983F-440F-9A62-EF99EEFCD7B0"), "Excellent Physical Base Damage (min and max)", string.Empty); + + /// + /// Gets the JoH option min and max physical base DMG attribute definition. + /// + public static AttributeDefinition HarmonyPhysBaseDmg { get; } = new(new Guid("6B7BC4C5-BD16-4E50-8AC1-DAA98F069A6B"), "Harmony Physical Base Damage (min and max)", string.Empty); + /// /// Gets the minimum wiz base DMG attribute definition. /// + /// The "resting" wizardry minimum base damage. Calculated in several stages: + /// Stage 0: stats; MST wizardry min, max, and "mastery" bonuses; wing and staff wizardry dmg options; wizard's ring, pet skeleton multipliers. + /// Stage 1: transformation rings' bonuses; demon pet multiplier. + /// Stage 2: JoH wiz base dmg option; socket base, min, max dmg options; exc lvl/20 wiz dmg opt; exc 2% wiz dmg opt multiplier. + /// Stage 3: ancient set wiz opt increase %. + /// Stage 4: ; MST one-handed staff/two-handed staff/stick strengthener bonus. public static AttributeDefinition MinimumWizBaseDmg { get; } = new(new Guid("65583A02-AB94-4A17-9B79-86ECC82DC835"), "Minimum Wizardry Base Damage", string.Empty); /// /// Gets the maximum wiz base DMG attribute definition. /// + /// The "resting" wizardry maximum base damage. Refer to for base DMG stage calculations breakdown. public static AttributeDefinition MaximumWizBaseDmg { get; } = new(new Guid("44B8236A-BF5B-4082-BA8B-5DEDA1458D33"), "Maximum Wizardry Base Damage", string.Empty); /// /// Gets the min and max wiz base DMG attribute definition. /// + /// Includes the wizardry DMG item option from weapons (staffs, swords, sticks) and wings, and MST Magic Mastery passive. public static AttributeDefinition WizardryBaseDmg { get; } = new(new Guid("7F4F3646-33A6-40AC-8DA6-29A0A0F46016"), "Wizardry Base Damage (min and max)", string.Empty); + /// + /// Gets the excellent option min and max wiz base DMG attribute definition. + /// + public static AttributeDefinition ExcellentWizBaseDmg { get; } = new(new Guid("C400B3EE-1F50-4684-A22E-3228374A5487"), "Excellent Wizardry Base Damage (min and max)", string.Empty); + + /// + /// Gets the JoH option min and max wiz base DMG attribute definition. + /// + public static AttributeDefinition HarmonyWizBaseDmg { get; } = new(new Guid("8DC69850-57A2-43F9-A78A-2BD2DEFE4B69"), "Harmony Wizardry Base Damage (min and max)", string.Empty); + + /// + /// Gets the ancient set option wizardry base DMG increase % attribute definition. + /// + public static AttributeDefinition AncientWizDmgIncrease { get; } = new(new Guid("23995CC0-19A0-4608-8995-DAECC33C643A"), "Ancient Wizardry Damage Increase", string.Empty); + /// /// Gets the staff rise percentage attribute definition. /// @@ -239,46 +309,91 @@ public class Stats /// /// Gets the minimum curse base DMG attribute definition. /// + /// The "resting" curse minimum base damage. Calculated in several stages: + /// Stage 0: stats; wing and book curse dmg options; pet skeleton multiplier. + /// Stage 1: transformation rings' bonuses; demon pet multiplier. + /// Stage 2: MST tome strengthener bonus. public static AttributeDefinition MinimumCurseBaseDmg { get; } = new(new Guid("B8AE2D6B-05CE-43A9-B2BB-3C32F288A043"), "Minimum Curse Base Damage", string.Empty); /// /// Gets the maximum curse base DMG attribute definition. /// + /// The "resting" curse maximum base damage. Refer to for base DMG stage calculations breakdown. public static AttributeDefinition MaximumCurseBaseDmg { get; } = new(new Guid("5E7B5B56-BB4D-4645-9593-836FE86E80EA"), "Maximum Curse Base Damage", string.Empty); + /// + /// Gets the the min and max curse base DMG attribute definition. + /// + /// Includes the curse DMG item option from weapons (books) and wings. + public static AttributeDefinition CurseBaseDmg { get; } = new(new Guid("60868001-6A67-408C-BFDB-320670A9A682"), "Curse Base Damage (min and max)", string.Empty); + + /// + /// Gets the the min wizardry and curse common MST DMG bonus attribute definition. + /// + public static AttributeDefinition MinWizardryAndCurseDmgBonus { get; } = new(new Guid("7E32A2B5-54F2-4D95-9968-9DE53100D3D4"), "Minimum Wizardry And Curse Base Damage Bonus (MST)", string.Empty); + + /// + /// Gets the the min and max wizardry and curse common MST DMG bonus attribute definition. + /// + public static AttributeDefinition WizardryAndCurseDmgBonus { get; } = new(new Guid("A4F57534-4185-450D-93B1-0CE4246FE2D3"), "Wizardry And Curse Base Damage Bonus (min and max, MST)", string.Empty); + /// /// Gets the attribute definition for the base damage of the fenrir pet. /// public static AttributeDefinition FenrirBaseDmg { get; } = new(new Guid("96F47E70-5C85-4A92-B224-944A9359240E"), "Fenrir Base Damage", string.Empty); /// - /// Gets the base damage bonus attribute definition. + /// Gets the consumable event items base damage (physical and wizardry) bonus attribute definition. + /// + /// So far includes Jack O'Lantern Wrath and Cherry Blossom Flower Petal. + public static AttributeDefinition BaseDamageBonus { get; } = new(new Guid("BB6F0151-EAB2-4A9D-BFE3-51E145F36C52"), "Base Damage Bonus", "A bonus value from special event consumables which gets added to min/max physical and wizardry damage values during the damage calculation."); + + /// + /// Gets the panda ring final damage bonus attribute definition. /// - public static AttributeDefinition BaseDamageBonus { get; } = new(new Guid("BB6F0151-EAB2-4A9D-BFE3-51E145F36C52"), "Base Damage Bonus", "A bonus value which gets added to all min/max damage values during the damage calculation"); + public static AttributeDefinition PandaRingDamageBonus { get; } = new(new Guid("7969421C-0F30-4991-BBB2-1CFEB8B151B2"), "Panda Ring Final Damage Bonus", string.Empty); /// - /// Gets the base min damage bonus attribute definition. + /// Gets the final damage (any type) bonus attribute definition. /// - public static AttributeDefinition BaseMinDamageBonus { get; } = new(new Guid("ACE8CC0A-3288-491C-A49F-4B754A18BA1F"), "Base Min Damage Bonus", "A bonus value which gets added to all min damage values during the damage calculation"); + /// So far includes the ancient set option. + public static AttributeDefinition FinalDamageBonus { get; } = new(new Guid("88316AEC-1D82-4103-BF09-CA6A3C0B177A"), "Late Damage Bonus", "A bonus value which gets added to the final damage value during the damage calculation."); /// - /// Gets the base max damage bonus attribute definition. + /// Gets the socket base damage (physical and wizardry) bonus attribute definition. /// - public static AttributeDefinition BaseMaxDamageBonus { get; } = new(new Guid("7C9E419B-63B0-4237-B799-B80418693A61"), "Base Max Damage Bonus", "A bonus value which gets added to all max damage values during the damage calculation"); + public static AttributeDefinition SocketBaseDmgBonus { get; } = new(new Guid("8A23559F-8339-4998-80CB-0B1345B47FBB"), "Socket Base Damage Bonus", "A bonus value which gets added to physical and wizardry base min/max damage values during the damage calculation."); + + /// + /// Gets the socket base min damage (physical and wizardry) bonus attribute definition. + /// + public static AttributeDefinition SocketBaseMinDmgBonus { get; } = new(new Guid("8C175E46-D614-495C-9990-EECD98547381"), "Socket Base Min Damage Bonus", "A bonus value which gets added to physical and wizardry base min damage values during the damage calculation."); + + /// + /// Gets the socket base max damage (physical and wizardry) bonus attribute definition. + /// + public static AttributeDefinition SocketBaseMaxDmgBonus { get; } = new(new Guid("51B4D505-DB02-412B-A69B-756C9DAA78FF"), "Socket Base Max Damage Bonus", "A bonus value which gets added to physical and wizardry base max damage values during the damage calculation."); /// /// Gets the skill multiplier attribute definition. /// public static AttributeDefinition SkillMultiplier { get; } = new(new Guid("D9FB3323-6DF5-48F7-8253-FDBB5EF82114"), "Skill Damage Multiplier", string.Empty); + /// + /// Gets the vitality skill multiplier (RF) attribute definition. + /// + public static AttributeDefinition VitalitySkillMultiplier { get; } = new(new Guid("5E987FB1-CECB-4703-B7C7-096AAB915672"), "Vitality Skill Damage Multiplier", string.Empty); + /// /// Gets the skill damage bonus attribute definition. /// + /// Does not apply to Fenrir's skill. Includes ancient set and JoH options. public static AttributeDefinition SkillDamageBonus { get; } = new(new Guid("B8B214B1-396B-4CA8-9A77-240AA70A989B"), "Skill Damage Bonus", "A bonus value which gets added to the damage calculation when the damage is calculated with a skill."); /// /// Gets the critical damage bonus attribute definition. /// + /// Includes ancient set, JoH, and socket options. public static AttributeDefinition CriticalDamageBonus { get; } = new(new Guid("33F53519-16F3-44C2-9D36-432C36329C78"), "Critical Damage Bonus", "A bonus value which gets added to the damage calculation when the damage is calculated and critical damage applies."); /// @@ -286,6 +401,11 @@ public class Stats /// public static AttributeDefinition ExcellentDamageBonus { get; } = new(new Guid("9CB8705A-398D-4158-BC60-D6ADBED36A28"), "Excellent Damage Bonus", "A bonus value which gets added to the damage calculation when the damage is calculated and excellent damage applies."); + /// + /// Gets the common attack speed attribute definition which adds to both and . + /// + public static AttributeDefinition AttackSpeedAny { get; } = new(new Guid("DA08473F-DF5B-444D-8651-9EDB65797922"), "Attack Speed Any", "The any attack speed which contributes to both attack speed and magic speed."); + /// /// Gets the attack speed attribute definition. /// @@ -300,23 +420,46 @@ public class Stats public static AttributeDefinition AttackSpeedByWeapon { get; } = new(new Guid("45EEEDEE-C76B-40E6-A0BC-2B493E10B140"), "Attack Speed by Weapons", string.Empty); /// - /// Gets the attribute which says, if two weapons are equipped. + /// Gets the attribute which says, if any two weapons are equipped (DK, MG, Sum, RF). /// + /// Used to average out the . public static AttributeDefinition AreTwoWeaponsEquipped { get; } = new(new Guid("56DA895D-BAFD-4A5C-9864-B17AB8369998"), "Are two weapons equipped", string.Empty) { MaximumValue = 1, }; /// - /// Gets the attribute which counts the equipped weapons. + /// Gets the attribute which counts the equipped weapons. Unlocks . /// public static AttributeDefinition EquippedWeaponCount { get; } = new(new Guid("15D6493F-549D-455F-9FFF-A0D589FD7DA2"), "Equipped Weapon Count", string.Empty); + /// + /// Gets the attribute which says if the player has a double wield (DK, MG, RF). + /// + /// This is different from the attribute, where two staffs can be equipped, for example. + /// For a double wield only physical attack type weapons are considered. + public static AttributeDefinition HasDoubleWield { get; } = new(new Guid("4AD0E3CA-526D-4DBF-AB65-87BEB7A1F080"), "Has Double Wield", "A double weapon wield grants a 10% increase in physical damage. Only DK, MG, and RF can double wield."); + + /// + /// Gets the double wield weapon count attribute. Unlocks . + /// + public static AttributeDefinition DoubleWieldWeaponCount { get; } = new(new Guid("84252905-3DAD-4E38-AE4D-C18FE2A99395"), "Double Wield Weapon Count", string.Empty); + /// /// Gets the magic speed attribute definition which is used for some skills. /// public static AttributeDefinition MagicSpeed { get; } = new(new Guid("AE32AA45-9C18-43B3-9F7B-648FD7F4B0AD"), "Magic Speed", string.Empty); + /// + /// Gets the excellent option wizardry damage 2% increase attribute definition>. + /// + public static AttributeDefinition ExcellentWizTwoPercentInc { get; } = new(new Guid("D9DBAA2C-BA56-4F7F-A516-8DE6354406FE"), "Excellent Wizardry Damage 2% Increase", string.Empty); + + /// + /// Gets the excellent option physical damage 2% increase attribute definition>. + /// + public static AttributeDefinition ExcellentPhysTwoPercentInc { get; } = new(new Guid("104B4DAA-C507-4CBB-AF38-D53DDBB4817E"), "Excellent Physical Damage 2% Increase", string.Empty); + /// /// Gets the walk speed attribute definition. /// @@ -325,17 +468,33 @@ public class Stats /// /// Gets the attack damage increase attribute definition. /// + /// Includes wings, and dinorant. public static AttributeDefinition AttackDamageIncrease { get; } = new(new Guid("0765CCD2-C70A-4338-BF49-0D652364C223"), "Attack Damage Increase Multiplier", string.Empty); + /// + /// Gets the imp pet attack damage increase attribute definition. + /// + public static AttributeDefinition ImpAttackDamageIncrease { get; } = new(new Guid("D548B040-A4F2-4B65-A55D-5F46849994F1"), "Imp Attack Damage Increase", "The imp attack damage multiplier which is multiplied with the final damage and added to it."); + + /// + /// Gets the fenrir pet attack damage increase attribute definition. + /// + public static AttributeDefinition FenrirAttackDamageIncrease { get; } = new(new Guid("46437116-2974-4595-A15A-DD9FC6CC673E"), "Fenrir Attack Damage Increase", "The fenrir attack damage multiplier which is multiplied with the final damage and added to it."); + + /// + /// Gets the fenrir pet damage receive decrement attribute definition. + /// + public static AttributeDefinition FenrirDamageReceiveDecrement { get; } = new(new Guid("1204AF41-706E-47CE-8D03-71F1F80F0B05"), "Fenrir Damage Receive Decrement", "The fenrir receive damage multiplier which is multiplied with the final damage and subtracted from it."); + /// /// Gets the wizardry attack damage increase attribute definition. /// public static AttributeDefinition WizardryAttackDamageIncrease { get; } = new(new Guid("8F1CD5A5-3792-42FC-89B8-E6D50F997F4B"), "Wizardry Attack Damage Increase Multiplier", "The wizardry damage increase which is multiplied with the min/max wiz base damage and added to it."); /// - /// Gets the pet attack damage increase attribute definition. + /// Gets the raven attack damage increase attribute definition. /// - public static AttributeDefinition PetAttackDamageIncrease { get; } = new(new Guid("662467B2-CBCF-4347-9B39-A2BBEE04E6D7"), "Pet Attack Damage Increase Multiplier", "The pet damage increase which is multiplied with the min/max wiz base damage and added to it."); + public static AttributeDefinition RavenAttackDamageIncrease { get; } = new(new Guid("662467B2-CBCF-4347-9B39-A2BBEE04E6D7"), "Raven Attack Damage Increase Multiplier", "The raven damage increase which is multiplied with the min/max raven base damage and added to it."); /// /// Gets the curse attack damage increase attribute definition. @@ -343,9 +502,9 @@ public class Stats public static AttributeDefinition CurseAttackDamageIncrease { get; } = new(new Guid("2B8904D5-9901-40C0-BFDE-66675672D9DC"), "Curse Attack Damage Increase Multiplier", "The cursed damage increase which is multiplied with the min/max curse base damage and added to it."); /// - /// Gets the two handed weapon damage increase attribute definition. + /// Gets the two handed weapon physical damage increase ancient set option attribute definition. /// - public static AttributeDefinition TwoHandedWeaponDamageIncrease { get; } = new(new Guid("BA3D57E9-68A5-47AC-A6E9-43793F4DDE2A"), "Two-Handed Weapon Damage Increase", "The damage increase which is multiplied with the min/max base damage and added to it when using a two-handed weapon."); + public static AttributeDefinition TwoHandedWeaponDamageIncrease { get; } = new(new Guid("BA3D57E9-68A5-47AC-A6E9-43793F4DDE2A"), "Two-Handed Weapon Physical Damage Increase (Ancient Option)", "The physical damage increase which is multiplied with the final damage and added to it when using a two-handed weapon."); /// /// Gets the is two handed weapon equipped. @@ -358,9 +517,9 @@ public class Stats public static AttributeDefinition IsBowEquipped { get; } = new(new Guid("8B1135B7-C323-4822-9B98-1A56C802BB6A"), "Is Bow Equipped", string.Empty); /// - /// Gets the bow bonus base damage. + /// Gets the bow strengthener MST bonus damage. /// - public static AttributeDefinition BowBonusBaseDamage { get; } = new(new Guid("AF19A56D-2F31-4A80-8DF7-B99ADF7D275B"), "Bow Bonus Base Damage", string.Empty); + public static AttributeDefinition BowStrBonusDamage { get; } = new(new Guid("AF19A56D-2F31-4A80-8DF7-B99ADF7D275B"), "Bow Strengthener Bonus Damage (MST)", string.Empty); /// /// Gets the is a cross bow equipped. @@ -368,9 +527,54 @@ public class Stats public static AttributeDefinition IsCrossBowEquipped { get; } = new(new Guid("EDB70177-D824-45FC-8B76-7AE26859B7E5"), "Is Cross Bow Equipped", string.Empty); /// - /// Gets the bow bonus base damage. + /// Gets the cross bow strengthener MST bonus damage. + /// + public static AttributeDefinition CrossBowStrBonusDamage { get; } = new(new Guid("DBAD454A-EB1C-4FEE-9B40-97EA70278BB5"), "Cross Bow Strengthener Bonus Damage (MST)", string.Empty); + + /// + /// Gets the cross bow mastery MST bonus damage. + /// + public static AttributeDefinition CrossBowMasteryBonusDamage { get; } = new(new Guid("B3AF7F51-6D6B-42FB-B8FF-689D03890F3E"), "Cross Bow Mastery Bonus Damage (MST)", string.Empty); + + /// + /// Gets elf's melee attack mode attribute definition. /// - public static AttributeDefinition CrossBowBonusBaseDamage { get; } = new(new Guid("DBAD454A-EB1C-4FEE-9B40-97EA70278BB5"), "Cross Bow Bonus Base Damage", string.Empty); + public static AttributeDefinition MeleeAttackMode { get; } = new(new Guid("2121E586-B511-4D27-9E1A-67BFCACD7F41"), "Melee Attack Mode", "The elf's melee attack mode switch."); + + /// + /// Gets elf's melee minimum damage attribute definition. + /// + public static AttributeDefinition MeleeMinDmg { get; } = new(new Guid("A85BD4A5-9649-49F9-A7E2-B24D9114CC3E"), "Melee Minimum Damage", "The elf's minimum melee damage, which is added to close range attacks."); + + /// + /// Gets elf's melee maximum damage attribute definition. + /// + public static AttributeDefinition MeleeMaxDmg { get; } = new(new Guid("35A2224D-FD1C-4D19-B64B-EB7247530DE4"), "Melee Maximum Damage", "The elf's maximum melee damage, which is added to close range attacks."); + + /// + /// Gets elf's archery attack mode attribute definition. + /// + public static AttributeDefinition ArcheryAttackMode { get; } = new(new Guid("371E1237-6AE9-4AC1-9A7F-20CBEC897091"), "Archery Attack Mode", "The elf's archery attack mode switch."); + + /// + /// Gets elf's archery minimum damage attribute definition. + /// + public static AttributeDefinition ArcheryMinDmg { get; } = new(new Guid("9308EF7C-4DC4-4A0A-8747-02AAB7CC051A"), "Archery Minimum Damage", "The elf's minimum archery damage, which is added to projectile weapon attacks."); + + /// + /// Gets elf's archery maximum damage attribute definition. + /// + public static AttributeDefinition ArcheryMaxDmg { get; } = new(new Guid("EC807B7C-4004-4D13-BED2-326E13F8EFEB"), "Archery Maximum Damage", "The elf's maximum archery damage, which is added to projectile weapon attacks."); + + /// + /// Gets the elf's greater damage buff bonus damage attribute definition. + /// + public static AttributeDefinition GreaterDamageBonus { get; } = new(new Guid("5CFE3ED7-AF45-4790-BDD9-0DC55B981296"), "Greater Damage Bonus", string.Empty); + + /// + /// Gets the infinity arrow strengthener attack damage multiplier attribute definition. + /// + public static AttributeDefinition InfinityArrowStrMultiplier { get; } = new(new Guid("62536721-6C69-46D9-A6C4-1E4F0F7AC5AB"), "Infinity Arrow Strengthener Multiplier", "The infinity arrow strengthener damage multiplier which is multiplied with the final damage and added to it."); /// /// Gets the is a one handed sword equipped. @@ -378,9 +582,15 @@ public class Stats public static AttributeDefinition IsOneHandedSwordEquipped { get; } = new(new Guid("21B71774-EB4F-41F6-A0AA-0E600F41226C"), "Is One Handed Sword Equipped", string.Empty); /// - /// Gets the one handed sword bonus base damage. + /// Gets the one handed sword MST bonus base damage. + /// + public static AttributeDefinition OneHandedSwordBonusDamage { get; } = new(new Guid("60FA78A3-4E8C-4304-9077-5D3312EB1BE8"), "One Handed Sword Bonus Damage (MST)", string.Empty); + + /// + /// Gets the weapon mastery MST bonus attack speed. /// - public static AttributeDefinition OneHandedSwordBonusBaseDamage { get; } = new(new Guid("60FA78A3-4E8C-4304-9077-5D3312EB1BE8"), "One Handed Sword Bonus Base Damage", string.Empty); + /// Bucket attribute for the master skills: one handed sword mastery (DK), bow mastery (Elf), one handed staff mastery (DW), other world tome mastery (Summoner). + public static AttributeDefinition WeaponMasteryAttackSpeed { get; } = new(new Guid("CD16D6FD-5495-4BD9-A112-DBAF83BB4008"), "Weapon Mastery Bonus Attack Speed (MST)", "A generic master tree attack speed bonus attribute, which serves as a bucket for \"mastery\" skills."); /// /// Gets the is a two handed sword equipped. @@ -388,9 +598,14 @@ public class Stats public static AttributeDefinition IsTwoHandedSwordEquipped { get; } = new(new Guid("15530767-556E-45F6-8C2D-9AC71FC4070F"), "Is Two Handed Sword Equipped", string.Empty); /// - /// Gets the two handed sword bonus base damage. + /// Gets the two handed sword strengthener MST bonus damage. /// - public static AttributeDefinition TwoHandedSwordBonusBaseDamage { get; } = new(new Guid("C77F9C38-336B-43AE-8B82-A8D73612E9D2"), "Two Handed Sword Bonus Base Damage", string.Empty); + public static AttributeDefinition TwoHandedSwordStrBonusDamage { get; } = new(new Guid("C77F9C38-336B-43AE-8B82-A8D73612E9D2"), "Two Handed Sword Strengthener Bonus Damage (MST)", string.Empty); + + /// + /// Gets the two handed sword mastery MST bonus damage. + /// + public static AttributeDefinition TwoHandedSwordMasteryBonusDamage { get; } = new(new Guid("77B2B093-7418-4A71-AD52-12DB162B4461"), "Two Handed Sword Mastery Bonus Damage (MST)", string.Empty); /// /// Gets the is a mace equipped. @@ -398,9 +613,9 @@ public class Stats public static AttributeDefinition IsMaceEquipped { get; } = new(new Guid("47BD42D1-2E27-407B-92B5-925F418C30DE"), "Is Mace Equipped", string.Empty); /// - /// Gets the mace bonus base damage. + /// Gets the mace bonus MST damage. /// - public static AttributeDefinition MaceBonusBaseDamage { get; } = new(new Guid("E7F2A75F-E8F5-4877-A0D8-59D59041A973"), "Mace Bonus Base Damage", string.Empty); + public static AttributeDefinition MaceBonusDamage { get; } = new(new Guid("E7F2A75F-E8F5-4877-A0D8-59D59041A973"), "Mace Bonus Damage (MST)", string.Empty); /// /// Gets the is a spear equipped. @@ -408,19 +623,29 @@ public class Stats public static AttributeDefinition IsSpearEquipped { get; } = new(new Guid("5CBBD700-B897-4425-AADE-FDE249318505"), "Is Spear Equipped", string.Empty); /// - /// Gets the spear bonus base damage. + /// Gets the spear MST bonus damage. + /// + public static AttributeDefinition SpearBonusDamage { get; } = new(new Guid("207DA941-CDDC-4231-A82C-B76A2441B77A"), "Spear Bonus Damage (MST)", string.Empty); + + /// + /// Gets the generic physical MST bonus damage attribute, which serves as a bucket for late stage bonus physical damage. /// - public static AttributeDefinition SpearBonusBaseDamage { get; } = new(new Guid("207DA941-CDDC-4231-A82C-B76A2441B77A"), "Spear Bonus Base Damage", string.Empty); + /// So far includes the Weapon Mastery (DK, Elf, MG, DL, RF) passive skills, and the end product of Command Attack Increase (DL). + public static AttributeDefinition MasterSkillPhysBonusDmg { get; } = new(new Guid("48BD920B-9C6F-4884-A307-AD3AB58B7927"), "Master Skill Physical Bonus Damage (MST)", "A generic master tree physical damage bonus attribute, which serves as a bucket for late stage bonus physical damage."); /// /// Gets the is a one handed staff equipped. /// - public static AttributeDefinition IsOneHandedStaffEquipped { get; } = new(new Guid("C452EFD8-9FFE-4015-BE93-8BC8D5D81572"), "Is One Handed Staff Equipped", string.Empty); + /// MG can equip two. + public static AttributeDefinition IsOneHandedStaffEquipped { get; } = new(new Guid("C452EFD8-9FFE-4015-BE93-8BC8D5D81572"), "Is One Handed Staff Equipped", string.Empty) + { + MaximumValue = 1, + }; /// - /// Gets the one handed staff bonus base damage. + /// Gets the one handed staff MST bonus base damage. /// - public static AttributeDefinition OneHandedStaffBonusBaseDamage { get; } = new(new Guid("12F2F553-DA04-432F-83E0-28F30C1B93A2"), "One Handed Staff Bonus Base Damage", string.Empty); + public static AttributeDefinition OneHandedStaffBonusBaseDamage { get; } = new(new Guid("12F2F553-DA04-432F-83E0-28F30C1B93A2"), "One Handed Staff Bonus Base Damage (MST)", string.Empty); /// /// Gets the is a two handed staff equipped. @@ -428,9 +653,14 @@ public class Stats public static AttributeDefinition IsTwoHandedStaffEquipped { get; } = new(new Guid("FE669B70-D36D-4F56-A1DA-4A4B98ED503D"), "Is Two Handed Staff Equipped", string.Empty); /// - /// Gets the two handed staff bonus base damage. + /// Gets the two handed staff MST bonus base damage. /// - public static AttributeDefinition TwoHandedStaffBonusBaseDamage { get; } = new(new Guid("8A46D105-4B58-4E42-B602-52715F6BEE61"), "Two Handed Staff Bonus Base Damage", string.Empty); + public static AttributeDefinition TwoHandedStaffBonusBaseDamage { get; } = new(new Guid("8A46D105-4B58-4E42-B602-52715F6BEE61"), "Two Handed Staff Bonus Base Damage (MST)", string.Empty); + + /// + /// Gets the two handed staff mastery MST bonus damage. + /// + public static AttributeDefinition TwoHandedStaffMasteryBonusDamage { get; } = new(new Guid("1E6B1569-A36D-4C41-97B1-DD6E0A9746EE"), "Two Handed Staff Mastery Bonus Damage (MST)", string.Empty); /// /// Gets the is a stick equipped. @@ -438,9 +668,39 @@ public class Stats public static AttributeDefinition IsStickEquipped { get; } = new(new Guid("85C46193-8EC9-4CCE-B18B-F79E938FE9C3"), "Is Stick Equipped", string.Empty); /// - /// Gets the stick bonus base damage. + /// Gets the is a book equipped. + /// + public static AttributeDefinition IsBookEquipped { get; } = new(new Guid("1EE456B6-65EF-46E9-A90D-D3BA7D23CBF5"), "Is Book Equipped", string.Empty); + + /// + /// Gets the book MST (tome strengthener) bonus base damage. + /// + public static AttributeDefinition BookBonusBaseDamage { get; } = new(new Guid("6B15592C-70A4-4EE0-A713-DDC4794313DA"), "Book Bonus Base Damage (MST)", string.Empty); + + /// + /// Gets the stick MST bonus base damage. + /// + public static AttributeDefinition StickBonusBaseDamage { get; } = new(new Guid("0EF0D78B-9518-445B-BE5A-469962AF7C9D"), "Stick Bonus Base Damage (MST)", string.Empty); + + /// + /// Gets the stick mastery MST bonus damage. + /// + public static AttributeDefinition StickMasteryBonusDamage { get; } = new(new Guid("E79B2B06-9A32-451F-9B2D-2B91FD79B614"), "Stick Mastery Bonus Damage (MST)", string.Empty); + + /// + /// Gets the explosion skill MST bonus damage, which rises with fire tome strengthener and is added late stage. + /// + public static AttributeDefinition ExplosionBonusDmg { get; } = new(new Guid("543E01C2-5C61-4473-ACF9-8A63A987A230"), "Explosion Bonus Damage (MST)", "The explosion skill (book of samut) bonus damage, which rises with fire stome strengthener and is added at a late stage."); + + /// + /// Gets the requiem skill MST bonus damage, which rises with wind tome strengthener and is added late stage. + /// + public static AttributeDefinition RequiemBonusDmg { get; } = new(new Guid("9354C6C8-5F85-440B-8649-3E18B7539D92"), "Requiem Bonus Damage (MST)", "The requiem skill (book of neil) bonus damage, which rises with wind tome strengthener and is added at a late stage."); + + /// + /// Gets the pollution skill MST bonus damage, which rises with lightning tome strengthener and is added late stage. /// - public static AttributeDefinition StickBonusBaseDamage { get; } = new(new Guid("0EF0D78B-9518-445B-BE5A-469962AF7C9D"), "Stick Bonus Base Damage", string.Empty); + public static AttributeDefinition PollutionBonusDmg { get; } = new(new Guid("9B7AF584-DB59-4770-BCE9-1B5131BBDE38"), "Pollution Bonus Damage (MST)", "The pollution skill (book of lagle) bonus damage, which rises with lightning tome strengthener and is added at a late stage."); /// /// Gets the is a scepter equipped. @@ -448,19 +708,24 @@ public class Stats public static AttributeDefinition IsScepterEquipped { get; } = new(new Guid("8650DE3B-BE11-458E-B352-4046CE264402"), "Is Scepter Equipped", string.Empty); /// - /// Gets the scepter bonus base damage. + /// Gets the scepter strengthener MST bonus damage. /// - public static AttributeDefinition ScepterBonusBaseDamage { get; } = new(new Guid("4E4373A5-F5DB-4D06-B5C1-EE798B58017E"), "Scepter Bonus Base Damage", string.Empty); + public static AttributeDefinition ScepterStrBonusDamage { get; } = new(new Guid("4E4373A5-F5DB-4D06-B5C1-EE798B58017E"), "Scepter Strengthener Bonus Damage (MST)", string.Empty); /// - /// Gets the scepter pet bonus base damage. + /// Gets the scepter mastery MST bonus damage. /// - public static AttributeDefinition ScepterPetBonusBaseDamage { get; } = new(new Guid("5706451D-6A73-4462-B559-31C7F847994E"), "Scepter Pet Bonus Base Damage", string.Empty); + public static AttributeDefinition ScepterMasteryBonusDamage { get; } = new(new Guid("39C1837C-B19F-4FA3-B16F-03A0F5AE624A"), "Scepter Mastery Bonus Damage (MST)", string.Empty); + + /// + /// Gets the scepter pet MST bonus damage. + /// + public static AttributeDefinition ScepterPetBonusDamage { get; } = new(new Guid("5706451D-6A73-4462-B559-31C7F847994E"), "Scepter Pet Bonus Base Damage (MST)", string.Empty); /// /// Gets the is a horse equipped. /// - public static AttributeDefinition IsHorseEquipped { get; } = new(new Guid("4CDC3CCC-9266-4EEE-9C91-0E6AAFA8B636"), "Is Horse equipped", string.Empty); + public static AttributeDefinition IsHorseEquipped { get; } = new(new Guid("4CDC3CCC-9266-4EEE-9C91-0E6AAFA8B636"), "Is Horse Equipped", string.Empty); /// /// Gets the is a glove weapon equipped. @@ -468,9 +733,9 @@ public class Stats public static AttributeDefinition IsGloveWeaponEquipped { get; } = new(new Guid("BC8FFFCA-A593-4B64-BE37-BF7EDC97CA1E"), "Is Glove Weapon Equipped", string.Empty); /// - /// Gets the glove weapon bonus base damage. + /// Gets the glove weapon MST bonus damage. /// - public static AttributeDefinition GloveWeaponBonusBaseDamage { get; } = new(new Guid("F9CB1174-0184-4F21-B71D-AFC7359BC594"), "Glove Weapon Bonus Base Damage", string.Empty); + public static AttributeDefinition GloveWeaponBonusDamage { get; } = new(new Guid("F9CB1174-0184-4F21-B71D-AFC7359BC594"), "Glove Weapon Bonus Damage (MST)", string.Empty); /// /// Gets the summoned monster health increase, percentage. @@ -505,6 +770,11 @@ public class Stats /// /// Gets the defense base attribute definition. /// + /// Calculated in several stages: + /// Stage 0: armor, shield, and wings defense plus their item options; horse defense bonus; set level bonus multiplier; MST defense increase bonus as final value. + /// Stage 1: halving and elite transfer skeleton ring multipliers. + /// Stage 2: robot knight ring, panda and unicorn pet bonuses; JoH option (halved), socket option, ancient set option (halved); ancient set/socket option def increase with shield multiplier. + /// Stage 3: Jack O'Lantern Cry bonus (halved), elf's defense buff, MST bonus defense with shield, MST horse strengthener defense bonus, guardian option (halved); fire slash defense reduction multiplier. public static AttributeDefinition DefenseBase { get; } = new(new Guid("EB098C46-60D4-4CA6-BBD4-5B6270A1407B"), "Base Defense", string.Empty); /// @@ -520,6 +790,9 @@ public class Stats /// /// Gets the defense rate PVM attribute definition. /// + /// Calculated in several stages: + /// Stage 0: base DR from stats; MST PvM DR increase multiplier. + /// Stage 1: MST shield mastery bonus; exc DR option multipliers. public static AttributeDefinition DefenseRatePvm { get; } = new(new Guid("C520DD2D-1B06-4392-95EE-3C41F33E68DA"), "Defense Rate (PvM)", string.Empty); /// @@ -530,38 +803,156 @@ public class Stats /// /// Gets the damage receive decrement attribute definition. /// + /// Includes wings, and dinorant. public static AttributeDefinition DamageReceiveDecrement { get; } = new(new Guid("9D9761EF-EF47-4E5C-8106-EBC555786F20"), "Damage Receive Multiplier", string.Empty); /// - /// Gets the shield block damage decrement attribute definition. - /// TODO: Usage in a shield skill handler. + /// Gets the damage receive decrement from dark horse attribute definition. + /// + public static AttributeDefinition DamageReceiveHorseDecrement { get; } = new(new Guid("041B2811-05C0-49DE-B083-4D1FBD7E6286"), "Damage Receive From Dark Horse Multiplier", string.Empty); + + /// + /// Gets the soul barrier skill damage receive decrement attribute definition. + /// + public static AttributeDefinition SoulBarrierReceiveDecrement { get; } = new(new Guid("CBC5404A-6232-4BF3-9B85-9AA0AE0F9BA4"), "Soul Barrier Damage Receive Decrement", "The soul barrier skill receive damage multiplier which is multiplied with the final damage and subtracted from it."); + + /// + /// Gets the soul barrier skill mana toll per successful received hit attribute definition. + /// + public static AttributeDefinition SoulBarrierManaTollPerHit { get; } = new(new Guid("25315C15-C884-4B45-9883-9A92693DC455"), "Soul Barrier Mana Toll Per Received Hit", "A mana requirement which must be met for the soul barrier skill decrement."); + + /// + /// Gets the damage receive decrement from a guardian angel or spirit of guardian pet attribute definition. + /// + public static AttributeDefinition GuardianReceiveDecrement { get; } = new(new Guid("9A23A2C2-6452-4D5B-B849-CDA3A1236C92"), "Guardian Damage Receive Decrement", "The guardian receive damage multiplier which is multiplied with the final damage and subtracted from it."); + + /// + /// Gets the total armor damage decrease (receive) attribute definition. + /// + /// Includes the sum of excellent, harmony, and socket options. + public static AttributeDefinition ArmorDamageDecrease { get; } = new(new Guid("BFCF7096-44E9-473F-8162-416E9AD61477"), "Armor Damage Decrease", "The total excellent, harmony, and socket options damage decrease multiplier which is multiplied with the final damage and subtracted from it."); + + /// + /// Gets the shield defense skill damage receive decrement attribute definition. /// - public static AttributeDefinition ShieldBlockDamageDecrement { get; } = new(new Guid("DAC6690B-5922-4446-BCE5-5E701BE62EC1"), "Shield Block Damage Multiplier", string.Empty); + /// The value is either 0 or 50%. + public static AttributeDefinition ShieldSkillReceiveDecrement { get; } = new(new Guid("DAC6690B-5922-4446-BCE5-5E701BE62EC1"), "Shield Defense Skill Damage Receive Decrement", "The shield's defense skill multiplier which is multiplied with the final damage and subtracted from it."); /// - /// Gets the defense increase with equipped shield attribute definition. + /// Gets the total defense increase with equipped shield attribute definition. /// + /// Includes the sum of ancient set and socket options. public static AttributeDefinition DefenseIncreaseWithEquippedShield { get; } = new(new Guid("41BCEC8D-A7A8-4930-AB2E-A07D8BF1B86C"), "Defense Increase Multiplier With Equipped Shield", string.Empty); /// - /// Gets the bonus defense (absolute) with an equipped shield attribute definition. + /// Gets the bonus defense (absolute) with an equipped shield MST attribute definition. + /// + public static AttributeDefinition BonusDefenseWithShield { get; } = new(new Guid("05F08D89-9BC6-4164-9B30-26EFAF4C0E0F"), "Defense Increase Bonus (absolute) With equipped Shield (MST)", string.Empty); + + /// + /// Gets the bonus PvM defense rate (absolute) with an equipped shield MST attribute definition. + /// + public static AttributeDefinition BonusDefenseRateWithShield { get; } = new(new Guid("C8CF9CE1-F7AC-48DE-BFCC-349ABBFB1FCA"), "PvM Defense Rate Increase Bonus (absolute) With equipped Shield (MST)", string.Empty); + + /// + /// Gets the bonus damage (absolute) with an equipped scepter attribute definition. /// - public static AttributeDefinition BonusDefenseWithShield { get; } = new(new Guid("05F08D89-9BC6-4164-9B30-26EFAF4C0E0F"), "Defense Increase Bonus (absolute) With equipped Shield", string.Empty); + public static AttributeDefinition BonusDamageWithScepter { get; } = new(new Guid("7977FE44-FC22-4A6B-A4E0-BA522FE807DF"), "Damage Increase Bonus (absolute) with equipped Scepter", string.Empty); /// - /// Gets the bonus defense (absolute) with an equipped scepter attribute definition. + /// Gets the bonus damage (absolute) command/leadership divisor with an equipped scepter MST attribute definition. /// - public static AttributeDefinition BonusDefenseWithScepter { get; } = new(new Guid("7977FE44-FC22-4A6B-A4E0-BA522FE807DF"), "Defense Increase Bonus (absolute) with equipped Scepter", string.Empty); + public static AttributeDefinition BonusDamageWithScepterCmdDiv { get; } = new(new Guid("9A3C99C4-4F94-4CD0-8BFC-C8B870CD5FE4"), "Damage Increase Bonus (absolute) command divisor with equipped Scepter (MST)", string.Empty); /// - /// Gets the bonus defense (absolute) command/leadership divisor with an equipped shield attribute definition. + /// Gets the bonus defense (absolute) with an equipped dark horse MST attribute definition. /// - public static AttributeDefinition BonusDefenseWithScepterCmdDiv { get; } = new(new Guid("9A3C99C4-4F94-4CD0-8BFC-C8B870CD5FE4"), "Defense Increase Bonus (absolute) with equipped Scepter", string.Empty); + public static AttributeDefinition BonusDefenseWithHorse { get; } = new(new Guid("8D22E36C-EB36-47DB-8CE0-9ABD599C533C"), "Defense Increase Bonus (absolute) With equipped Horse (MST)", string.Empty); /// - /// Gets the bonus defense (absolute) with an equipped dark horse attribute definition. + /// Gets the electric spike skill bonus damage attribute definition. /// - public static AttributeDefinition BonusDefenseWithHorse { get; } = new(new Guid("8D22E36C-EB36-47DB-8CE0-9ABD599C533C"), "Defense Increase Bonus (absolute) With equipped Horse", string.Empty); + public static AttributeDefinition ElectricSpikeBonusDmg { get; } = new(new Guid("2DDBCE01-88CF-4A01-B691-1772FA836D9B"), "Electric Spike Bonus Damage", "The electric spike skill bonus damage, which depends on other stats."); + + /// + /// Gets the earthshake skill bonus damage attribute definition. + /// + public static AttributeDefinition EarthshakeBonusDmg { get; } = new(new Guid("6370BB15-5602-44BC-8FDC-A787A6FAB4F2"), "Earthshake Bonus Damage", "The earthshake skill bonus damage, which depends on other stats."); + + /// + /// Gets the chaotic diseier skill bonus damage attribute definition. + /// + public static AttributeDefinition ChaoticDiseierBonusDmg { get; } = new(new Guid("BF691FDC-2791-49DD-8725-602C6762A57D"), "Chaotic Diseier Bonus Damage", "The chaotic diseier skill bonus damage, which depends on other stats."); + + /// + /// Gets the dark lord generic skill attribute definition. + /// + public static AttributeDefinition DarkLordGenericSkillBonusDmg { get; } = new(new Guid("8D6E3761-0C88-48F7-91DC-9D520038F12F"), "Dark Lord Generic Skill Bonus Damage", "The dark lord generic skill bonus damage, which depends on other stats. Any skill other than Electric Spike, Earthshake, and Chaotic Diseier."); + + /// + /// Gets the berserker buff mana (and damage) multiplier attribute definition. + /// + public static AttributeDefinition BerserkerManaMultiplier { get; } = new(new Guid("9B6AA0DA-9ABA-4C14-B094-F1AC70BCB52D"), "Berserker Mana Multiplier", "The berserker mana multiplier which is used to increase both caster's mana and damage (any type)."); + + /// + /// Gets the berserker buff health multiplier factor attribute definition. + /// + /// The health decrese multiplier debuff factor. + public static AttributeDefinition BerserkerHealthMultiplierFactor { get; } = new(new Guid("D1948382-23F6-43A4-AD84-69227BF2ABA3"), "Berserker Health Multiplier Factor", "The berserker health multiplier factor which is compared against and deduced from the final multiplier to lower caster's health."); + + /// + /// Gets the berserker buff curse damage multiplier MST attribute definition. + /// + /// Increases with MST berserker strengthener. Applies on skills. + public static AttributeDefinition BerserkerCurseMultiplier { get; } = new(new Guid("AD1A3A3F-B461-4CAE-B3A3-D03DD0714A96"), "Berserker Curse Multiplier", "The berserker strengthener curse damage multiplier which is multiplied with the base min/max and added to it."); + + /// + /// Gets the berserker buff wizardry damage multiplier attribute definition. + /// + /// The sum of and . Applies on skills. + public static AttributeDefinition BerserkerWizardryMultiplier { get; } = new(new Guid("8DA7B8C2-F28B-4472-AE8F-28F08D4E7E93"), "Berserker Wizardry Multiplier", "The berserker proficiency wizardry damage multiplier which is multiplied with the base min/max and added to it."); + + /// + /// Gets the berserker proficiency buff damage multiplier MST attribute definition. + /// + /// Increases with MST berserker proficiency. Applies on and skills. + public static AttributeDefinition BerserkerProficiencyMultiplier { get; } = new(new Guid("55124C97-6EF3-4C46-AEC9-D01C11BE18A4"), "Berserker Proficiency Multiplier (MST)", "The berserker proficiency damage multiplier which is added to the wizardry multiplier but also by itself is multiplied by the wizardry/curse final damage and added to it."); + + /// + /// Gets the berserker buff minimum physical damage bonus attribute definition. + /// + public static AttributeDefinition BerserkerMinPhysDmgBonus { get; } = new(new Guid("81B5B942-A6D4-4343-BD4D-106CFFF34F4E"), "Berserker Minimum Physical Damage Bonus", string.Empty); + + /// + /// Gets the berserker buff maximum physical damage bonus attribute definition. + /// + public static AttributeDefinition BerserkerMaxPhysDmgBonus { get; } = new(new Guid("602D5FC4-AB85-423A-9C91-D23B0A28996C"), "Berserker Maximum Physical Damage Bonus", string.Empty); + + /// + /// Gets the berserker buff minimum wizardry damage bonus attribute definition. + /// + public static AttributeDefinition BerserkerMinWizDmgBonus { get; } = new(new Guid("DFCEC75A-BFB4-4FD4-922D-12EAAB4AEF18"), "Berserker Minimum Wizardry Damage Bonus", string.Empty); + + /// + /// Gets the berserker buff maximum wizardry damage bonus attribute definition. + /// + public static AttributeDefinition BerserkerMaxWizDmgBonus { get; } = new(new Guid("B2A85454-B442-44C5-BAD0-4933F0C5E6E0"), "Berserker Maximum Wizardry Damage Bonus", string.Empty); + + /// + /// Gets the berserker buff minimum curse damage bonus attribute definition. + /// + public static AttributeDefinition BerserkerMinCurseDmgBonus { get; } = new(new Guid("06BA893F-F9EF-4813-8233-DAB0D83CC4EC"), "Berserker Minimum Curse Damage Bonus", string.Empty); + + /// + /// Gets the berserker buff maximum curse damage bonus attribute definition. + /// + public static AttributeDefinition BerserkerMaxCurseDmgBonus { get; } = new(new Guid("B519555A-748D-4462-A8C0-A7E7DA0C3B67"), "Berserker Maximum Curse Damage Bonus", string.Empty); + + /// + /// Gets the weakness physical damage decrement due to magic effects of weakness (Summoner) or killing blow (RF) skills attribute definition. + /// + /// Only applies to physical damage. + public static AttributeDefinition WeaknessPhysDmgDecrement { get; } = new(new Guid("37497650-139B-4DA1-9FB6-27AEB8F04CF6"), "Weakness Physical Damage Decrement", "The inflicted physical damage decrement due to the magic effects of weakness or killing blow skills, which is multiplied with the final damage and subtracted from it."); /// /// Gets the 'is shield equipped' attribute definition. @@ -772,7 +1163,7 @@ public class Stats /// /// Gets the pet duration increase attribute definition. /// - public static AttributeDefinition PetDurationIncrease { get; } = new(new Guid("B4455150-D3A9-4A5F-914B-F41F9387FE9A"), "Pet Duraction Increase", string.Empty); + public static AttributeDefinition PetDurationIncrease { get; } = new(new Guid("B4455150-D3A9-4A5F-914B-F41F9387FE9A"), "Pet Duration Increase", string.Empty); /// /// Gets the horse level attribute definition. @@ -785,9 +1176,9 @@ public class Stats public static AttributeDefinition RavenLevel { get; } = new(new Guid("2C9AA85C-AB8B-4E0F-8F0B-BC6E49EE134E"), "Dark Raven Level", string.Empty); /// - /// Gets the raven base damage definition. + /// Gets the raven bonus damage MST definition. /// - public static AttributeDefinition RavenBaseDamage { get; } = new(new Guid("3F77AD23-3833-4F2F-A264-23F7A4688FDA"), "Min and Max damage of the dark raven.", string.Empty); + public static AttributeDefinition RavenBonusDamage { get; } = new(new Guid("3F77AD23-3833-4F2F-A264-23F7A4688FDA"), "Dark Raven Bonus Damage (MST)", string.Empty); /// /// Gets the raven minimum damage definition. @@ -810,14 +1201,14 @@ public class Stats public static AttributeDefinition RavenAttackSpeed { get; } = new(new Guid("3359F7E9-936C-48DD-BB0A-E44E2347D3CA"), "Attack speed of the dark raven.", string.Empty); /// - /// Gets the raven critical damage chance bonus. + /// Gets the raven critical damage chance. /// - public static AttributeDefinition RavenCriticalDamageChanceBonus { get; } = new(new Guid("D9C8D708-F94A-430E-B812-99A2F3F0768E"), "Raven critical damage chance bonus", string.Empty); + public static AttributeDefinition RavenCriticalDamageChance { get; } = new(new Guid("D9C8D708-F94A-430E-B812-99A2F3F0768E"), "Raven critical damage chance", string.Empty); /// - /// Gets the raven excellent damage chance bonus. + /// Gets the raven excellent damage chance. /// - public static AttributeDefinition RavenExcDamageChanceBonus { get; } = new(new Guid("31EF09B0-0F79-439B-900C-C9350BAD99DF"), "Raven exc damage chance bonus", string.Empty); + public static AttributeDefinition RavenExcDamageChance { get; } = new(new Guid("31EF09B0-0F79-439B-900C-C9350BAD99DF"), "Raven exc damage chance", string.Empty); /// /// Gets the maximum guild size attribute definition. @@ -850,7 +1241,12 @@ public class Stats public static AttributeDefinition CanFly { get; } = new(new Guid("EC34C673-84DE-4811-8962-CD2164A2248C"), "Requirement of the Icarus map.", "You can enter Icarus only with wings, dinorant, fenrir."); /// - /// Gets the MoonstonePendantEquipped attribute for warping to Karutan. + /// Gets the is dinorant equipped attribute definition. + /// + public static AttributeDefinition IsDinorantEquipped { get; } = new(new Guid("C52B5CA4-34BA-4E31-963B-E37089671C37"), "Is Dinorant Equipped", string.Empty); + + /// + /// Gets the MoonstonePendantEquipped attribute for entering Kanturu event. /// public static AttributeDefinition MoonstonePendantEquipped { get; } = new(new Guid("4BC010D0-9E75-4ECB-8963-08A3697278C3"), "Requirement of the Kanturu Event Map during the event.", "You can enter the Kanturu Event only with an equipped Moonstone Pendant."); @@ -864,6 +1260,11 @@ public class Stats /// public static AttributeDefinition AmmunitionAmount { get; } = new(new Guid("064543E6-2559-4033-B363-AE76214E7DEE"), "The amount of ammo which is equipped.", "You can only execute certain skills if you have enough ammo, or if the ammo consumption rate is 0."); + /// + /// Gets the Ammo damage bonus (relative) increase attribute. + /// + public static AttributeDefinition AmmunitionDamageBonus { get; } = new(new Guid("C715CC22-9D8A-4056-BB5E-AC681CFC9E44"), "Ammunition Damage Bonus", "The ammunition damage bonus (relative) which is multiplied by the min/max base damage."); + /// /// Gets the attribute which defines if the character is located in a safezone of a game map. /// diff --git a/src/GameLogic/DefaultDropGenerator.cs b/src/GameLogic/DefaultDropGenerator.cs index 064a38cc6..fd41b5135 100644 --- a/src/GameLogic/DefaultDropGenerator.cs +++ b/src/GameLogic/DefaultDropGenerator.cs @@ -327,6 +327,17 @@ private void ApplyOption(Item item, ItemOptionDefinition option) .Distinct().Where(l => l <= this._maxItemOptionLevelDrop).SelectRandom() ?? 0, }; item.ItemOptions.Add(itemOptionLink); + + if (item.Definition?.Group == 0 && item.Definition.BasePowerUpAttributes.Any(bpua => bpua.TargetAttribute == Stats.StaffRise)) + { + // Double item option MG sword + var doubleOptionLink = new ItemOptionLink + { + ItemOption = remainingOptions.First(o => o != newOption), + Level = itemOptionLink.Level, + }; + item.ItemOptions.Add(doubleOptionLink); + } } } } diff --git a/src/GameLogic/IAttacker.cs b/src/GameLogic/IAttacker.cs index 037235f4b..dec2ee062 100644 --- a/src/GameLogic/IAttacker.cs +++ b/src/GameLogic/IAttacker.cs @@ -20,4 +20,9 @@ public interface IAttacker : IIdentifiable, ILocateable /// Gets the state of the combo, if the attacker supports combos. /// ComboStateMachine? ComboState { get; } + + /// + /// Gets the attacker's party, if the attacker can have one. + /// + Party? Party { get; } } \ No newline at end of file diff --git a/src/GameLogic/InventoryStorage.cs b/src/GameLogic/InventoryStorage.cs index 69a482fa5..d6019af37 100644 --- a/src/GameLogic/InventoryStorage.cs +++ b/src/GameLogic/InventoryStorage.cs @@ -25,7 +25,8 @@ public class InventoryStorage : Storage, IInventoryStorage /// The player. /// The game context. public InventoryStorage(Player player, IGameContext context) - : base(GetInventorySize(0), + : base( + GetInventorySize(0), EquippableSlotsCount, 0, new ItemStorageAdapter(player.SelectedCharacter?.Inventory ?? throw Error.NotInitializedProperty(player, "SelectedCharacter.Inventory"), FirstEquippableItemSlotIndex, player.GetInventorySize())) @@ -139,7 +140,7 @@ private async ValueTask UpdateItemsOnChangeAsync(Item item, bool isEquipped) await this._player.ForEachWorldObserverAsync( p => p.AppearanceChangedAsync(this._player, item, isEquipped), - false).ConfigureAwait(false); // in my tests it was not needed to send the appearance to the own players client. + false).ConfigureAwait(false); // in my tests it was not needed to send the appearance to the own player's client. if (this._player.Attributes is null) { @@ -155,7 +156,7 @@ await this._player.ForEachWorldObserverAsync( } } - if (item.ItemSetGroups != null && item.ItemSetGroups.Any()) + if (item.Definition!.PossibleItemSetGroups.Count > 0) { this.UpdateSetPowerUps(); } @@ -178,7 +179,7 @@ private void InitializePowerUps() { if (this._player.Attributes is null) { - throw new InvalidOperationException("The players AttributeSystem is not set yet."); + throw new InvalidOperationException("The player's AttributeSystem is not set yet."); } foreach (var powerUp in this._player.Attributes.ItemPowerUps.Values.SelectMany(p => p).ToList()) diff --git a/src/GameLogic/ItemExtensions.cs b/src/GameLogic/ItemExtensions.cs index e2e465b1d..94deccaa5 100644 --- a/src/GameLogic/ItemExtensions.cs +++ b/src/GameLogic/ItemExtensions.cs @@ -167,7 +167,7 @@ public static bool IsPhysicalWeapon(this Item item, [NotNullWhen(true)] out floa /// Determines whether this instance is a weapon which increases wizardry damage. /// /// The item. - /// The staff/stick's wizardry damage rise percentage. + /// The staff/sword/stick's wizardry damage rise percentage. /// /// true if this instance is a weapon which increases wizardry damage; otherwise, false. /// diff --git a/src/GameLogic/ItemPowerUpFactory.cs b/src/GameLogic/ItemPowerUpFactory.cs index 6f7c0664c..8bdd939eb 100644 --- a/src/GameLogic/ItemPowerUpFactory.cs +++ b/src/GameLogic/ItemPowerUpFactory.cs @@ -45,9 +45,33 @@ public IEnumerable GetPowerUps(Item item, AttributeSystem attrib yield break; } + var isRightWieldWeapon = item.ItemSlot == InventoryConstants.RightHandSlot + && item.Definition!.BasePowerUpAttributes.Any(pu => pu.TargetAttribute == Stats.DoubleWieldWeaponCount || pu.TargetAttribute == Stats.IsOneHandedStaffEquipped); + + AttributeDefinition? targetAttribute = null; foreach (var attribute in item.Definition.BasePowerUpAttributes) { - foreach (var powerUp in this.GetBasePowerUpWrappers(item, attributeHolder, attribute)) + if (isRightWieldWeapon) + { + if (attribute.TargetAttribute == Stats.StaffRise) + { + continue; + } + else if (attribute.TargetAttribute == Stats.MinimumPhysBaseDmgByWeapon) + { + targetAttribute = Stats.MinPhysBaseDmgByRightWeapon; + } + else if (attribute.TargetAttribute == Stats.MaximumPhysBaseDmgByWeapon) + { + targetAttribute = Stats.MaxPhysBaseDmgByRightWeapon; + } + else + { + targetAttribute = null; + } + } + + foreach (var powerUp in this.GetBasePowerUpWrappers(item, attributeHolder, attribute, targetAttribute)) { yield return powerUp; } @@ -179,7 +203,7 @@ private bool AreRequiredOptionsFound(ItemOptionCombinationBonus bonus, IList GetBasePowerUpWrappers(Item item, AttributeSystem attributeHolder, ItemBasePowerUpDefinition attribute) + private IEnumerable GetBasePowerUpWrappers(Item item, AttributeSystem attributeHolder, ItemBasePowerUpDefinition attribute, AttributeDefinition? targetAttribute = null) { attribute.ThrowNotInitializedProperty(attribute.BaseValueElement is null, nameof(attribute.BaseValueElement)); attribute.ThrowNotInitializedProperty(attribute.TargetAttribute is null, nameof(attribute.TargetAttribute)); @@ -190,13 +214,13 @@ private IEnumerable GetBasePowerUpWrappers(Item item, AttributeS if (levelBonusElmt is null) { - yield return new PowerUpWrapper(attribute.BaseValueElement, attribute.TargetAttribute, attributeHolder); + yield return new PowerUpWrapper(attribute.BaseValueElement, targetAttribute ?? attribute.TargetAttribute, attributeHolder); } else { yield return new PowerUpWrapper( new CombinedElement(attribute.BaseValueElement, levelBonusElmt), - attribute.TargetAttribute, + targetAttribute ?? attribute.TargetAttribute, attributeHolder); } } @@ -218,6 +242,12 @@ private IEnumerable GetPowerUpsOfItemOptions(Item item, Attribut continue; } + if (item.ItemSlot == InventoryConstants.RightHandSlot && option.PowerUpDefinition?.TargetAttribute == Stats.WizardryBaseDmg) + { + // For a RH-wielded staff (MG), its wizardry item option doesn't count (but the others do!) + continue; + } + var level = option.LevelType == LevelType.ItemLevel ? item.Level : optionLink.Level; var optionOfLevel = option.LevelDependentOptions?.FirstOrDefault(l => l.Level == level); @@ -294,18 +324,30 @@ private IEnumerable CreateExcellentAndAncientBasePowerUpWrappers if (item.IsPhysicalWeapon(out var minPhysDmg)) { - var additionalDmg = ((int)minPhysDmg * 25 / baseDropLevel) + 5; - yield return new PowerUpWrapper(new SimpleElement(additionalDmg, AggregateType.AddRaw), Stats.MinimumPhysBaseDmgByWeapon, attributeHolder); - yield return new PowerUpWrapper(new SimpleElement(additionalDmg, AggregateType.AddRaw), Stats.MaximumPhysBaseDmgByWeapon, attributeHolder); + var minDmgAttribute = Stats.MinimumPhysBaseDmgByWeapon; + var maxDmgAttribute = Stats.MaximumPhysBaseDmgByWeapon; + if (item.ItemSlot == InventoryConstants.RightHandSlot + && item.Definition!.BasePowerUpAttributes.Any(pu => pu.TargetAttribute == Stats.DoubleWieldWeaponCount || pu.TargetAttribute == Stats.IsOneHandedStaffEquipped)) + { + minDmgAttribute = Stats.MinPhysBaseDmgByRightWeapon; + maxDmgAttribute = Stats.MaxPhysBaseDmgByRightWeapon; + } + + var dmgDivisor = item.Definition!.Group == 5 ? 2 : 1; + minPhysDmg *= dmgDivisor; // For staffs/sticks the damage is halved initially, so we restore it first + + var additionalDmg = (((int)minPhysDmg * 25 / baseDropLevel) + 5) / dmgDivisor; + yield return new PowerUpWrapper(new SimpleElement(additionalDmg, AggregateType.AddRaw), minDmgAttribute, attributeHolder); + yield return new PowerUpWrapper(new SimpleElement(additionalDmg, AggregateType.AddRaw), maxDmgAttribute, attributeHolder); if (itemIsAncient) { - var ancientBonus = 5 + (ancientDropLevel / 40); - yield return new PowerUpWrapper(new SimpleElement(ancientBonus, AggregateType.AddRaw), Stats.MinimumPhysBaseDmgByWeapon, attributeHolder); - yield return new PowerUpWrapper(new SimpleElement(ancientBonus, AggregateType.AddRaw), Stats.MaximumPhysBaseDmgByWeapon, attributeHolder); + var ancientBonus = (5 + (ancientDropLevel / 40)) / dmgDivisor; + yield return new PowerUpWrapper(new SimpleElement(ancientBonus, AggregateType.AddRaw), minDmgAttribute, attributeHolder); + yield return new PowerUpWrapper(new SimpleElement(ancientBonus, AggregateType.AddRaw), maxDmgAttribute, attributeHolder); } } - if (item.IsWizardryWeapon(out var staffRise)) + if (item.IsWizardryWeapon(out var staffRise) && item.ItemSlot == InventoryConstants.LeftHandSlot) { var additionalRise = (((int)staffRise * 2 * 25 / baseDropLevel) + 5) / 2; yield return new PowerUpWrapper(new SimpleElement(additionalRise, AggregateType.AddRaw), Stats.StaffRise, attributeHolder); diff --git a/src/GameLogic/NPC/AttackableNpcBase.cs b/src/GameLogic/NPC/AttackableNpcBase.cs index 04b0462fc..f57e47ad2 100644 --- a/src/GameLogic/NPC/AttackableNpcBase.cs +++ b/src/GameLogic/NPC/AttackableNpcBase.cs @@ -112,12 +112,12 @@ public int Health attacker.ApplyAmmunitionConsumption(hitInfo); if (attacker is Player player) { - await player.AfterHitTargetAsync().ConfigureAwait(false); + await player.AfterHitTargetAsync(skill).ConfigureAwait(false); } if (attacker as IPlayerSurrogate is { } playerSurrogate) { - await playerSurrogate.Owner.AfterHitTargetAsync().ConfigureAwait(false); + await playerSurrogate.Owner.AfterHitTargetAsync(skill).ConfigureAwait(false); } } diff --git a/src/GameLogic/NPC/Monster.cs b/src/GameLogic/NPC/Monster.cs index 6f8acd3c5..11b480094 100644 --- a/src/GameLogic/NPC/Monster.cs +++ b/src/GameLogic/NPC/Monster.cs @@ -92,6 +92,10 @@ public Monster(MonsterSpawnArea spawnInfo, MonsterDefinition stats, GameMap map, /// Monsters don't do combos. public ComboStateMachine? ComboState => null; + /// + /// Monsters don't have parties. + public Party? Party => null; + /// /// Attacks the specified target. /// diff --git a/src/GameLogic/NPC/Trap.cs b/src/GameLogic/NPC/Trap.cs index ab87c029a..4028d8d99 100644 --- a/src/GameLogic/NPC/Trap.cs +++ b/src/GameLogic/NPC/Trap.cs @@ -38,6 +38,10 @@ public Trap(MonsterSpawnArea spawnInfo, MonsterDefinition stats, GameMap map, IN /// Traps don't do combos. public ComboStateMachine? ComboState => null; + /// + /// Traps don't have parties. + public Party? Party => null; + /// /// Attacks the specified player. /// diff --git a/src/GameLogic/Pet/AttackerSurrogate.cs b/src/GameLogic/Pet/AttackerSurrogate.cs index 81327c84b..ef04e5cda 100644 --- a/src/GameLogic/Pet/AttackerSurrogate.cs +++ b/src/GameLogic/Pet/AttackerSurrogate.cs @@ -10,7 +10,7 @@ namespace MUnique.OpenMU.GameLogic.Pet; using MUnique.OpenMU.PlugIns; /// -/// A surrogate for an which exposes the attack attributes +/// A surrogate for a which exposes the attack attributes /// of another . /// public class AttackerSurrogate : IAttacker, IWorldObserver, IPlayerSurrogate @@ -36,6 +36,10 @@ public AttackerSurrogate(Player owner, IAttributeSystem attributeSystem) /// public ComboStateMachine? ComboState => null; + /// + /// Pets don't have parties. + public Party? Party => null; + /// public ushort Id => this.Owner.Id; diff --git a/src/GameLogic/Pet/RavenAttributeSystem.cs b/src/GameLogic/Pet/RavenAttributeSystem.cs index 7989303fb..2189e5f6d 100644 --- a/src/GameLogic/Pet/RavenAttributeSystem.cs +++ b/src/GameLogic/Pet/RavenAttributeSystem.cs @@ -19,7 +19,7 @@ public class RavenAttributeSystem : IAttributeSystem Stats.MinimumPhysBaseDmg, player => { var minDamage = player.Attributes?[Stats.RavenMinimumDamage] ?? 0; - minDamage += minDamage * (player.Attributes?[Stats.PetAttackDamageIncrease] ?? 1); + minDamage += minDamage * (player.Attributes?[Stats.RavenAttackDamageIncrease] ?? 1); return minDamage; } }, @@ -27,24 +27,20 @@ public class RavenAttributeSystem : IAttributeSystem Stats.MaximumPhysBaseDmg, player => { var maxDamage = player.Attributes?[Stats.RavenMaximumDamage] ?? 0; - maxDamage += maxDamage * (player.Attributes?[Stats.PetAttackDamageIncrease] ?? 1); + maxDamage += maxDamage * (player.Attributes?[Stats.RavenAttackDamageIncrease] ?? 1); return maxDamage; } }, - { Stats.BaseDamageBonus, player => player.Attributes?[Stats.BaseDamageBonus] ?? 0 }, + { Stats.RavenBonusDamage, player => player.Attributes?[Stats.RavenBonusDamage] ?? 0 }, { Stats.AttackSpeed, player => player.Attributes?[Stats.RavenAttackSpeed] ?? 0 }, { Stats.AttackRatePvm, player => player.Attributes?[Stats.RavenAttackRate] ?? 0 }, - { Stats.AttackRatePvp, player => player.Attributes?[Stats.RavenAttackRate] ?? 0 }, - { Stats.CriticalDamageChance, player => player.Attributes?[Stats.CriticalDamageChance] + player.Attributes?[Stats.RavenCriticalDamageChanceBonus] ?? 0 }, - { Stats.CriticalDamageBonus, player => player.Attributes?[Stats.CriticalDamageBonus] ?? 0 }, - { Stats.ExcellentDamageChance, player => player.Attributes?[Stats.ExcellentDamageChance] ?? 0 + player.Attributes?[Stats.RavenExcDamageChanceBonus] ?? 0 }, - { Stats.ExcellentDamageBonus, player => player.Attributes?[Stats.ExcellentDamageBonus] ?? 0 }, + { Stats.AttackRatePvp, player => player.Attributes?[Stats.AttackRatePvp] ?? 0 }, + { Stats.CriticalDamageChance, player => player.Attributes?[Stats.RavenCriticalDamageChance] ?? 0 }, + { Stats.ExcellentDamageChance, player => player.Attributes?[Stats.RavenExcDamageChance] ?? 0 }, { Stats.DefenseIgnoreChance, player => player.Attributes?[Stats.DefenseIgnoreChance] ?? 0 }, - { Stats.DoubleDamageChance, player => player.Attributes?[Stats.DoubleDamageChance] ?? 0 }, { Stats.ShieldBypassChance, player => player.Attributes?[Stats.ShieldBypassChance] ?? 0 }, { Stats.ShieldDecreaseRateIncrease, player => player.Attributes?[Stats.ShieldDecreaseRateIncrease] ?? 0 }, - { Stats.AttackDamageIncrease, player => player.Attributes?[Stats.AttackDamageIncrease] ?? 0 }, - { Stats.FinalDamageIncreasePvp, player => player.Attributes?[Stats.FinalDamageIncreasePvp] ?? 0 }, + { Stats.AttackDamageIncrease, player => 1.0f }, }; private readonly Player _owner; diff --git a/src/GameLogic/Player.cs b/src/GameLogic/Player.cs index a787cda3d..374850cd4 100644 --- a/src/GameLogic/Player.cs +++ b/src/GameLogic/Player.cs @@ -509,7 +509,7 @@ public async ValueTask SetSelectedCharacterAsync(Character? character) this._appearanceData.RaiseAppearanceChanged(); await this.PlayerLeftWorld.SafeInvokeAsync(this).ConfigureAwait(false); - + (this.SkillList as IDisposable)?.Dispose(); this.SkillList = null; @@ -637,12 +637,12 @@ public bool IsAnySelfDefenseActive() if (attacker as IPlayerSurrogate is { } playerSurrogate) { - await playerSurrogate.Owner.AfterHitTargetAsync().ConfigureAwait(false); + await playerSurrogate.Owner.AfterHitTargetAsync(skill).ConfigureAwait(false); } if (attacker is Player attackerPlayer) { - await attackerPlayer.AfterHitTargetAsync().ConfigureAwait(false); + await attackerPlayer.AfterHitTargetAsync(skill).ConfigureAwait(false); } return hitInfo; @@ -651,10 +651,33 @@ public bool IsAnySelfDefenseActive() /// /// Is called after the player successfully hit a target. /// - public async ValueTask AfterHitTargetAsync() + public async ValueTask AfterHitTargetAsync(SkillEntry? skill) { this.Attributes![Stats.CurrentHealth] = Math.Max(this.Attributes[Stats.CurrentHealth] - this.Attributes[Stats.HealthLossAfterHit], 1); - this.Attributes![Stats.CurrentMana] = Math.Max(this.Attributes[Stats.CurrentMana] - this.Attributes[Stats.ManaLossAfterHit], 0); + + if (skill?.Skill is not null) + { + // Only skills consume mana + float extraManaLoss = 0; + if (this.MagicEffectList.ActiveEffects.ContainsKey(6)) // MagicEffectNumber.InfiniteArrow + { + var ammoItemLevel = this.Inventory?.EquippedAmmunitionItem?.Level ?? 0; + switch (ammoItemLevel) + { + case 0: + break; + case 1: + extraManaLoss = 2; + break; + default: + extraManaLoss = 5; + break; + } + } + + this.Attributes![Stats.CurrentMana] = Math.Max(this.Attributes[Stats.CurrentMana] - (this.Attributes[Stats.ManaLossAfterHit] + extraManaLoss), 0); + } + await this.DecreaseWeaponDurabilityAfterHitAsync().ConfigureAwait(false); } @@ -1404,12 +1427,14 @@ public void CreateMagicEffectPowerUp(SkillEntry skillEntry) int i = 0; var result = new (AttributeDefinition Target, IElement BuffPowerUp)[skill.MagicEffectDef.PowerUpDefinitions.Count]; + var durationElement = this.Attributes!.CreateDurationElement(skill.MagicEffectDef.Duration); AddSkillPowersToResult(skill); - skillEntry.PowerUpDuration = this.Attributes!.CreateDurationElement(skill.MagicEffectDef.Duration); + skillEntry.PowerUpDuration = durationElement; skillEntry.PowerUps = result; void AddSkillPowersToResult(Skill skill) { + var durationExtended = false; foreach (var powerUpDef in skill.MagicEffectDef!.PowerUpDefinitions) { IElement powerUp; @@ -1417,11 +1442,26 @@ void AddSkillPowersToResult(Skill skill) { powerUp = this.Attributes!.CreateElement(powerUpDef); - foreach (var masterSkillDefinition in GetMasterSkillDefinitions(skill.MasterDefinition)) + foreach (var masterSkillEntry in GetMasterSkillEntries(skillEntry)) { - // Apply either for all, or just for the specified TargetAttribute of the master skill - powerUp = AppedMasterSkillPowerUp(masterSkillDefinition, powerUpDef, powerUp); + var extendsDuration = masterSkillEntry.Skill?.MasterDefinition?.ExtendsDuration ?? false; + if (extendsDuration && !durationExtended) + { + durationElement = new CombinedElement(durationElement, new ConstantElement(skillEntry.CalculateValue())); + } + else if (extendsDuration) + { + continue; + } + else + { + // Apply either for all, or just for the specified TargetAttribute of the master skill + powerUp = AppedMasterSkillPowerUp(masterSkillEntry, powerUpDef, powerUp); + } } + + // After the first iteration all possible duration extensions have been applied + durationExtended = true; } else { @@ -1433,27 +1473,34 @@ void AddSkillPowersToResult(Skill skill) } } - IEnumerable GetMasterSkillDefinitions(MasterSkillDefinition? masterSkillDefinition) + IEnumerable GetMasterSkillEntries(SkillEntry? masterSkillEntry) { - var current = masterSkillDefinition; - while (current is not null) + var currentEntry = masterSkillEntry; + while (currentEntry is not null) { - yield return current; - current = current.ReplacedSkill?.MasterDefinition; + yield return currentEntry; + if (currentEntry.Skill?.MasterDefinition?.ReplacedSkill is { } replacedSkill && replacedSkill.MasterDefinition is not null) + { + currentEntry = this.SkillList!.GetSkill((ushort)replacedSkill.Number); + } + else + { + currentEntry = null; + } } } - IElement AppedMasterSkillPowerUp(MasterSkillDefinition? masterSkillDefinition, PowerUpDefinition powerUpDef, IElement powerUp) + IElement AppedMasterSkillPowerUp(SkillEntry? masterSkillEntry, PowerUpDefinition powerUpDef, IElement powerUp) { - if (masterSkillDefinition is null) + if (masterSkillEntry?.Skill?.MasterDefinition is not { } masterSkillDefinition) { return powerUp; } - if (masterSkillDefinition?.TargetAttribute is not { } masterSkillTargetAttribute + if (masterSkillDefinition.TargetAttribute is not { } masterSkillTargetAttribute || masterSkillTargetAttribute == powerUpDef.TargetAttribute) { - var additionalValue = new SimpleElement(skillEntry.CalculateValue(), skillEntry.Skill.MasterDefinition?.Aggregation ?? powerUp.AggregateType); + var additionalValue = new SimpleElement(masterSkillEntry.CalculateValue(), masterSkillEntry.Skill.MasterDefinition?.Aggregation ?? powerUp.AggregateType); powerUp = new CombinedElement(powerUp, additionalValue); } @@ -2354,6 +2401,11 @@ async ValueTask AddExpToPetAsync(Item pet, double experience) && (!pet.IsDarkRaven() || pet.GetDarkRavenLeadershipRequirement(pet.Level + 1) <= this.Attributes![Stats.TotalLeadership])) { pet.Level++; + this.Attributes!.ItemPowerUps[pet] = this.Attributes.ItemPowerUps[pet] + .Append(new PowerUpWrapper( + new SimpleElement(1, AggregateType.AddRaw), + pet.IsDarkRaven() ? Stats.RavenLevel : Stats.HorseLevel, + this.Attributes)).ToList(); await this.InvokeViewPlugInAsync(p => p.ShowPetInfoAsync(pet, pet.ItemSlot, PetStorageLocation.InventoryPetSlot)).ConfigureAwait(false); } diff --git a/src/GameLogic/PlayerActions/Character/AddMasterPointAction.cs b/src/GameLogic/PlayerActions/Character/AddMasterPointAction.cs index 8090afa09..672beae40 100644 --- a/src/GameLogic/PlayerActions/Character/AddMasterPointAction.cs +++ b/src/GameLogic/PlayerActions/Character/AddMasterPointAction.cs @@ -81,7 +81,23 @@ private async ValueTask AddMasterPointToLearnedSkillAsync(Player player, SkillEn learnedSkill.Level += requiredPoints; learnedSkill.PowerUpDuration = null; learnedSkill.PowerUps = null; + + var currentSkill = learnedSkill; + while (player.SkillList!.Skills.FirstOrDefault(s => s.Skill?.MasterDefinition?.ReplacedSkill == currentSkill.Skill) is { } childSkill) + { + // Because the learned skill might have been replaced by a child skill (active), we also need to nullify the child's powerups to force an update + childSkill.PowerUpDuration = null; + childSkill.PowerUps = null; + currentSkill = childSkill; + } + + if (learnedSkill.Skill.Number == 509) // Force Wave Streng + { + player.SkillList!.GetSkill(5090)!.Level += requiredPoints; + } + player.SelectedCharacter.MasterLevelUpPoints -= requiredPoints; + await player.InvokeViewPlugInAsync(p => p.MasterSkillLevelChangedAsync(learnedSkill)).ConfigureAwait(false); } else @@ -126,11 +142,11 @@ private bool CheckRank(MasterSkillDefinition definition, DataModel.Entities.Char return true; } - var learnedRequiredSkill = character.LearnedSkills - .Where(l => l.Skill?.MasterDefinition?.Root != null) - .FirstOrDefault(l => l.Skill!.MasterDefinition!.Root!.Id == definition.Root?.Id - && l.Skill.MasterDefinition.Rank == definition.Rank - 1); - return learnedRequiredSkill?.Level >= MinimumSkillLevelOfRequiredSkill; + var learnedRequiredSkills = character.LearnedSkills + .Where(l => l.Skill?.MasterDefinition?.Root != null + && l.Skill.MasterDefinition.Root.Id == definition.Root?.Id + && l.Skill.MasterDefinition.Rank == definition.Rank - 1); + return learnedRequiredSkills?.Any(lrs => lrs.Level >= MinimumSkillLevelOfRequiredSkill) ?? false; } private bool CheckRequiredSkill(MasterSkillDefinition definition, Player player) diff --git a/src/GameLogic/PlayerActions/Craftings/DarkHorseCrafting.cs b/src/GameLogic/PlayerActions/Craftings/DarkHorseCrafting.cs new file mode 100644 index 000000000..c19b861bb --- /dev/null +++ b/src/GameLogic/PlayerActions/Craftings/DarkHorseCrafting.cs @@ -0,0 +1,40 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.GameLogic.PlayerActions.Craftings; + +using MUnique.OpenMU.DataModel.Configuration.ItemCrafting; +using MUnique.OpenMU.DataModel.Configuration.Items; +using MUnique.OpenMU.GameLogic.PlayerActions.Items; + +/// +/// Crafting for Dark Horse. +/// +public class DarkHorseCrafting : SimpleItemCraftingHandler +{ + /// + /// Initializes a new instance of the class. + /// + /// The settings. + public DarkHorseCrafting(SimpleCraftingSettings settings) + : base(settings) + { + } + + /// + protected override void AddRandomItemOption(Item resultItem, Player player, byte successRate) + { + if (resultItem.Definition!.PossibleItemOptions.FirstOrDefault(o => + o.PossibleOptions.Any(p => p.OptionType == ItemOptionTypes.DarkHorse)) + is { } horseOptions) + { + foreach (var option in horseOptions.PossibleOptions) + { + var link = player.PersistenceContext.CreateNew(); + link.ItemOption = option; + resultItem.ItemOptions.Add(link); + } + } + } +} \ No newline at end of file diff --git a/src/GameLogic/PlayerActions/ItemConsumeActions/ItemUpgradeConsumeHandlerPlugIn.cs b/src/GameLogic/PlayerActions/ItemConsumeActions/ItemUpgradeConsumeHandlerPlugIn.cs index 316e34ba6..468920d7e 100644 --- a/src/GameLogic/PlayerActions/ItemConsumeActions/ItemUpgradeConsumeHandlerPlugIn.cs +++ b/src/GameLogic/PlayerActions/ItemConsumeActions/ItemUpgradeConsumeHandlerPlugIn.cs @@ -88,9 +88,9 @@ protected virtual bool TryUpgradeItemOption(Item item) return false; } - var itemOption = item.ItemOptions.First(o => o.ItemOption?.OptionType == this.Configuration.OptionType); - var increasableOption = itemOption.ItemOption; - var higherOptionPossible = increasableOption?.LevelDependentOptions.Any(o => o.Level > itemOption.Level && o.RequiredItemLevel <= item.Level) ?? false; + var itemOptions = item.ItemOptions.Where(o => o.ItemOption?.OptionType == this.Configuration.OptionType); + var increasableOption = itemOptions.First().ItemOption; + var higherOptionPossible = increasableOption?.LevelDependentOptions.Any(o => o.Level > itemOptions.First().Level && o.RequiredItemLevel <= item.Level) ?? false; if (!higherOptionPossible) { return false; @@ -98,11 +98,18 @@ protected virtual bool TryUpgradeItemOption(Item item) if (Rand.NextRandomBool(this.Configuration.SuccessChance)) { - itemOption.Level++; + foreach (var itemOption in itemOptions) + { + itemOption.Level++; + } } else { - this.HandleFailedUpgrade(item, itemOption); + var totalOptions = itemOptions.Count(); + for (int i = 0; i < totalOptions; i++) + { + this.HandleFailedUpgrade(item, itemOptions.First()); + } } return true; @@ -168,6 +175,15 @@ private bool TryAddItemOption(Item item, IContext persistenceContext) // ItemOptionTypes.Option optionLink.ItemOption = possibleOptions.SelectRandom(); optionLink.Level = 1; + + if (item.Definition.Group == 0 && item.Definition.BasePowerUpAttributes.Any(bpua => bpua.TargetAttribute == Stats.StaffRise)) + { + // Double item option MG sword + var doubleOptionLink = persistenceContext.CreateNew(); + doubleOptionLink.ItemOption = possibleOptions.First(o => o != optionLink.ItemOption); + doubleOptionLink.Level = 1; + item.ItemOptions.Add(doubleOptionLink); + } } item.ItemOptions.Add(optionLink); diff --git a/src/GameLogic/PlayerActions/Quests/ElfSoldierBuffRequestAction.cs b/src/GameLogic/PlayerActions/Quests/ElfSoldierBuffRequestAction.cs index 1a4efae13..5af09eda2 100644 --- a/src/GameLogic/PlayerActions/Quests/ElfSoldierBuffRequestAction.cs +++ b/src/GameLogic/PlayerActions/Quests/ElfSoldierBuffRequestAction.cs @@ -50,8 +50,8 @@ public async ValueTask RequestBuffAsync(Player player) await player.MagicEffectList.AddEffectAsync(new MagicEffect( TimeSpan.FromMinutes(60), BuffEffect, - new MagicEffect.ElementWithTarget(new ConstantElement(50 + (player.Level / 5)), Stats.DefenseBase), - new MagicEffect.ElementWithTarget(new ConstantElement(45 + (player.Level / 3)), Stats.BaseDamageBonus))).ConfigureAwait(false); + new MagicEffect.ElementWithTarget(new ConstantElement(50 + (player.Level / 5), stage: 3), Stats.DefenseBase), + new MagicEffect.ElementWithTarget(new ConstantElement(45 + (player.Level / 3)), Stats.GreaterDamageBonus))).ConfigureAwait(false); } private sealed class SoldierBuffMagicEffectDefinition : MagicEffectDefinition diff --git a/src/GameLogic/PlayerActions/Skills/ForceSkillAction.cs b/src/GameLogic/PlayerActions/Skills/ForceSkillAction.cs index 53e7ce853..ae4217784 100644 --- a/src/GameLogic/PlayerActions/Skills/ForceSkillAction.cs +++ b/src/GameLogic/PlayerActions/Skills/ForceSkillAction.cs @@ -5,6 +5,7 @@ namespace MUnique.OpenMU.GameLogic.PlayerActions.Skills; using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic.Attributes; using MUnique.OpenMU.PlugIns; /// @@ -22,8 +23,13 @@ public class ForceSkillAction : TargetedSkillDefaultPlugin /// public override async ValueTask PerformSkillAsync(Player player, IAttackable target, ushort skillId) { - // Special handling of force wave skill. The client might send skill id 60, - // even though it's performing force wave. - await base.PerformSkillAsync(player, target, ForceWaveSkillId).ConfigureAwait(false); + // If there is an equipped scepter with skill, force wave skill is to be used instead + if (player.Attributes is { } attr && attr[Stats.IsScepterEquipped] > 0 + && (player.Inventory?.EquippedItems.FirstOrDefault(item => item.ItemSlot == InventoryConstants.LeftHandSlot)?.HasSkill ?? false)) + { + skillId = ForceWaveSkillId; + } + + await base.PerformSkillAsync(player, target, skillId).ConfigureAwait(false); } } \ No newline at end of file diff --git a/src/GameLogic/PlayerActions/Skills/ForceWaveStrengSkillAction.cs b/src/GameLogic/PlayerActions/Skills/ForceWaveStrengSkillAction.cs new file mode 100644 index 000000000..8869f5d6d --- /dev/null +++ b/src/GameLogic/PlayerActions/Skills/ForceWaveStrengSkillAction.cs @@ -0,0 +1,35 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.GameLogic.PlayerActions.Skills; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.PlugIns; + +/// +/// The Force Wave Strengthener skill action. +/// +[PlugIn(nameof(ForceWaveStrengSkillAction), "Handles the force wave strengthener skill of the dark lord.")] +[Guid("9072ce9c-1482-4838-ba0a-4c312062e090")] +public class ForceWaveStrengSkillAction : TargetedSkillDefaultPlugin +{ + private const ushort ForceWaveStrengSkillAltId = 5090; + + /// + public override short Key => 509; + + /// + public override async ValueTask PerformSkillAsync(Player player, IAttackable target, ushort skillId) + { + // If there is an equipped scepter with skill, we call the alt master skill with force wave as its related skill + if (player.Attributes is { } attr && attr[Stats.IsScepterEquipped] > 0 + && (player.Inventory?.EquippedItems.FirstOrDefault(item => item.ItemSlot == InventoryConstants.LeftHandSlot)?.HasSkill ?? false)) + { + skillId = ForceWaveStrengSkillAltId; + } + + await base.PerformSkillAsync(player, target, skillId).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameLogic/PlayerActions/Skills/SoulBarrierProficieSkillAction.cs b/src/GameLogic/PlayerActions/Skills/SoulBarrierProficieSkillAction.cs new file mode 100644 index 000000000..e44d520d2 --- /dev/null +++ b/src/GameLogic/PlayerActions/Skills/SoulBarrierProficieSkillAction.cs @@ -0,0 +1,19 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.GameLogic.PlayerActions.Skills; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.PlugIns; + +/// +/// The Soul Barrier Proficiency skill action. +/// +[PlugIn(nameof(SoulBarrierProficieSkillAction), "Handles the soul barrier proficiency skill of the grand master.")] +[Guid("9c56073f-1719-423c-8397-30d94793f929")] +public class SoulBarrierProficieSkillAction : SoulBarrierStrengSkillAction +{ + /// + public override short Key => 404; +} \ No newline at end of file diff --git a/src/GameLogic/PlayerActions/Skills/SoulBarrierStrengSkillAction.cs b/src/GameLogic/PlayerActions/Skills/SoulBarrierStrengSkillAction.cs new file mode 100644 index 000000000..55fe85f83 --- /dev/null +++ b/src/GameLogic/PlayerActions/Skills/SoulBarrierStrengSkillAction.cs @@ -0,0 +1,93 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.GameLogic.PlayerActions.Skills; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.AttributeSystem; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.World; +using MUnique.OpenMU.PlugIns; + +/// +/// The Soul Barrier Strengthener skill action. +/// +[PlugIn(nameof(SoulBarrierStrengSkillAction), "Handles the soul barrier strengthener skill of the grand master.")] +[Guid("05fdea2a-ac92-4b2c-8305-001e97ec26a8")] +public class SoulBarrierStrengSkillAction : TargetedSkillDefaultPlugin +{ + private const ushort SoulBarrierStrengSkilId = 403; + private const ushort SoulBarrierProficieSkilId = 404; + + /// + public override short Key => 403; + + /// + public override async ValueTask PerformSkillAsync(Player player, IAttackable target, ushort skillId) + { + var skillEntry = player.SkillList!.GetSkill(skillId); + var skill = skillEntry?.Skill; + if (skill is null) + { + return; + } + + var miniGame = player.CurrentMiniGame; + var inMiniGame = miniGame is { }; + var isBuff = skill.SkillType is SkillType.Buff or SkillType.Regeneration; + if (player.IsAtSafezone() && !(inMiniGame && isBuff)) + { + return; + } + + if (inMiniGame && !miniGame!.IsSkillAllowed(skill, player, target)) + { + return; + } + + if (!target.IsActive()) + { + return; + } + + if (!target.CheckSkillTargetRestrictions(player, skill)) + { + return; + } + + if (!player.IsInRange(target.Position, skill.Range + 2)) + { + // target position might be out of sync so we send the current coordinates to the client again. + if (!(target is ISupportWalk { IsWalking: true })) + { + await player.InvokeViewPlugInAsync(p => p.ObjectMovedAsync(target, MoveType.Instant)).ConfigureAwait(false); + } + + return; + } + + if (!await player.TryConsumeForSkillAsync(skill).ConfigureAwait(false)) + { + return; + } + + if (skillEntry!.PowerUps is null) + { + player.CreateMagicEffectPowerUp(skillEntry); + + var strengSkillLevel = skillId == SoulBarrierProficieSkilId ? player.SkillList!.GetSkill(SoulBarrierStrengSkilId) : skillEntry; + skillEntry.PowerUps = + [ + .. skillEntry.PowerUps!, + (Stats.SoulBarrierManaTollPerHit, new AttributeRelationshipElement( + [player.Attributes!.GetOrCreateAttribute(Stats.MaximumMana)], + new ConstantElement(strengSkillLevel!.Level * 0.001f), // extra 0.1% per streng skill level + InputOperator.Multiply)) + ]; + } + + await AttackableExtensions.ApplyMagicEffectAsync(target, player, skillEntry).ConfigureAwait(false); + await player.ForEachWorldObserverAsync(p => p.ShowSkillAnimationAsync(player, target, skill, true), true).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameLogic/PlayerActions/Skills/TargetedSkillDefaultPlugin.cs b/src/GameLogic/PlayerActions/Skills/TargetedSkillDefaultPlugin.cs index 5e3aa9529..6cc705fb7 100644 --- a/src/GameLogic/PlayerActions/Skills/TargetedSkillDefaultPlugin.cs +++ b/src/GameLogic/PlayerActions/Skills/TargetedSkillDefaultPlugin.cs @@ -159,6 +159,11 @@ private async ValueTask ApplySkillAsync(Player player, IAttackable targete { if (skill.SkillType == SkillType.DirectHit || skill.SkillType == SkillType.CastleSiegeSkill) { + if (player.Attributes![Stats.AmmunitionConsumptionRate] > player.Attributes[Stats.AmmunitionAmount]) + { + break; + } + if (!target.IsAtSafezone() && !player.IsAtSafezone() && target != player) { await target.AttackByAsync(player, skillEntry, isCombo).ConfigureAwait(false); diff --git a/src/GameLogic/PlayerActions/Skills/TargetedSkillPluginBase.cs b/src/GameLogic/PlayerActions/Skills/TargetedSkillPluginBase.cs index e51dd75f5..08fdcaf22 100644 --- a/src/GameLogic/PlayerActions/Skills/TargetedSkillPluginBase.cs +++ b/src/GameLogic/PlayerActions/Skills/TargetedSkillPluginBase.cs @@ -1,4 +1,4 @@ -// +// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.GameLogic.PlayerActions.Skills; diff --git a/src/GameLogic/PlugIns/ChatCommands/ItemChatCommandPlugIn.cs b/src/GameLogic/PlugIns/ChatCommands/ItemChatCommandPlugIn.cs index ead5d2cbd..786457fed 100644 --- a/src/GameLogic/PlugIns/ChatCommands/ItemChatCommandPlugIn.cs +++ b/src/GameLogic/PlugIns/ChatCommands/ItemChatCommandPlugIn.cs @@ -101,7 +101,7 @@ private static void AddOption(TemporaryItem item, ItemChatCommandArgs arguments) if ((arguments.Opt & 4) > 0) { - itemOption = allOptions.First(o => o.PowerUpDefinition!.TargetAttribute == Stats.AttackSpeed); + itemOption = allOptions.First(o => o.PowerUpDefinition!.TargetAttribute == Stats.AttackSpeedAny); var dinoOptionLink = new ItemOptionLink { ItemOption = itemOption, Level = 4 }; item.ItemOptions.Add(dinoOptionLink); } diff --git a/src/GameLogic/SkillList.cs b/src/GameLogic/SkillList.cs index 1463b1ed7..3b86dc920 100644 --- a/src/GameLogic/SkillList.cs +++ b/src/GameLogic/SkillList.cs @@ -88,6 +88,15 @@ public async ValueTask AddLearnedSkillAsync(Skill skill) skillEntry.Level = 0; await this.AddLearnedSkillAsync(skillEntry).ConfigureAwait(false); + if (skill.Number == 509) // Force Wave Streng + { + var forceWaveStrAltSkillEntry = this._player.PersistenceContext.CreateNew(); + forceWaveStrAltSkillEntry.Skill = this._player.GameContext.Configuration.Skills.FirstOrDefault(s => s.Number == 5090); + forceWaveStrAltSkillEntry.Level = 0; + this._availableSkills.Add(forceWaveStrAltSkillEntry.Skill!.Number.ToUnsigned(), forceWaveStrAltSkillEntry); + this._learnedSkills.Add(forceWaveStrAltSkillEntry); + } + if (skill.MasterDefinition?.ReplacedSkill is { } replacedSkill) { await this._player.InvokeViewPlugInAsync(p => p.RemoveSkillAsync(replacedSkill)).ConfigureAwait(false); @@ -213,6 +222,8 @@ public PassiveSkillBoostPowerUp(SkillEntry skillEntry) public AggregateType AggregateType { get; } + public byte Stage { get; } + public void Dispose() { this._skillEntry.PropertyChanged -= this.OnSkillEntryOnPropertyChanged; diff --git a/src/GameServer/RemoteView/World/DeActivateMagicEffectPlugIn.cs b/src/GameServer/RemoteView/World/DeActivateMagicEffectPlugIn.cs index 6de880e24..7ccccd352 100644 --- a/src/GameServer/RemoteView/World/DeActivateMagicEffectPlugIn.cs +++ b/src/GameServer/RemoteView/World/DeActivateMagicEffectPlugIn.cs @@ -26,7 +26,7 @@ public class DeActivateMagicEffectPlugIn : IActivateMagicEffectPlugIn, IDeactiva private static readonly ReadOnlyDictionary EffectTypeMapping = new( new Dictionary { - { Stats.AttackSpeed, EffectItemConsumption.EffectType.AttackSpeed }, + { Stats.AttackSpeedAny, EffectItemConsumption.EffectType.AttackSpeed }, { Stats.BaseDamageBonus, EffectItemConsumption.EffectType.Damage }, { Stats.DefenseBase, EffectItemConsumption.EffectType.Defense }, { Stats.MaximumHealth, EffectItemConsumption.EffectType.MaximumHealth }, diff --git a/src/GameServer/RemoteView/World/NewPlayersInScopeExtendedPlugIn.cs b/src/GameServer/RemoteView/World/NewPlayersInScopeExtendedPlugIn.cs index aec8032f8..d9487fdd8 100644 --- a/src/GameServer/RemoteView/World/NewPlayersInScopeExtendedPlugIn.cs +++ b/src/GameServer/RemoteView/World/NewPlayersInScopeExtendedPlugIn.cs @@ -85,7 +85,7 @@ int Write() packet.Rotation = newPlayer.Rotation.ToPacketByte(); packet.HeroState = selectedCharacter.State.Convert(); packet.AttackSpeed = (ushort)(newPlayer.Attributes?[Stats.AttackSpeed] ?? 0); - packet.MagicSpeed = (ushort)(newPlayer.Attributes?[Stats.AttackSpeed] ?? 0); // TODO: Implement MagicSpeed + packet.MagicSpeed = (ushort)(newPlayer.Attributes?[Stats.MagicSpeed] ?? 0); appearanceSerializer.WriteAppearanceData(packet.AppearanceAndEffects, newPlayer.AppearanceData, true); diff --git a/src/GameServer/RemoteView/World/ShowSkillAnimationPlugIn.cs b/src/GameServer/RemoteView/World/ShowSkillAnimationPlugIn.cs index c5ba3402c..1e7cae62f 100644 --- a/src/GameServer/RemoteView/World/ShowSkillAnimationPlugIn.cs +++ b/src/GameServer/RemoteView/World/ShowSkillAnimationPlugIn.cs @@ -30,6 +30,8 @@ public class ShowSkillAnimationPlugIn : IShowSkillAnimationPlugIn private const ushort NovaStartSkillId = 58; private const short ForceSkillId = 60; private const short ForceWaveSkillId = 66; + private const short ForceWaveStrSkillId = 509; + private const short ForceWaveStrAltSkillId = 5090; private readonly RemotePlayer _player; @@ -52,6 +54,14 @@ public async ValueTask ShowSkillAnimationAsync(IAttacker attacker, IAttackable? { skillNumber = ForceSkillId; } + else if (skillNumber == ForceWaveStrAltSkillId) + { + skillNumber = ForceWaveStrSkillId; + } + else + { + // nothing to do + } var playerId = attacker.GetId(this._player); var targetId = target.GetId(this._player); diff --git a/src/Persistence/BasicModel/AttributeRelationship.Custom.cs b/src/Persistence/BasicModel/AttributeRelationship.Custom.cs index 5d512d782..a3cd46b1e 100644 --- a/src/Persistence/BasicModel/AttributeRelationship.Custom.cs +++ b/src/Persistence/BasicModel/AttributeRelationship.Custom.cs @@ -2,10 +2,10 @@ // Licensed under the MIT License. See LICENSE file in the project root for full license information. // -using MUnique.OpenMU.DataModel; - namespace MUnique.OpenMU.Persistence.BasicModel; +using MUnique.OpenMU.DataModel; + /// /// A plain implementation of . /// @@ -39,5 +39,7 @@ public virtual void AssignValuesOf(AttributeSystem.AttributeRelationship other, this.TargetAttribute = gameConfiguration.Attributes.FirstOrDefault(a => a.Id == other.TargetAttribute?.Id) ?? other.TargetAttribute; this.InputOperand = other.InputOperand; this.InputOperator = other.InputOperator; + this.AggregateType = other.AggregateType; + this.Stage = other.Stage; } } \ No newline at end of file diff --git a/src/Persistence/BasicModel/AttributeRelationship.Generated.cs b/src/Persistence/BasicModel/AttributeRelationship.Generated.cs index 43f538f41..635bf0075 100644 --- a/src/Persistence/BasicModel/AttributeRelationship.Generated.cs +++ b/src/Persistence/BasicModel/AttributeRelationship.Generated.cs @@ -25,20 +25,20 @@ public AttributeRelationship() } /// - public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, System.Single inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute) - : base(targetAttribute, inputOperand, inputAttribute) + public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, System.Single inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute, MUnique.OpenMU.AttributeSystem.AggregateType aggregateType, System.Byte stage) + : base(targetAttribute, inputOperand, inputAttribute, aggregateType, stage) { } /// - public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute) - : base(targetAttribute, inputOperand, inputAttribute) + public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute, MUnique.OpenMU.AttributeSystem.AggregateType aggregateType, System.Byte stage) + : base(targetAttribute, inputOperand, inputAttribute, aggregateType, stage) { } /// - public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, System.Single inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute, MUnique.OpenMU.AttributeSystem.InputOperator inputOperator, MUnique.OpenMU.AttributeSystem.AttributeDefinition operandAttribute) - : base(targetAttribute, inputOperand, inputAttribute, inputOperator, operandAttribute) + public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, System.Single inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute, MUnique.OpenMU.AttributeSystem.InputOperator inputOperator, MUnique.OpenMU.AttributeSystem.AttributeDefinition operandAttribute, MUnique.OpenMU.AttributeSystem.AggregateType aggregateType, System.Byte stage) + : base(targetAttribute, inputOperand, inputAttribute, inputOperator, operandAttribute, aggregateType, stage) { } diff --git a/src/Persistence/BasicModel/ConstValueAttribute.Generated.cs b/src/Persistence/BasicModel/ConstValueAttribute.Generated.cs index 559732109..5c9dbf429 100644 --- a/src/Persistence/BasicModel/ConstValueAttribute.Generated.cs +++ b/src/Persistence/BasicModel/ConstValueAttribute.Generated.cs @@ -21,8 +21,8 @@ public partial class ConstValueAttribute : MUnique.OpenMU.AttributeSystem.ConstV { /// - public ConstValueAttribute(System.Single value, MUnique.OpenMU.AttributeSystem.AttributeDefinition definition) - : base(value, definition) + public ConstValueAttribute(System.Single value, MUnique.OpenMU.AttributeSystem.AttributeDefinition definition, MUnique.OpenMU.AttributeSystem.AggregateType aggregateType, System.Byte stage) + : base(value, definition, aggregateType, stage) { } diff --git a/src/Persistence/EntityFramework/EntityDataContext.cs b/src/Persistence/EntityFramework/EntityDataContext.cs index 20ba7d70e..55fe53866 100644 --- a/src/Persistence/EntityFramework/EntityDataContext.cs +++ b/src/Persistence/EntityFramework/EntityDataContext.cs @@ -54,7 +54,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(); modelBuilder.Entity().Apply(); - modelBuilder.Entity().Apply(); modelBuilder.Entity().Apply(); modelBuilder.Entity().Apply(); modelBuilder.Entity().Apply(); diff --git a/src/Persistence/EntityFramework/Extensions/ModelBuilder/AttributeExtensions.cs b/src/Persistence/EntityFramework/Extensions/ModelBuilder/AttributeExtensions.cs index a6c32d15d..1e2c88312 100644 --- a/src/Persistence/EntityFramework/Extensions/ModelBuilder/AttributeExtensions.cs +++ b/src/Persistence/EntityFramework/Extensions/ModelBuilder/AttributeExtensions.cs @@ -12,15 +12,6 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Extensions.ModelBuilder; /// internal static class AttributeExtensions { - /// - /// Applies the settings for the entity. - /// - /// The builder. - public static void Apply(this EntityTypeBuilder builder) - { - builder.Ignore(c => c.AggregateType); - } - /// /// Applies the settings for the entity. /// diff --git a/src/Persistence/EntityFramework/Migrations/20250221154911_AddStageToAttributeEntities.Designer.cs b/src/Persistence/EntityFramework/Migrations/20250221154911_AddStageToAttributeEntities.Designer.cs new file mode 100644 index 000000000..8e3c468a5 --- /dev/null +++ b/src/Persistence/EntityFramework/Migrations/20250221154911_AddStageToAttributeEntities.Designer.cs @@ -0,0 +1,5100 @@ +// +using System; +using MUnique.OpenMU.Persistence.EntityFramework; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations +{ + [DbContext(typeof(EntityDataContext))] + [Migration("20250221154911_AddStageToAttributeEntities")] + partial class AddStageToAttributeEntities + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Account", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChatBanUntil") + .HasColumnType("timestamp with time zone"); + + b.Property("EMail") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsVaultExtended") + .HasColumnType("boolean"); + + b.Property("LoginName") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegistrationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SecurityCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("TimeZone") + .HasColumnType("smallint"); + + b.Property("VaultId") + .HasColumnType("uuid"); + + b.Property("VaultPassword") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("LoginName") + .IsUnique(); + + b.HasIndex("VaultId") + .IsUnique(); + + b.ToTable("Account", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AccountCharacterClass", b => + { + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("CharacterClassId") + .HasColumnType("uuid"); + + b.HasKey("AccountId", "CharacterClassId"); + + b.HasIndex("CharacterClassId"); + + b.ToTable("AccountCharacterClass", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AppearanceData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CharacterClassId") + .HasColumnType("uuid"); + + b.Property("FullAncientSetEquipped") + .HasColumnType("boolean"); + + b.Property("Pose") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("CharacterClassId"); + + b.ToTable("AppearanceData", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AreaSkillSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DelayBetweenHits") + .HasColumnType("interval"); + + b.Property("DelayPerOneDistance") + .HasColumnType("interval"); + + b.Property("FrustumDistance") + .HasColumnType("real"); + + b.Property("FrustumEndWidth") + .HasColumnType("real"); + + b.Property("FrustumStartWidth") + .HasColumnType("real"); + + b.Property("HitChancePerDistanceMultiplier") + .HasColumnType("real"); + + b.Property("MaximumNumberOfHitsPerAttack") + .HasColumnType("integer"); + + b.Property("MaximumNumberOfHitsPerTarget") + .HasColumnType("integer"); + + b.Property("MinimumNumberOfHitsPerTarget") + .HasColumnType("integer"); + + b.Property("TargetAreaDiameter") + .HasColumnType("real"); + + b.Property("UseDeferredHits") + .HasColumnType("boolean"); + + b.Property("UseFrustumFilter") + .HasColumnType("boolean"); + + b.Property("UseTargetAreaFilter") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("AreaSkillSettings", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Designation") + .HasColumnType("text"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("MaximumValue") + .HasColumnType("real"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("AttributeDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeRelationship", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AggregateType") + .HasColumnType("integer"); + + b.Property("CharacterClassId") + .HasColumnType("uuid"); + + b.Property("InputAttributeId") + .HasColumnType("uuid"); + + b.Property("InputOperand") + .HasColumnType("real"); + + b.Property("InputOperator") + .HasColumnType("integer"); + + b.Property("OperandAttributeId") + .HasColumnType("uuid"); + + b.Property("PowerUpDefinitionValueId") + .HasColumnType("uuid"); + + b.Property("Stage") + .HasColumnType("smallint"); + + b.Property("TargetAttributeId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CharacterClassId"); + + b.HasIndex("InputAttributeId"); + + b.HasIndex("OperandAttributeId"); + + b.HasIndex("PowerUpDefinitionValueId"); + + b.HasIndex("TargetAttributeId"); + + b.ToTable("AttributeRelationship", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeRequirement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AttributeId") + .HasColumnType("uuid"); + + b.Property("GameMapDefinitionId") + .HasColumnType("uuid"); + + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.Property("MinimumValue") + .HasColumnType("integer"); + + b.Property("SkillId") + .HasColumnType("uuid"); + + b.Property("SkillId1") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AttributeId"); + + b.HasIndex("GameMapDefinitionId"); + + b.HasIndex("ItemDefinitionId"); + + b.HasIndex("SkillId"); + + b.HasIndex("SkillId1"); + + b.ToTable("AttributeRequirement", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.BattleZoneDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("GroundId") + .HasColumnType("uuid"); + + b.Property("LeftGoalId") + .HasColumnType("uuid"); + + b.Property("LeftTeamSpawnPointX") + .HasColumnType("smallint"); + + b.Property("LeftTeamSpawnPointY") + .HasColumnType("smallint"); + + b.Property("RightGoalId") + .HasColumnType("uuid"); + + b.Property("RightTeamSpawnPointX") + .HasColumnType("smallint"); + + b.Property("RightTeamSpawnPointY") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GroundId") + .IsUnique(); + + b.HasIndex("LeftGoalId") + .IsUnique(); + + b.HasIndex("RightGoalId") + .IsUnique(); + + b.ToTable("BattleZoneDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("CharacterClassId") + .HasColumnType("uuid"); + + b.Property("CharacterSlot") + .HasColumnType("smallint"); + + b.Property("CharacterStatus") + .HasColumnType("integer"); + + b.Property("CreateDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CurrentMapId") + .HasColumnType("uuid"); + + b.Property("Experience") + .HasColumnType("bigint"); + + b.Property("InventoryExtensions") + .HasColumnType("integer"); + + b.Property("InventoryId") + .HasColumnType("uuid"); + + b.Property("KeyConfiguration") + .HasColumnType("bytea"); + + b.Property("LevelUpPoints") + .HasColumnType("integer"); + + b.Property("MasterExperience") + .HasColumnType("bigint"); + + b.Property("MasterLevelUpPoints") + .HasColumnType("integer"); + + b.Property("MuHelperConfiguration") + .HasColumnType("bytea"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("PlayerKillCount") + .HasColumnType("integer"); + + b.Property("Pose") + .HasColumnType("smallint"); + + b.Property("PositionX") + .HasColumnType("smallint"); + + b.Property("PositionY") + .HasColumnType("smallint"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("StateRemainingSeconds") + .HasColumnType("integer"); + + b.Property("UsedFruitPoints") + .HasColumnType("integer"); + + b.Property("UsedNegFruitPoints") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("CharacterClassId"); + + b.HasIndex("CurrentMapId"); + + b.HasIndex("InventoryId") + .IsUnique(); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Character", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CanGetCreated") + .HasColumnType("boolean"); + + b.Property("ComboDefinitionId") + .HasColumnType("uuid"); + + b.Property("CreationAllowedFlag") + .HasColumnType("smallint"); + + b.Property("FruitCalculation") + .HasColumnType("integer"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("HomeMapId") + .HasColumnType("uuid"); + + b.Property("IsMasterClass") + .HasColumnType("boolean"); + + b.Property("LevelRequirementByCreation") + .HasColumnType("smallint"); + + b.Property("LevelWarpRequirementReductionPercent") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("NextGenerationClassId") + .HasColumnType("uuid"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("ComboDefinitionId") + .IsUnique(); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("HomeMapId"); + + b.HasIndex("NextGenerationClassId"); + + b.ToTable("CharacterClass", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterDropItemGroup", b => + { + b.Property("CharacterId") + .HasColumnType("uuid"); + + b.Property("DropItemGroupId") + .HasColumnType("uuid"); + + b.HasKey("CharacterId", "DropItemGroupId"); + + b.HasIndex("DropItemGroupId"); + + b.ToTable("CharacterDropItemGroup", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterQuestState", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActiveQuestId") + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("uuid"); + + b.Property("ClientActionPerformed") + .HasColumnType("boolean"); + + b.Property("Group") + .HasColumnType("smallint"); + + b.Property("LastFinishedQuestId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ActiveQuestId"); + + b.HasIndex("CharacterId"); + + b.HasIndex("LastFinishedQuestId"); + + b.ToTable("CharacterQuestState", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ChatServerDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ClientCleanUpInterval") + .HasColumnType("interval"); + + b.Property("ClientTimeout") + .HasColumnType("interval"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("MaximumConnections") + .HasColumnType("integer"); + + b.Property("RoomCleanUpInterval") + .HasColumnType("interval"); + + b.Property("ServerId") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("ChatServerDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ChatServerEndpoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChatServerDefinitionId") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasColumnType("uuid"); + + b.Property("NetworkPort") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ChatServerDefinitionId"); + + b.HasIndex("ClientId"); + + b.ToTable("ChatServerEndpoint", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CombinationBonusRequirement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ItemOptionCombinationBonusId") + .HasColumnType("uuid"); + + b.Property("MinimumCount") + .HasColumnType("integer"); + + b.Property("OptionTypeId") + .HasColumnType("uuid"); + + b.Property("SubOptionType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ItemOptionCombinationBonusId"); + + b.HasIndex("OptionTypeId"); + + b.ToTable("CombinationBonusRequirement", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ConfigurationUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("InstalledAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ConfigurationUpdate", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ConfigurationUpdateState", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrentInstalledVersion") + .HasColumnType("integer"); + + b.Property("InitializationKey") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ConfigurationUpdateState", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ConnectServerDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CheckMaxConnectionsPerAddress") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("uuid"); + + b.Property("ClientListenerPort") + .HasColumnType("integer"); + + b.Property("CurrentPatchVersion") + .HasColumnType("bytea"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("DisconnectOnUnknownPacket") + .HasColumnType("boolean"); + + b.Property("ListenerBacklog") + .HasColumnType("integer"); + + b.Property("MaxConnections") + .HasColumnType("integer"); + + b.Property("MaxConnectionsPerAddress") + .HasColumnType("integer"); + + b.Property("MaxFtpRequests") + .HasColumnType("integer"); + + b.Property("MaxIpRequests") + .HasColumnType("integer"); + + b.Property("MaxServerListRequests") + .HasColumnType("integer"); + + b.Property("MaximumReceiveSize") + .HasColumnType("smallint"); + + b.Property("PatchAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("ServerId") + .HasColumnType("smallint"); + + b.Property("Timeout") + .HasColumnType("interval"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ConnectServerDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ConstValueAttribute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AggregateType") + .HasColumnType("integer"); + + b.Property("CharacterClassId") + .HasColumnType("uuid"); + + b.Property("DefinitionId") + .HasColumnType("uuid"); + + b.Property("Stage") + .HasColumnType("smallint"); + + b.Property("Value") + .HasColumnType("real"); + + b.HasKey("Id"); + + b.HasIndex("CharacterClassId"); + + b.HasIndex("DefinitionId"); + + b.ToTable("ConstValueAttribute", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Chance") + .HasColumnType("double precision"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("ItemLevel") + .HasColumnType("smallint"); + + b.Property("ItemType") + .HasColumnType("integer"); + + b.Property("MaximumMonsterLevel") + .HasColumnType("smallint"); + + b.Property("MinimumMonsterLevel") + .HasColumnType("smallint"); + + b.Property("MonsterId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("MonsterId"); + + b.ToTable("DropItemGroup", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroupItemDefinition", b => + { + b.Property("DropItemGroupId") + .HasColumnType("uuid"); + + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("DropItemGroupId", "ItemDefinitionId"); + + b.HasIndex("ItemDefinitionId"); + + b.ToTable("DropItemGroupItemDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DuelArea", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DuelConfigurationId") + .HasColumnType("uuid"); + + b.Property("FirstPlayerGateId") + .HasColumnType("uuid"); + + b.Property("Index") + .HasColumnType("smallint"); + + b.Property("SecondPlayerGateId") + .HasColumnType("uuid"); + + b.Property("SpectatorsGateId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("DuelConfigurationId"); + + b.HasIndex("FirstPlayerGateId"); + + b.HasIndex("SecondPlayerGateId"); + + b.HasIndex("SpectatorsGateId"); + + b.ToTable("DuelArea", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DuelConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntranceFee") + .HasColumnType("integer"); + + b.Property("ExitId") + .HasColumnType("uuid"); + + b.Property("MaximumScore") + .HasColumnType("integer"); + + b.Property("MaximumSpectatorsPerDuelRoom") + .HasColumnType("integer"); + + b.Property("MinimumCharacterLevel") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ExitId"); + + b.ToTable("DuelConfiguration", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.EnterGate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("GameMapDefinitionId") + .HasColumnType("uuid"); + + b.Property("LevelRequirement") + .HasColumnType("smallint"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("TargetGateId") + .HasColumnType("uuid"); + + b.Property("X1") + .HasColumnType("smallint"); + + b.Property("X2") + .HasColumnType("smallint"); + + b.Property("Y1") + .HasColumnType("smallint"); + + b.Property("Y2") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("GameMapDefinitionId"); + + b.HasIndex("TargetGateId"); + + b.ToTable("EnterGate", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Direction") + .HasColumnType("integer"); + + b.Property("IsSpawnGate") + .HasColumnType("boolean"); + + b.Property("MapId") + .HasColumnType("uuid"); + + b.Property("X1") + .HasColumnType("smallint"); + + b.Property("X2") + .HasColumnType("smallint"); + + b.Property("Y1") + .HasColumnType("smallint"); + + b.Property("Y2") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("MapId"); + + b.ToTable("ExitGate", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Friend", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("CharacterId") + .HasColumnType("uuid"); + + b.Property("FriendId") + .HasColumnType("uuid"); + + b.Property("RequestOpen") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasAlternateKey("CharacterId", "FriendId"); + + b.ToTable("Friend", "friend"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameClientDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Episode") + .HasColumnType("smallint"); + + b.Property("Language") + .HasColumnType("integer"); + + b.Property("Season") + .HasColumnType("smallint"); + + b.Property("Serial") + .HasColumnType("bytea"); + + b.Property("Version") + .HasColumnType("bytea"); + + b.HasKey("Id"); + + b.ToTable("GameClientDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AreaSkillHitsPlayer") + .HasColumnType("boolean"); + + b.Property("CharacterNameRegex") + .HasColumnType("text"); + + b.Property("DamagePerOneItemDurability") + .HasColumnType("double precision"); + + b.Property("DamagePerOnePetDurability") + .HasColumnType("double precision"); + + b.Property("DuelConfigurationId") + .HasColumnType("uuid"); + + b.Property("ExperienceFormula") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue("if(level == 0, 0, if(level < 256, 10 * (level + 8) * (level - 1) * (level - 1), (10 * (level + 8) * (level - 1) * (level - 1)) + (1000 * (level - 247) * (level - 256) * (level - 256))))"); + + b.Property("ExperienceRate") + .HasColumnType("real"); + + b.Property("HitsPerOneItemDurability") + .HasColumnType("double precision"); + + b.Property("InfoRange") + .HasColumnType("smallint"); + + b.Property("ItemDropDuration") + .ValueGeneratedOnAdd() + .HasColumnType("interval") + .HasDefaultValue(new TimeSpan(0, 0, 1, 0, 0)); + + b.Property("LetterSendPrice") + .HasColumnType("integer"); + + b.Property("MasterExperienceFormula") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue("(505 * level * level * level) + (35278500 * level) + (228045 * level * level)"); + + b.Property("MaximumCharactersPerAccount") + .HasColumnType("smallint"); + + b.Property("MaximumInventoryMoney") + .HasColumnType("integer"); + + b.Property("MaximumItemOptionLevelDrop") + .HasColumnType("smallint"); + + b.Property("MaximumLetters") + .HasColumnType("integer"); + + b.Property("MaximumLevel") + .HasColumnType("smallint"); + + b.Property("MaximumMasterLevel") + .HasColumnType("smallint"); + + b.Property("MaximumPartySize") + .HasColumnType("smallint"); + + b.Property("MaximumPasswordLength") + .HasColumnType("integer"); + + b.Property("MaximumVaultMoney") + .HasColumnType("integer"); + + b.Property("MinimumMonsterLevelForMasterExperience") + .HasColumnType("smallint"); + + b.Property("RecoveryInterval") + .HasColumnType("integer"); + + b.Property("ShouldDropMoney") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("DuelConfigurationId") + .IsUnique(); + + b.ToTable("GameConfiguration", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BattleZoneId") + .HasColumnType("uuid"); + + b.Property("Discriminator") + .HasColumnType("integer"); + + b.Property("ExpMultiplier") + .HasColumnType("double precision"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("SafezoneMapId") + .HasColumnType("uuid"); + + b.Property("TerrainData") + .HasColumnType("bytea"); + + b.HasKey("Id"); + + b.HasIndex("BattleZoneId") + .IsUnique(); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("SafezoneMapId"); + + b.ToTable("GameMapDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinitionDropItemGroup", b => + { + b.Property("GameMapDefinitionId") + .HasColumnType("uuid"); + + b.Property("DropItemGroupId") + .HasColumnType("uuid"); + + b.HasKey("GameMapDefinitionId", "DropItemGroupId"); + + b.HasIndex("DropItemGroupId"); + + b.ToTable("GameMapDefinitionDropItemGroup", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MaximumPlayers") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("GameServerConfiguration", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerConfigurationGameMapDefinition", b => + { + b.Property("GameServerConfigurationId") + .HasColumnType("uuid"); + + b.Property("GameMapDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("GameServerConfigurationId", "GameMapDefinitionId"); + + b.HasIndex("GameMapDefinitionId"); + + b.ToTable("GameServerConfigurationGameMapDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExperienceRate") + .HasColumnType("real"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("PvpEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ServerConfigurationId") + .HasColumnType("uuid"); + + b.Property("ServerID") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("ServerConfigurationId"); + + b.ToTable("GameServerDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerEndpoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AlternativePublishedPort") + .HasColumnType("integer"); + + b.Property("ClientId") + .HasColumnType("uuid"); + + b.Property("GameServerDefinitionId") + .HasColumnType("uuid"); + + b.Property("NetworkPort") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("GameServerDefinitionId"); + + b.ToTable("GameServerEndpoint", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Guild", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllianceGuildId") + .HasColumnType("uuid"); + + b.Property("HostilityId") + .HasColumnType("uuid"); + + b.Property("Logo") + .HasColumnType("bytea"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("character varying(8)"); + + b.Property("Notice") + .HasColumnType("text"); + + b.Property("Score") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("AllianceGuildId"); + + b.HasIndex("HostilityId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Guild", "guild"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GuildMember", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("GuildId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.ToTable("GuildMember", "guild"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.IncreasableItemOption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ItemOptionDefinitionId") + .HasColumnType("uuid"); + + b.Property("LevelType") + .HasColumnType("integer"); + + b.Property("Number") + .HasColumnType("integer"); + + b.Property("OptionTypeId") + .HasColumnType("uuid"); + + b.Property("PowerUpDefinitionId") + .HasColumnType("uuid"); + + b.Property("SubOptionType") + .HasColumnType("integer"); + + b.Property("Weight") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("ItemOptionDefinitionId"); + + b.HasIndex("OptionTypeId"); + + b.HasIndex("PowerUpDefinitionId") + .IsUnique(); + + b.ToTable("IncreasableItemOption", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefinitionId") + .HasColumnType("uuid"); + + b.Property("Durability") + .HasColumnType("double precision"); + + b.Property("HasSkill") + .HasColumnType("boolean"); + + b.Property("ItemSlot") + .HasColumnType("smallint"); + + b.Property("ItemStorageId") + .HasColumnType("uuid"); + + b.Property("Level") + .HasColumnType("smallint"); + + b.Property("PetExperience") + .HasColumnType("integer"); + + b.Property("SocketCount") + .HasColumnType("integer"); + + b.Property("StorePrice") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("DefinitionId"); + + b.HasIndex("ItemStorageId"); + + b.ToTable("Item", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemAppearance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppearanceDataId") + .HasColumnType("uuid"); + + b.Property("DefinitionId") + .HasColumnType("uuid"); + + b.Property("ItemSlot") + .HasColumnType("smallint"); + + b.Property("Level") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AppearanceDataId"); + + b.HasIndex("DefinitionId"); + + b.ToTable("ItemAppearance", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemAppearanceItemOptionType", b => + { + b.Property("ItemAppearanceId") + .HasColumnType("uuid"); + + b.Property("ItemOptionTypeId") + .HasColumnType("uuid"); + + b.HasKey("ItemAppearanceId", "ItemOptionTypeId"); + + b.HasIndex("ItemOptionTypeId"); + + b.ToTable("ItemAppearanceItemOptionType", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemBasePowerUpDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AggregateType") + .HasColumnType("integer"); + + b.Property("BaseValue") + .HasColumnType("real"); + + b.Property("BonusPerLevelTableId") + .HasColumnType("uuid"); + + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.Property("Stage") + .HasColumnType("smallint"); + + b.Property("TargetAttributeId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("BonusPerLevelTableId"); + + b.HasIndex("ItemDefinitionId"); + + b.HasIndex("TargetAttributeId"); + + b.ToTable("ItemBasePowerUpDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCrafting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ItemCraftingHandlerClassName") + .IsRequired() + .HasColumnType("text"); + + b.Property("MonsterDefinitionId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("SimpleCraftingSettingsId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("MonsterDefinitionId"); + + b.HasIndex("SimpleCraftingSettingsId") + .IsUnique(); + + b.ToTable("ItemCrafting", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddPercentage") + .HasColumnType("smallint"); + + b.Property("FailResult") + .HasColumnType("integer"); + + b.Property("MaximumAmount") + .HasColumnType("smallint"); + + b.Property("MaximumItemLevel") + .HasColumnType("smallint"); + + b.Property("MinimumAmount") + .HasColumnType("smallint"); + + b.Property("MinimumItemLevel") + .HasColumnType("smallint"); + + b.Property("NpcPriceDivisor") + .HasColumnType("integer"); + + b.Property("Reference") + .HasColumnType("smallint"); + + b.Property("SimpleCraftingSettingsId") + .HasColumnType("uuid"); + + b.Property("SuccessResult") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SimpleCraftingSettingsId"); + + b.ToTable("ItemCraftingRequiredItem", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItemItemDefinition", b => + { + b.Property("ItemCraftingRequiredItemId") + .HasColumnType("uuid"); + + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("ItemCraftingRequiredItemId", "ItemDefinitionId"); + + b.HasIndex("ItemDefinitionId"); + + b.ToTable("ItemCraftingRequiredItemItemDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItemItemOptionType", b => + { + b.Property("ItemCraftingRequiredItemId") + .HasColumnType("uuid"); + + b.Property("ItemOptionTypeId") + .HasColumnType("uuid"); + + b.HasKey("ItemCraftingRequiredItemId", "ItemOptionTypeId"); + + b.HasIndex("ItemOptionTypeId"); + + b.ToTable("ItemCraftingRequiredItemItemOptionType", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingResultItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddLevel") + .HasColumnType("smallint"); + + b.Property("Durability") + .HasColumnType("smallint"); + + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.Property("RandomMaximumLevel") + .HasColumnType("smallint"); + + b.Property("RandomMinimumLevel") + .HasColumnType("smallint"); + + b.Property("Reference") + .HasColumnType("smallint"); + + b.Property("SimpleCraftingSettingsId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ItemDefinitionId"); + + b.HasIndex("SimpleCraftingSettingsId"); + + b.ToTable("ItemCraftingResultItem", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConsumeEffectId") + .HasColumnType("uuid"); + + b.Property("DropLevel") + .HasColumnType("smallint"); + + b.Property("DropsFromMonsters") + .HasColumnType("boolean"); + + b.Property("Durability") + .HasColumnType("smallint"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("Group") + .HasColumnType("smallint"); + + b.Property("Height") + .HasColumnType("smallint"); + + b.Property("IsAmmunition") + .HasColumnType("boolean"); + + b.Property("IsBoundToCharacter") + .HasColumnType("boolean"); + + b.Property("ItemSlotId") + .HasColumnType("uuid"); + + b.Property("MaximumItemLevel") + .HasColumnType("smallint"); + + b.Property("MaximumSockets") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("PetExperienceFormula") + .HasColumnType("text"); + + b.Property("SkillId") + .HasColumnType("uuid"); + + b.Property("StorageLimitPerCharacter") + .HasColumnType("integer"); + + b.Property("Value") + .HasColumnType("integer"); + + b.Property("Width") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("ConsumeEffectId"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("ItemSlotId"); + + b.HasIndex("SkillId"); + + b.ToTable("ItemDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinitionCharacterClass", b => + { + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.Property("CharacterClassId") + .HasColumnType("uuid"); + + b.HasKey("ItemDefinitionId", "CharacterClassId"); + + b.HasIndex("CharacterClassId"); + + b.ToTable("ItemDefinitionCharacterClass", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinitionItemOptionDefinition", b => + { + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.Property("ItemOptionDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("ItemDefinitionId", "ItemOptionDefinitionId"); + + b.HasIndex("ItemOptionDefinitionId"); + + b.ToTable("ItemDefinitionItemOptionDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinitionItemSetGroup", b => + { + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.Property("ItemSetGroupId") + .HasColumnType("uuid"); + + b.HasKey("ItemDefinitionId", "ItemSetGroupId"); + + b.HasIndex("ItemSetGroupId"); + + b.ToTable("ItemDefinitionItemSetGroup", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDropItemGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Chance") + .HasColumnType("double precision"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("DropEffect") + .HasColumnType("integer"); + + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.Property("ItemLevel") + .HasColumnType("smallint"); + + b.Property("ItemType") + .HasColumnType("integer"); + + b.Property("MaximumLevel") + .HasColumnType("smallint"); + + b.Property("MaximumMonsterLevel") + .HasColumnType("smallint"); + + b.Property("MinimumLevel") + .HasColumnType("smallint"); + + b.Property("MinimumMonsterLevel") + .HasColumnType("smallint"); + + b.Property("MoneyAmount") + .HasColumnType("integer"); + + b.Property("MonsterId") + .HasColumnType("uuid"); + + b.Property("RequiredCharacterLevel") + .HasColumnType("smallint"); + + b.Property("SourceItemLevel") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("ItemDefinitionId"); + + b.HasIndex("MonsterId"); + + b.ToTable("ItemDropItemGroup", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDropItemGroupItemDefinition", b => + { + b.Property("ItemDropItemGroupId") + .HasColumnType("uuid"); + + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("ItemDropItemGroupId", "ItemDefinitionId"); + + b.HasIndex("ItemDefinitionId"); + + b.ToTable("ItemDropItemGroupItemDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemItemOfItemSet", b => + { + b.Property("ItemId") + .HasColumnType("uuid"); + + b.Property("ItemOfItemSetId") + .HasColumnType("uuid"); + + b.HasKey("ItemId", "ItemOfItemSetId"); + + b.HasIndex("ItemOfItemSetId"); + + b.ToTable("ItemItemOfItemSet", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemLevelBonusTable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("ItemLevelBonusTable", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOfItemSet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AncientSetDiscriminator") + .HasColumnType("integer"); + + b.Property("BonusOptionId") + .HasColumnType("uuid"); + + b.Property("ItemDefinitionId") + .HasColumnType("uuid"); + + b.Property("ItemSetGroupId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("BonusOptionId"); + + b.HasIndex("ItemDefinitionId"); + + b.HasIndex("ItemSetGroupId"); + + b.ToTable("ItemOfItemSet", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Number") + .HasColumnType("integer"); + + b.Property("OptionTypeId") + .HasColumnType("uuid"); + + b.Property("PowerUpDefinitionId") + .HasColumnType("uuid"); + + b.Property("SubOptionType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("OptionTypeId"); + + b.HasIndex("PowerUpDefinitionId") + .IsUnique(); + + b.ToTable("ItemOption", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionCombinationBonus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppliesMultipleTimes") + .HasColumnType("boolean"); + + b.Property("BonusId") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("Number") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("BonusId") + .IsUnique(); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("ItemOptionCombinationBonus", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddChance") + .HasColumnType("real"); + + b.Property("AddsRandomly") + .HasColumnType("boolean"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("MaximumOptionsPerItem") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("ItemOptionDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Index") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("uuid"); + + b.Property("ItemOptionId") + .HasColumnType("uuid"); + + b.Property("Level") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ItemId"); + + b.HasIndex("ItemOptionId"); + + b.ToTable("ItemOptionLink", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionOfLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IncreasableItemOptionId") + .HasColumnType("uuid"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("PowerUpDefinitionId") + .HasColumnType("uuid"); + + b.Property("RequiredItemLevel") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IncreasableItemOptionId"); + + b.HasIndex("PowerUpDefinitionId") + .IsUnique(); + + b.ToTable("ItemOptionOfLevel", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("IsVisible") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("ItemOptionType", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemSetGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AlwaysApplies") + .HasColumnType("boolean"); + + b.Property("CountDistinct") + .HasColumnType("boolean"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("MinimumItemCount") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OptionsId") + .HasColumnType("uuid"); + + b.Property("SetLevel") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("OptionsId"); + + b.ToTable("ItemSetGroup", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemSlotType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("RawItemSlots") + .HasColumnType("text") + .HasColumnName("ItemSlots") + .HasAnnotation("Relational:JsonPropertyName", "itemSlots"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("ItemSlotType", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemStorage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Money") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ItemStorage", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.JewelMix", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("MixedJewelId") + .HasColumnType("uuid"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("SingleJewelId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("MixedJewelId"); + + b.HasIndex("SingleJewelId"); + + b.ToTable("JewelMix", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.LetterBody", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Animation") + .HasColumnType("smallint"); + + b.Property("HeaderId") + .HasColumnType("uuid"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rotation") + .HasColumnType("smallint"); + + b.Property("SenderAppearanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("HeaderId"); + + b.HasIndex("SenderAppearanceId") + .IsUnique(); + + b.ToTable("LetterBody", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.LetterHeader", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("LetterDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ReadFlag") + .HasColumnType("boolean"); + + b.Property("ReceiverId") + .HasColumnType("uuid"); + + b.Property("SenderName") + .HasColumnType("text"); + + b.Property("Subject") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReceiverId"); + + b.ToTable("LetterHeader", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.LevelBonus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AdditionalValue") + .HasColumnType("real"); + + b.Property("ItemLevelBonusTableId") + .HasColumnType("uuid"); + + b.Property("Level") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ItemLevelBonusTableId"); + + b.ToTable("LevelBonus", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MagicEffectDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DurationId") + .HasColumnType("uuid"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("InformObservers") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("SendDuration") + .HasColumnType("boolean"); + + b.Property("StopByDeath") + .HasColumnType("boolean"); + + b.Property("SubType") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("DurationId") + .IsUnique(); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("MagicEffectDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Aggregation") + .HasColumnType("integer"); + + b.Property("DisplayValueFormula") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtendsDuration") + .HasColumnType("boolean"); + + b.Property("MaximumLevel") + .HasColumnType("smallint"); + + b.Property("MinimumLevel") + .HasColumnType("smallint"); + + b.Property("Rank") + .HasColumnType("smallint"); + + b.Property("ReplacedSkillId") + .HasColumnType("uuid"); + + b.Property("RootId") + .HasColumnType("uuid"); + + b.Property("TargetAttributeId") + .HasColumnType("uuid"); + + b.Property("ValueFormula") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ReplacedSkillId"); + + b.HasIndex("RootId"); + + b.HasIndex("TargetAttributeId"); + + b.ToTable("MasterSkillDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillDefinitionSkill", b => + { + b.Property("MasterSkillDefinitionId") + .HasColumnType("uuid"); + + b.Property("SkillId") + .HasColumnType("uuid"); + + b.HasKey("MasterSkillDefinitionId", "SkillId"); + + b.HasIndex("SkillId"); + + b.ToTable("MasterSkillDefinitionSkill", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillRoot", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("MasterSkillRoot", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameChangeEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Index") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("MiniGameDefinitionId") + .HasColumnType("uuid"); + + b.Property("MinimumTargetLevel") + .HasColumnType("smallint"); + + b.Property("MultiplyKillsByPlayers") + .HasColumnType("boolean"); + + b.Property("NumberOfKills") + .HasColumnType("smallint"); + + b.Property("SpawnAreaId") + .HasColumnType("uuid"); + + b.Property("Target") + .HasColumnType("integer"); + + b.Property("TargetDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("MiniGameDefinitionId"); + + b.HasIndex("SpawnAreaId") + .IsUnique(); + + b.HasIndex("TargetDefinitionId"); + + b.ToTable("MiniGameChangeEvent", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowParty") + .HasColumnType("boolean"); + + b.Property("ArePlayerKillersAllowedToEnter") + .HasColumnType("boolean"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EnterDuration") + .HasColumnType("interval"); + + b.Property("EntranceFee") + .HasColumnType("integer"); + + b.Property("EntranceId") + .HasColumnType("uuid"); + + b.Property("ExitDuration") + .HasColumnType("interval"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("GameDuration") + .HasColumnType("interval"); + + b.Property("GameLevel") + .HasColumnType("smallint"); + + b.Property("MapCreationPolicy") + .HasColumnType("integer"); + + b.Property("MaximumCharacterLevel") + .HasColumnType("integer"); + + b.Property("MaximumPlayerCount") + .HasColumnType("integer"); + + b.Property("MaximumSpecialCharacterLevel") + .HasColumnType("integer"); + + b.Property("MinimumCharacterLevel") + .HasColumnType("integer"); + + b.Property("MinimumSpecialCharacterLevel") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequiresMasterClass") + .HasColumnType("boolean"); + + b.Property("SaveRankingStatistics") + .HasColumnType("boolean"); + + b.Property("TicketItemId") + .HasColumnType("uuid"); + + b.Property("TicketItemLevel") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("EntranceId"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("TicketItemId"); + + b.ToTable("MiniGameDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameRankingEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("uuid"); + + b.Property("GameInstanceId") + .HasColumnType("uuid"); + + b.Property("MiniGameId") + .HasColumnType("uuid"); + + b.Property("Rank") + .HasColumnType("integer"); + + b.Property("Score") + .HasColumnType("integer"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CharacterId"); + + b.HasIndex("MiniGameId"); + + b.ToTable("MiniGameRankingEntry", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ItemRewardId") + .HasColumnType("uuid"); + + b.Property("MiniGameDefinitionId") + .HasColumnType("uuid"); + + b.Property("Rank") + .HasColumnType("integer"); + + b.Property("RequiredKillId") + .HasColumnType("uuid"); + + b.Property("RequiredSuccess") + .HasColumnType("integer"); + + b.Property("RewardAmount") + .HasColumnType("integer"); + + b.Property("RewardType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ItemRewardId"); + + b.HasIndex("MiniGameDefinitionId"); + + b.HasIndex("RequiredKillId"); + + b.ToTable("MiniGameReward", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameSpawnWave", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("MiniGameDefinitionId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("WaveNumber") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("MiniGameDefinitionId"); + + b.ToTable("MiniGameSpawnWave", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameTerrainChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EndX") + .HasColumnType("smallint"); + + b.Property("EndY") + .HasColumnType("smallint"); + + b.Property("IsClientUpdateRequired") + .HasColumnType("boolean"); + + b.Property("MiniGameChangeEventId") + .HasColumnType("uuid"); + + b.Property("SetTerrainAttribute") + .HasColumnType("boolean"); + + b.Property("StartX") + .HasColumnType("smallint"); + + b.Property("StartY") + .HasColumnType("smallint"); + + b.Property("TerrainAttribute") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("MiniGameChangeEventId"); + + b.ToTable("MiniGameTerrainChange", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterAttribute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AttributeDefinitionId") + .HasColumnType("uuid"); + + b.Property("MonsterDefinitionId") + .HasColumnType("uuid"); + + b.Property("Value") + .HasColumnType("real"); + + b.HasKey("Id"); + + b.HasIndex("AttributeDefinitionId"); + + b.HasIndex("MonsterDefinitionId"); + + b.ToTable("MonsterAttribute", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AttackDelay") + .HasColumnType("interval"); + + b.Property("AttackRange") + .HasColumnType("smallint"); + + b.Property("AttackSkillId") + .HasColumnType("uuid"); + + b.Property("Attribute") + .HasColumnType("smallint"); + + b.Property("Designation") + .IsRequired() + .HasColumnType("text"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("IntelligenceTypeName") + .HasColumnType("text"); + + b.Property("MerchantStoreId") + .HasColumnType("uuid"); + + b.Property("MoveDelay") + .HasColumnType("interval"); + + b.Property("MoveRange") + .HasColumnType("smallint"); + + b.Property("NpcWindow") + .HasColumnType("integer"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("NumberOfMaximumItemDrops") + .HasColumnType("integer"); + + b.Property("ObjectKind") + .HasColumnType("integer"); + + b.Property("RespawnDelay") + .HasColumnType("interval"); + + b.Property("ViewRange") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AttackSkillId"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("MerchantStoreId") + .IsUnique(); + + b.ToTable("MonsterDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinitionDropItemGroup", b => + { + b.Property("MonsterDefinitionId") + .HasColumnType("uuid"); + + b.Property("DropItemGroupId") + .HasColumnType("uuid"); + + b.HasKey("MonsterDefinitionId", "DropItemGroupId"); + + b.HasIndex("DropItemGroupId"); + + b.ToTable("MonsterDefinitionDropItemGroup", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterSpawnArea", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Direction") + .HasColumnType("integer"); + + b.Property("GameMapId") + .HasColumnType("uuid"); + + b.Property("MaximumHealthOverride") + .HasColumnType("integer"); + + b.Property("MonsterDefinitionId") + .HasColumnType("uuid"); + + b.Property("Quantity") + .HasColumnType("smallint"); + + b.Property("SpawnTrigger") + .HasColumnType("integer"); + + b.Property("WaveNumber") + .HasColumnType("smallint"); + + b.Property("X1") + .HasColumnType("smallint"); + + b.Property("X2") + .HasColumnType("smallint"); + + b.Property("Y1") + .HasColumnType("smallint"); + + b.Property("Y2") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("GameMapId"); + + b.HasIndex("MonsterDefinitionId"); + + b.ToTable("MonsterSpawnArea", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.PlugInConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CustomConfiguration") + .HasColumnType("text"); + + b.Property("CustomPlugInSource") + .HasColumnType("text"); + + b.Property("ExternalAssemblyName") + .HasColumnType("text"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("TypeId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.ToTable("PlugInConfiguration", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BoostId") + .HasColumnType("uuid"); + + b.Property("GameMapDefinitionId") + .HasColumnType("uuid"); + + b.Property("MagicEffectDefinitionId") + .HasColumnType("uuid"); + + b.Property("TargetAttributeId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("BoostId") + .IsUnique(); + + b.HasIndex("GameMapDefinitionId"); + + b.HasIndex("MagicEffectDefinitionId"); + + b.HasIndex("TargetAttributeId"); + + b.ToTable("PowerUpDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinitionValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AggregateType") + .HasColumnType("integer"); + + b.Property("Stage") + .HasColumnType("smallint"); + + b.Property("Value") + .HasColumnType("real"); + + b.HasKey("Id"); + + b.ToTable("PowerUpDefinitionValue", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Group") + .HasColumnType("smallint"); + + b.Property("MaximumCharacterLevel") + .HasColumnType("integer"); + + b.Property("MinimumCharacterLevel") + .HasColumnType("integer"); + + b.Property("MonsterDefinitionId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("QualifiedCharacterId") + .HasColumnType("uuid"); + + b.Property("QuestGiverId") + .HasColumnType("uuid"); + + b.Property("RefuseNumber") + .HasColumnType("smallint"); + + b.Property("Repeatable") + .HasColumnType("boolean"); + + b.Property("RequiredStartMoney") + .HasColumnType("integer"); + + b.Property("RequiresClientAction") + .HasColumnType("boolean"); + + b.Property("StartingNumber") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("MonsterDefinitionId"); + + b.HasIndex("QualifiedCharacterId"); + + b.HasIndex("QuestGiverId"); + + b.ToTable("QuestDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestItemRequirement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DropItemGroupId") + .HasColumnType("uuid"); + + b.Property("ItemId") + .HasColumnType("uuid"); + + b.Property("MinimumNumber") + .HasColumnType("integer"); + + b.Property("QuestDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("DropItemGroupId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuestDefinitionId"); + + b.ToTable("QuestItemRequirement", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestMonsterKillRequirement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MinimumNumber") + .HasColumnType("integer"); + + b.Property("MonsterId") + .HasColumnType("uuid"); + + b.Property("QuestDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("MonsterId"); + + b.HasIndex("QuestDefinitionId"); + + b.ToTable("QuestMonsterKillRequirement", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestMonsterKillRequirementState", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CharacterQuestStateId") + .HasColumnType("uuid"); + + b.Property("KillCount") + .HasColumnType("integer"); + + b.Property("RequirementId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CharacterQuestStateId"); + + b.HasIndex("RequirementId"); + + b.ToTable("QuestMonsterKillRequirementState", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AttributeRewardId") + .HasColumnType("uuid"); + + b.Property("ItemRewardId") + .HasColumnType("uuid"); + + b.Property("QuestDefinitionId") + .HasColumnType("uuid"); + + b.Property("RewardType") + .HasColumnType("integer"); + + b.Property("SkillRewardId") + .HasColumnType("uuid"); + + b.Property("Value") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("AttributeRewardId"); + + b.HasIndex("ItemRewardId") + .IsUnique(); + + b.HasIndex("QuestDefinitionId"); + + b.HasIndex("SkillRewardId"); + + b.ToTable("QuestReward", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Rectangle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("X1") + .HasColumnType("smallint"); + + b.Property("X2") + .HasColumnType("smallint"); + + b.Property("Y1") + .HasColumnType("smallint"); + + b.Property("Y2") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("Rectangle", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SimpleCraftingSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MaximumSuccessPercent") + .HasColumnType("smallint"); + + b.Property("Money") + .HasColumnType("integer"); + + b.Property("MoneyPerFinalSuccessPercentage") + .HasColumnType("integer"); + + b.Property("MultipleAllowed") + .HasColumnType("boolean"); + + b.Property("NpcPriceDivisor") + .HasColumnType("integer"); + + b.Property("ResultItemExcellentOptionChance") + .HasColumnType("smallint"); + + b.Property("ResultItemLuckOptionChance") + .HasColumnType("smallint"); + + b.Property("ResultItemMaxExcOptionCount") + .HasColumnType("smallint"); + + b.Property("ResultItemSelect") + .HasColumnType("integer"); + + b.Property("ResultItemSkillChance") + .HasColumnType("smallint"); + + b.Property("SuccessPercent") + .HasColumnType("smallint"); + + b.Property("SuccessPercentageAdditionForAncientItem") + .HasColumnType("integer"); + + b.Property("SuccessPercentageAdditionForExcellentItem") + .HasColumnType("integer"); + + b.Property("SuccessPercentageAdditionForGuardianItem") + .HasColumnType("integer"); + + b.Property("SuccessPercentageAdditionForLuck") + .HasColumnType("integer"); + + b.Property("SuccessPercentageAdditionForSocketItem") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("SimpleCraftingSettings", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AreaSkillSettingsId") + .HasColumnType("uuid"); + + b.Property("AttackDamage") + .HasColumnType("integer"); + + b.Property("DamageType") + .HasColumnType("integer"); + + b.Property("ElementalModifierTargetId") + .HasColumnType("uuid"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("ImplicitTargetRange") + .HasColumnType("smallint"); + + b.Property("MagicEffectDefId") + .HasColumnType("uuid"); + + b.Property("MasterDefinitionId") + .HasColumnType("uuid"); + + b.Property("MovesTarget") + .HasColumnType("boolean"); + + b.Property("MovesToTarget") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.Property("Range") + .HasColumnType("smallint"); + + b.Property("SkillType") + .HasColumnType("integer"); + + b.Property("Target") + .HasColumnType("integer"); + + b.Property("TargetRestriction") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("AreaSkillSettingsId") + .IsUnique(); + + b.HasIndex("ElementalModifierTargetId"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("MagicEffectDefId"); + + b.HasIndex("MasterDefinitionId") + .IsUnique(); + + b.ToTable("Skill", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillCharacterClass", b => + { + b.Property("SkillId") + .HasColumnType("uuid"); + + b.Property("CharacterClassId") + .HasColumnType("uuid"); + + b.HasKey("SkillId", "CharacterClassId"); + + b.HasIndex("CharacterClassId"); + + b.ToTable("SkillCharacterClass", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillComboDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MaximumCompletionTime") + .HasColumnType("interval"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("SkillComboDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillComboStep", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IsFinalStep") + .HasColumnType("boolean"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("SkillComboDefinitionId") + .HasColumnType("uuid"); + + b.Property("SkillId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SkillComboDefinitionId"); + + b.HasIndex("SkillId"); + + b.ToTable("SkillComboStep", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("uuid"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("SkillId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CharacterId"); + + b.HasIndex("SkillId"); + + b.ToTable("SkillEntry", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.StatAttribute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("CharacterId") + .HasColumnType("uuid"); + + b.Property("DefinitionId") + .HasColumnType("uuid"); + + b.Property("Value") + .HasColumnType("real"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("CharacterId"); + + b.HasIndex("DefinitionId"); + + b.ToTable("StatAttribute", "data"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.StatAttributeDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AttributeId") + .HasColumnType("uuid"); + + b.Property("BaseValue") + .HasColumnType("real"); + + b.Property("CharacterClassId") + .HasColumnType("uuid"); + + b.Property("IncreasableByPlayer") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AttributeId"); + + b.HasIndex("CharacterClassId"); + + b.ToTable("StatAttributeDefinition", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SystemConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AutoStart") + .HasColumnType("boolean"); + + b.Property("AutoUpdateSchema") + .HasColumnType("boolean"); + + b.Property("IpResolver") + .HasColumnType("integer"); + + b.Property("IpResolverParameter") + .HasColumnType("text"); + + b.Property("ReadConsoleInput") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("SystemConfiguration", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.WarpInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Costs") + .HasColumnType("integer"); + + b.Property("GameConfigurationId") + .HasColumnType("uuid"); + + b.Property("GateId") + .HasColumnType("uuid"); + + b.Property("Index") + .HasColumnType("integer"); + + b.Property("LevelRequirement") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GameConfigurationId"); + + b.HasIndex("GateId"); + + b.ToTable("WarpInfo", "config"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Account", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemStorage", "RawVault") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.Account", "VaultId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawVault"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AccountCharacterClass", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Account", "Account") + .WithMany("JoinedUnlockedCharacterClasses") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "CharacterClass") + .WithMany() + .HasForeignKey("CharacterClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("CharacterClass"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AppearanceData", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "RawCharacterClass") + .WithMany() + .HasForeignKey("CharacterClassId"); + + b.Navigation("RawCharacterClass"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawAttributes") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeRelationship", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", null) + .WithMany("RawAttributeCombinations") + .HasForeignKey("CharacterClassId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawInputAttribute") + .WithMany() + .HasForeignKey("InputAttributeId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawOperandAttribute") + .WithMany() + .HasForeignKey("OperandAttributeId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinitionValue", null) + .WithMany("RawRelatedValues") + .HasForeignKey("PowerUpDefinitionValueId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawTargetAttribute") + .WithMany() + .HasForeignKey("TargetAttributeId"); + + b.Navigation("RawInputAttribute"); + + b.Navigation("RawOperandAttribute"); + + b.Navigation("RawTargetAttribute"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeRequirement", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawAttribute") + .WithMany() + .HasForeignKey("AttributeId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", null) + .WithMany("RawMapRequirements") + .HasForeignKey("GameMapDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", null) + .WithMany("RawRequirements") + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", null) + .WithMany("RawConsumeRequirements") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", null) + .WithMany("RawRequirements") + .HasForeignKey("SkillId1") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawAttribute"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.BattleZoneDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Rectangle", "RawGround") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.BattleZoneDefinition", "GroundId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Rectangle", "RawLeftGoal") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.BattleZoneDefinition", "LeftGoalId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Rectangle", "RawRightGoal") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.BattleZoneDefinition", "RightGoalId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawGround"); + + b.Navigation("RawLeftGoal"); + + b.Navigation("RawRightGoal"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Account", null) + .WithMany("RawCharacters") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "RawCharacterClass") + .WithMany() + .HasForeignKey("CharacterClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "RawCurrentMap") + .WithMany() + .HasForeignKey("CurrentMapId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemStorage", "RawInventory") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", "InventoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawCharacterClass"); + + b.Navigation("RawCurrentMap"); + + b.Navigation("RawInventory"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillComboDefinition", "RawComboDefinition") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "ComboDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawCharacterClasses") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "RawHomeMap") + .WithMany() + .HasForeignKey("HomeMapId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "RawNextGenerationClass") + .WithMany() + .HasForeignKey("NextGenerationClassId"); + + b.Navigation("RawComboDefinition"); + + b.Navigation("RawHomeMap"); + + b.Navigation("RawNextGenerationClass"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterDropItemGroup", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", "Character") + .WithMany("JoinedDropItemGroups") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", "DropItemGroup") + .WithMany() + .HasForeignKey("DropItemGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Character"); + + b.Navigation("DropItemGroup"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterQuestState", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestDefinition", "RawActiveQuest") + .WithMany() + .HasForeignKey("ActiveQuestId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", null) + .WithMany("RawQuestStates") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestDefinition", "RawLastFinishedQuest") + .WithMany() + .HasForeignKey("LastFinishedQuestId"); + + b.Navigation("RawActiveQuest"); + + b.Navigation("RawLastFinishedQuest"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ChatServerEndpoint", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ChatServerDefinition", null) + .WithMany("RawEndpoints") + .HasForeignKey("ChatServerDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameClientDefinition", "RawClient") + .WithMany() + .HasForeignKey("ClientId"); + + b.Navigation("RawClient"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CombinationBonusRequirement", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionCombinationBonus", null) + .WithMany("RawRequirements") + .HasForeignKey("ItemOptionCombinationBonusId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionType", "RawOptionType") + .WithMany() + .HasForeignKey("OptionTypeId"); + + b.Navigation("RawOptionType"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ConnectServerDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameClientDefinition", "RawClient") + .WithMany() + .HasForeignKey("ClientId"); + + b.Navigation("RawClient"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ConstValueAttribute", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "CharacterClass") + .WithMany("RawBaseAttributeValues") + .HasForeignKey("CharacterClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawDefinition") + .WithMany() + .HasForeignKey("DefinitionId"); + + b.Navigation("CharacterClass"); + + b.Navigation("RawDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawDropItemGroups") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "RawMonster") + .WithMany() + .HasForeignKey("MonsterId"); + + b.Navigation("RawMonster"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroupItemDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", "DropItemGroup") + .WithMany("JoinedPossibleItems") + .HasForeignKey("DropItemGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "ItemDefinition") + .WithMany() + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DropItemGroup"); + + b.Navigation("ItemDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DuelArea", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DuelConfiguration", null) + .WithMany("RawDuelAreas") + .HasForeignKey("DuelConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", "RawFirstPlayerGate") + .WithMany() + .HasForeignKey("FirstPlayerGateId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", "RawSecondPlayerGate") + .WithMany() + .HasForeignKey("SecondPlayerGateId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", "RawSpectatorsGate") + .WithMany() + .HasForeignKey("SpectatorsGateId"); + + b.Navigation("RawFirstPlayerGate"); + + b.Navigation("RawSecondPlayerGate"); + + b.Navigation("RawSpectatorsGate"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DuelConfiguration", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", "RawExit") + .WithMany() + .HasForeignKey("ExitId"); + + b.Navigation("RawExit"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.EnterGate", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", null) + .WithMany("RawEnterGates") + .HasForeignKey("GameMapDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", "RawTargetGate") + .WithMany() + .HasForeignKey("TargetGateId"); + + b.Navigation("RawTargetGate"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "RawMap") + .WithMany("RawExitGates") + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawMap"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DuelConfiguration", "RawDuelConfiguration") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", "DuelConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawDuelConfiguration"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.BattleZoneDefinition", "RawBattleZone") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "BattleZoneId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawMaps") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "RawSafezoneMap") + .WithMany() + .HasForeignKey("SafezoneMapId"); + + b.Navigation("RawBattleZone"); + + b.Navigation("RawSafezoneMap"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinitionDropItemGroup", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", "DropItemGroup") + .WithMany() + .HasForeignKey("DropItemGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "GameMapDefinition") + .WithMany("JoinedDropItemGroups") + .HasForeignKey("GameMapDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DropItemGroup"); + + b.Navigation("GameMapDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerConfigurationGameMapDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "GameMapDefinition") + .WithMany() + .HasForeignKey("GameMapDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerConfiguration", "GameServerConfiguration") + .WithMany("JoinedMaps") + .HasForeignKey("GameServerConfigurationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GameMapDefinition"); + + b.Navigation("GameServerConfiguration"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", "RawGameConfiguration") + .WithMany() + .HasForeignKey("GameConfigurationId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerConfiguration", "RawServerConfiguration") + .WithMany() + .HasForeignKey("ServerConfigurationId"); + + b.Navigation("RawGameConfiguration"); + + b.Navigation("RawServerConfiguration"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerEndpoint", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameClientDefinition", "RawClient") + .WithMany() + .HasForeignKey("ClientId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerDefinition", null) + .WithMany("RawEndpoints") + .HasForeignKey("GameServerDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawClient"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Guild", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Guild", "RawAllianceGuild") + .WithMany() + .HasForeignKey("AllianceGuildId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Guild", "RawHostility") + .WithMany() + .HasForeignKey("HostilityId"); + + b.Navigation("RawAllianceGuild"); + + b.Navigation("RawHostility"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GuildMember", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Guild", null) + .WithMany("RawMembers") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", "Character") + .WithMany() + .HasForeignKey("Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.IncreasableItemOption", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionDefinition", null) + .WithMany("RawPossibleOptions") + .HasForeignKey("ItemOptionDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionType", "RawOptionType") + .WithMany() + .HasForeignKey("OptionTypeId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinition", "RawPowerUpDefinition") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.IncreasableItemOption", "PowerUpDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawOptionType"); + + b.Navigation("RawPowerUpDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Item", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawDefinition") + .WithMany() + .HasForeignKey("DefinitionId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemStorage", "RawItemStorage") + .WithMany("RawItems") + .HasForeignKey("ItemStorageId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawDefinition"); + + b.Navigation("RawItemStorage"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemAppearance", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AppearanceData", null) + .WithMany("RawEquippedItems") + .HasForeignKey("AppearanceDataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawDefinition") + .WithMany() + .HasForeignKey("DefinitionId"); + + b.Navigation("RawDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemAppearanceItemOptionType", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemAppearance", "ItemAppearance") + .WithMany("JoinedVisibleOptions") + .HasForeignKey("ItemAppearanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionType", "ItemOptionType") + .WithMany() + .HasForeignKey("ItemOptionTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ItemAppearance"); + + b.Navigation("ItemOptionType"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemBasePowerUpDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemLevelBonusTable", "RawBonusPerLevelTable") + .WithMany() + .HasForeignKey("BonusPerLevelTableId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", null) + .WithMany("RawBasePowerUpAttributes") + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawTargetAttribute") + .WithMany() + .HasForeignKey("TargetAttributeId"); + + b.Navigation("RawBonusPerLevelTable"); + + b.Navigation("RawTargetAttribute"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCrafting", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", null) + .WithMany("RawItemCraftings") + .HasForeignKey("MonsterDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.SimpleCraftingSettings", "RawSimpleCraftingSettings") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCrafting", "SimpleCraftingSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawSimpleCraftingSettings"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItem", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.SimpleCraftingSettings", null) + .WithMany("RawRequiredItems") + .HasForeignKey("SimpleCraftingSettingsId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItemItemDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItem", "ItemCraftingRequiredItem") + .WithMany("JoinedPossibleItems") + .HasForeignKey("ItemCraftingRequiredItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "ItemDefinition") + .WithMany() + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ItemCraftingRequiredItem"); + + b.Navigation("ItemDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItemItemOptionType", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItem", "ItemCraftingRequiredItem") + .WithMany("JoinedRequiredItemOptions") + .HasForeignKey("ItemCraftingRequiredItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionType", "ItemOptionType") + .WithMany() + .HasForeignKey("ItemOptionTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ItemCraftingRequiredItem"); + + b.Navigation("ItemOptionType"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingResultItem", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawItemDefinition") + .WithMany() + .HasForeignKey("ItemDefinitionId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.SimpleCraftingSettings", null) + .WithMany("RawResultItems") + .HasForeignKey("SimpleCraftingSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawItemDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MagicEffectDefinition", "RawConsumeEffect") + .WithMany() + .HasForeignKey("ConsumeEffectId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawItems") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemSlotType", "RawItemSlot") + .WithMany() + .HasForeignKey("ItemSlotId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "RawSkill") + .WithMany() + .HasForeignKey("SkillId"); + + b.Navigation("RawConsumeEffect"); + + b.Navigation("RawItemSlot"); + + b.Navigation("RawSkill"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinitionCharacterClass", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "CharacterClass") + .WithMany() + .HasForeignKey("CharacterClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "ItemDefinition") + .WithMany("JoinedQualifiedCharacters") + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CharacterClass"); + + b.Navigation("ItemDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinitionItemOptionDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "ItemDefinition") + .WithMany("JoinedPossibleItemOptions") + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionDefinition", "ItemOptionDefinition") + .WithMany() + .HasForeignKey("ItemOptionDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ItemDefinition"); + + b.Navigation("ItemOptionDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinitionItemSetGroup", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "ItemDefinition") + .WithMany("JoinedPossibleItemSetGroups") + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemSetGroup", "ItemSetGroup") + .WithMany() + .HasForeignKey("ItemSetGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ItemDefinition"); + + b.Navigation("ItemSetGroup"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDropItemGroup", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", null) + .WithMany("RawDropItems") + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "RawMonster") + .WithMany() + .HasForeignKey("MonsterId"); + + b.Navigation("RawMonster"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDropItemGroupItemDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "ItemDefinition") + .WithMany() + .HasForeignKey("ItemDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDropItemGroup", "ItemDropItemGroup") + .WithMany("JoinedPossibleItems") + .HasForeignKey("ItemDropItemGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ItemDefinition"); + + b.Navigation("ItemDropItemGroup"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemItemOfItemSet", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Item", "Item") + .WithMany("JoinedItemSetGroups") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOfItemSet", "ItemOfItemSet") + .WithMany() + .HasForeignKey("ItemOfItemSetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ItemOfItemSet"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemLevelBonusTable", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawItemLevelBonusTables") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOfItemSet", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.IncreasableItemOption", "RawBonusOption") + .WithMany() + .HasForeignKey("BonusOptionId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawItemDefinition") + .WithMany() + .HasForeignKey("ItemDefinitionId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemSetGroup", "RawItemSetGroup") + .WithMany("RawItems") + .HasForeignKey("ItemSetGroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawBonusOption"); + + b.Navigation("RawItemDefinition"); + + b.Navigation("RawItemSetGroup"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOption", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionType", "RawOptionType") + .WithMany() + .HasForeignKey("OptionTypeId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinition", "RawPowerUpDefinition") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOption", "PowerUpDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawOptionType"); + + b.Navigation("RawPowerUpDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionCombinationBonus", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinition", "RawBonus") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionCombinationBonus", "BonusId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawItemOptionCombinationBonuses") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawBonus"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawItemOptions") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionLink", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Item", null) + .WithMany("RawItemOptions") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.IncreasableItemOption", "RawItemOption") + .WithMany() + .HasForeignKey("ItemOptionId"); + + b.Navigation("RawItemOption"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionOfLevel", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.IncreasableItemOption", null) + .WithMany("RawLevelDependentOptions") + .HasForeignKey("IncreasableItemOptionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinition", "RawPowerUpDefinition") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionOfLevel", "PowerUpDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawPowerUpDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionType", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawItemOptionTypes") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemSetGroup", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawItemSetGroups") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionDefinition", "RawOptions") + .WithMany() + .HasForeignKey("OptionsId"); + + b.Navigation("RawOptions"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemSlotType", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawItemSlotTypes") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.JewelMix", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawJewelMixes") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawMixedJewel") + .WithMany() + .HasForeignKey("MixedJewelId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawSingleJewel") + .WithMany() + .HasForeignKey("SingleJewelId"); + + b.Navigation("RawMixedJewel"); + + b.Navigation("RawSingleJewel"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.LetterBody", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.LetterHeader", "RawHeader") + .WithMany() + .HasForeignKey("HeaderId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AppearanceData", "RawSenderAppearance") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.LetterBody", "SenderAppearanceId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawHeader"); + + b.Navigation("RawSenderAppearance"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.LetterHeader", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", "Receiver") + .WithMany("RawLetters") + .HasForeignKey("ReceiverId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Receiver"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.LevelBonus", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemLevelBonusTable", null) + .WithMany("RawBonusPerLevel") + .HasForeignKey("ItemLevelBonusTableId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MagicEffectDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinitionValue", "RawDuration") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.MagicEffectDefinition", "DurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawMagicEffects") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawDuration"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "RawReplacedSkill") + .WithMany() + .HasForeignKey("ReplacedSkillId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillRoot", "RawRoot") + .WithMany() + .HasForeignKey("RootId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawTargetAttribute") + .WithMany() + .HasForeignKey("TargetAttributeId"); + + b.Navigation("RawReplacedSkill"); + + b.Navigation("RawRoot"); + + b.Navigation("RawTargetAttribute"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillDefinitionSkill", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillDefinition", "MasterSkillDefinition") + .WithMany("JoinedRequiredMasterSkills") + .HasForeignKey("MasterSkillDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "Skill") + .WithMany() + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MasterSkillDefinition"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillRoot", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawMasterSkillRoots") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameChangeEvent", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameDefinition", null) + .WithMany("RawChangeEvents") + .HasForeignKey("MiniGameDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterSpawnArea", "RawSpawnArea") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameChangeEvent", "SpawnAreaId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "RawTargetDefinition") + .WithMany() + .HasForeignKey("TargetDefinitionId"); + + b.Navigation("RawSpawnArea"); + + b.Navigation("RawTargetDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", "RawEntrance") + .WithMany() + .HasForeignKey("EntranceId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawMiniGameDefinitions") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawTicketItem") + .WithMany() + .HasForeignKey("TicketItemId"); + + b.Navigation("RawEntrance"); + + b.Navigation("RawTicketItem"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameRankingEntry", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", "RawCharacter") + .WithMany() + .HasForeignKey("CharacterId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameDefinition", "RawMiniGame") + .WithMany() + .HasForeignKey("MiniGameId"); + + b.Navigation("RawCharacter"); + + b.Navigation("RawMiniGame"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameReward", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", "RawItemReward") + .WithMany() + .HasForeignKey("ItemRewardId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameDefinition", null) + .WithMany("RawRewards") + .HasForeignKey("MiniGameDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "RawRequiredKill") + .WithMany() + .HasForeignKey("RequiredKillId"); + + b.Navigation("RawItemReward"); + + b.Navigation("RawRequiredKill"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameSpawnWave", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameDefinition", null) + .WithMany("RawSpawnWaves") + .HasForeignKey("MiniGameDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameTerrainChange", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameChangeEvent", null) + .WithMany("RawTerrainChanges") + .HasForeignKey("MiniGameChangeEventId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterAttribute", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawAttributeDefinition") + .WithMany() + .HasForeignKey("AttributeDefinitionId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", null) + .WithMany("RawAttributes") + .HasForeignKey("MonsterDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawAttributeDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "RawAttackSkill") + .WithMany() + .HasForeignKey("AttackSkillId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawMonsters") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemStorage", "RawMerchantStore") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "MerchantStoreId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawAttackSkill"); + + b.Navigation("RawMerchantStore"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinitionDropItemGroup", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", "DropItemGroup") + .WithMany() + .HasForeignKey("DropItemGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "MonsterDefinition") + .WithMany("JoinedDropItemGroups") + .HasForeignKey("MonsterDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DropItemGroup"); + + b.Navigation("MonsterDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterSpawnArea", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "RawGameMap") + .WithMany("RawMonsterSpawns") + .HasForeignKey("GameMapId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "RawMonsterDefinition") + .WithMany() + .HasForeignKey("MonsterDefinitionId"); + + b.Navigation("RawGameMap"); + + b.Navigation("RawMonsterDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.PlugInConfiguration", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawPlugInConfigurations") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinitionValue", "RawBoost") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinition", "BoostId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", null) + .WithMany("RawCharacterPowerUpDefinitions") + .HasForeignKey("GameMapDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MagicEffectDefinition", null) + .WithMany("RawPowerUpDefinitions") + .HasForeignKey("MagicEffectDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawTargetAttribute") + .WithMany() + .HasForeignKey("TargetAttributeId"); + + b.Navigation("RawBoost"); + + b.Navigation("RawTargetAttribute"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", null) + .WithMany("RawQuests") + .HasForeignKey("MonsterDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "RawQualifiedCharacter") + .WithMany() + .HasForeignKey("QualifiedCharacterId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "RawQuestGiver") + .WithMany() + .HasForeignKey("QuestGiverId"); + + b.Navigation("RawQualifiedCharacter"); + + b.Navigation("RawQuestGiver"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestItemRequirement", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", "RawDropItemGroup") + .WithMany() + .HasForeignKey("DropItemGroupId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawItem") + .WithMany() + .HasForeignKey("ItemId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestDefinition", null) + .WithMany("RawRequiredItems") + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawDropItemGroup"); + + b.Navigation("RawItem"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestMonsterKillRequirement", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "RawMonster") + .WithMany() + .HasForeignKey("MonsterId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestDefinition", null) + .WithMany("RawRequiredMonsterKills") + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawMonster"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestMonsterKillRequirementState", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterQuestState", null) + .WithMany("RawRequirementStates") + .HasForeignKey("CharacterQuestStateId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestMonsterKillRequirement", "RawRequirement") + .WithMany() + .HasForeignKey("RequirementId"); + + b.Navigation("RawRequirement"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestReward", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawAttributeReward") + .WithMany() + .HasForeignKey("AttributeRewardId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Item", "RawItemReward") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestReward", "ItemRewardId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestDefinition", null) + .WithMany("RawRewards") + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "RawSkillReward") + .WithMany() + .HasForeignKey("SkillRewardId"); + + b.Navigation("RawAttributeReward"); + + b.Navigation("RawItemReward"); + + b.Navigation("RawSkillReward"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AreaSkillSettings", "RawAreaSkillSettings") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "AreaSkillSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawElementalModifierTarget") + .WithMany() + .HasForeignKey("ElementalModifierTargetId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawSkills") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MagicEffectDefinition", "RawMagicEffectDef") + .WithMany() + .HasForeignKey("MagicEffectDefId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillDefinition", "RawMasterDefinition") + .WithOne() + .HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "MasterDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawAreaSkillSettings"); + + b.Navigation("RawElementalModifierTarget"); + + b.Navigation("RawMagicEffectDef"); + + b.Navigation("RawMasterDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillCharacterClass", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", "CharacterClass") + .WithMany() + .HasForeignKey("CharacterClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "Skill") + .WithMany("JoinedQualifiedCharacters") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CharacterClass"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillComboStep", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillComboDefinition", null) + .WithMany("RawSteps") + .HasForeignKey("SkillComboDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "RawSkill") + .WithMany() + .HasForeignKey("SkillId"); + + b.Navigation("RawSkill"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillEntry", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", null) + .WithMany("RawLearnedSkills") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", "RawSkill") + .WithMany() + .HasForeignKey("SkillId"); + + b.Navigation("RawSkill"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.StatAttribute", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Account", null) + .WithMany("RawAttributes") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", null) + .WithMany("RawAttributes") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawDefinition") + .WithMany() + .HasForeignKey("DefinitionId"); + + b.Navigation("RawDefinition"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.StatAttributeDefinition", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.AttributeDefinition", "RawAttribute") + .WithMany() + .HasForeignKey("AttributeId"); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", null) + .WithMany("RawStatAttributes") + .HasForeignKey("CharacterClassId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RawAttribute"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.WarpInfo", b => + { + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", null) + .WithMany("RawWarpList") + .HasForeignKey("GameConfigurationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ExitGate", "RawGate") + .WithMany() + .HasForeignKey("GateId"); + + b.Navigation("RawGate"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Account", b => + { + b.Navigation("JoinedUnlockedCharacterClasses"); + + b.Navigation("RawAttributes"); + + b.Navigation("RawCharacters"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.AppearanceData", b => + { + b.Navigation("RawEquippedItems"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", b => + { + b.Navigation("JoinedDropItemGroups"); + + b.Navigation("RawAttributes"); + + b.Navigation("RawLearnedSkills"); + + b.Navigation("RawLetters"); + + b.Navigation("RawQuestStates"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterClass", b => + { + b.Navigation("RawAttributeCombinations"); + + b.Navigation("RawBaseAttributeValues"); + + b.Navigation("RawStatAttributes"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CharacterQuestState", b => + { + b.Navigation("RawRequirementStates"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ChatServerDefinition", b => + { + b.Navigation("RawEndpoints"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DropItemGroup", b => + { + b.Navigation("JoinedPossibleItems"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.DuelConfiguration", b => + { + b.Navigation("RawDuelAreas"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", b => + { + b.Navigation("RawAttributes"); + + b.Navigation("RawCharacterClasses"); + + b.Navigation("RawDropItemGroups"); + + b.Navigation("RawItemLevelBonusTables"); + + b.Navigation("RawItemOptionCombinationBonuses"); + + b.Navigation("RawItemOptionTypes"); + + b.Navigation("RawItemOptions"); + + b.Navigation("RawItemSetGroups"); + + b.Navigation("RawItemSlotTypes"); + + b.Navigation("RawItems"); + + b.Navigation("RawJewelMixes"); + + b.Navigation("RawMagicEffects"); + + b.Navigation("RawMaps"); + + b.Navigation("RawMasterSkillRoots"); + + b.Navigation("RawMiniGameDefinitions"); + + b.Navigation("RawMonsters"); + + b.Navigation("RawPlugInConfigurations"); + + b.Navigation("RawSkills"); + + b.Navigation("RawWarpList"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", b => + { + b.Navigation("JoinedDropItemGroups"); + + b.Navigation("RawCharacterPowerUpDefinitions"); + + b.Navigation("RawEnterGates"); + + b.Navigation("RawExitGates"); + + b.Navigation("RawMapRequirements"); + + b.Navigation("RawMonsterSpawns"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerConfiguration", b => + { + b.Navigation("JoinedMaps"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameServerDefinition", b => + { + b.Navigation("RawEndpoints"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Guild", b => + { + b.Navigation("RawMembers"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.IncreasableItemOption", b => + { + b.Navigation("RawLevelDependentOptions"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Item", b => + { + b.Navigation("JoinedItemSetGroups"); + + b.Navigation("RawItemOptions"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemAppearance", b => + { + b.Navigation("JoinedVisibleOptions"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemCraftingRequiredItem", b => + { + b.Navigation("JoinedPossibleItems"); + + b.Navigation("JoinedRequiredItemOptions"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", b => + { + b.Navigation("JoinedPossibleItemOptions"); + + b.Navigation("JoinedPossibleItemSetGroups"); + + b.Navigation("JoinedQualifiedCharacters"); + + b.Navigation("RawBasePowerUpAttributes"); + + b.Navigation("RawDropItems"); + + b.Navigation("RawRequirements"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDropItemGroup", b => + { + b.Navigation("JoinedPossibleItems"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemLevelBonusTable", b => + { + b.Navigation("RawBonusPerLevel"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionCombinationBonus", b => + { + b.Navigation("RawRequirements"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemOptionDefinition", b => + { + b.Navigation("RawPossibleOptions"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemSetGroup", b => + { + b.Navigation("RawItems"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemStorage", b => + { + b.Navigation("RawItems"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MagicEffectDefinition", b => + { + b.Navigation("RawPowerUpDefinitions"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MasterSkillDefinition", b => + { + b.Navigation("JoinedRequiredMasterSkills"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameChangeEvent", b => + { + b.Navigation("RawTerrainChanges"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MiniGameDefinition", b => + { + b.Navigation("RawChangeEvents"); + + b.Navigation("RawRewards"); + + b.Navigation("RawSpawnWaves"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", b => + { + b.Navigation("JoinedDropItemGroups"); + + b.Navigation("RawAttributes"); + + b.Navigation("RawItemCraftings"); + + b.Navigation("RawQuests"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.PowerUpDefinitionValue", b => + { + b.Navigation("RawRelatedValues"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.QuestDefinition", b => + { + b.Navigation("RawRequiredItems"); + + b.Navigation("RawRequiredMonsterKills"); + + b.Navigation("RawRewards"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SimpleCraftingSettings", b => + { + b.Navigation("RawRequiredItems"); + + b.Navigation("RawResultItems"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Skill", b => + { + b.Navigation("JoinedQualifiedCharacters"); + + b.Navigation("RawConsumeRequirements"); + + b.Navigation("RawRequirements"); + }); + + modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.SkillComboDefinition", b => + { + b.Navigation("RawSteps"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Persistence/EntityFramework/Migrations/20250221154911_AddStageToAttributeEntities.cs b/src/Persistence/EntityFramework/Migrations/20250221154911_AddStageToAttributeEntities.cs new file mode 100644 index 000000000..906821a14 --- /dev/null +++ b/src/Persistence/EntityFramework/Migrations/20250221154911_AddStageToAttributeEntities.cs @@ -0,0 +1,109 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations +{ + /// + public partial class AddStageToAttributeEntities : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Stage", + schema: "config", + table: "PowerUpDefinitionValue", + type: "smallint", + nullable: false, + defaultValue: (byte)0); + + migrationBuilder.AddColumn( + name: "ExtendsDuration", + schema: "config", + table: "MasterSkillDefinition", + type: "boolean", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Stage", + schema: "config", + table: "ItemBasePowerUpDefinition", + type: "smallint", + nullable: false, + defaultValue: (byte)0); + + migrationBuilder.AddColumn( + name: "AggregateType", + schema: "config", + table: "ConstValueAttribute", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Stage", + schema: "config", + table: "ConstValueAttribute", + type: "smallint", + nullable: false, + defaultValue: (byte)0); + + migrationBuilder.AddColumn( + name: "AggregateType", + schema: "config", + table: "AttributeRelationship", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Stage", + schema: "config", + table: "AttributeRelationship", + type: "smallint", + nullable: false, + defaultValue: (byte)0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Stage", + schema: "config", + table: "PowerUpDefinitionValue"); + + migrationBuilder.DropColumn( + name: "ExtendsDuration", + schema: "config", + table: "MasterSkillDefinition"); + + migrationBuilder.DropColumn( + name: "Stage", + schema: "config", + table: "ItemBasePowerUpDefinition"); + + migrationBuilder.DropColumn( + name: "AggregateType", + schema: "config", + table: "ConstValueAttribute"); + + migrationBuilder.DropColumn( + name: "Stage", + schema: "config", + table: "ConstValueAttribute"); + + migrationBuilder.DropColumn( + name: "AggregateType", + schema: "config", + table: "AttributeRelationship"); + + migrationBuilder.DropColumn( + name: "Stage", + schema: "config", + table: "AttributeRelationship"); + } + } +} diff --git a/src/Persistence/EntityFramework/Migrations/EntityDataContextModelSnapshot.cs b/src/Persistence/EntityFramework/Migrations/EntityDataContextModelSnapshot.cs index dab00efec..34592788d 100644 --- a/src/Persistence/EntityFramework/Migrations/EntityDataContextModelSnapshot.cs +++ b/src/Persistence/EntityFramework/Migrations/EntityDataContextModelSnapshot.cs @@ -196,6 +196,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("AggregateType") + .HasColumnType("integer"); + b.Property("CharacterClassId") .HasColumnType("uuid"); @@ -214,6 +217,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PowerUpDefinitionValueId") .HasColumnType("uuid"); + b.Property("Stage") + .HasColumnType("smallint"); + b.Property("TargetAttributeId") .HasColumnType("uuid"); @@ -706,12 +712,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("AggregateType") + .HasColumnType("integer"); + b.Property("CharacterClassId") .HasColumnType("uuid"); b.Property("DefinitionId") .HasColumnType("uuid"); + b.Property("Stage") + .HasColumnType("smallint"); + b.Property("Value") .HasColumnType("real"); @@ -1408,6 +1420,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("ItemDefinitionId") .HasColumnType("uuid"); + b.Property("Stage") + .HasColumnType("smallint"); + b.Property("TargetAttributeId") .HasColumnType("uuid"); @@ -2239,6 +2254,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("ExtendsDuration") + .HasColumnType("boolean"); + b.Property("MaximumLevel") .HasColumnType("smallint"); @@ -2805,6 +2823,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("AggregateType") .HasColumnType("integer"); + b.Property("Stage") + .HasColumnType("smallint"); + b.Property("Value") .HasColumnType("real"); diff --git a/src/Persistence/EntityFramework/Model/AttributeRelationship.Custom.cs b/src/Persistence/EntityFramework/Model/AttributeRelationship.Custom.cs index 41e063697..f6562269c 100644 --- a/src/Persistence/EntityFramework/Model/AttributeRelationship.Custom.cs +++ b/src/Persistence/EntityFramework/Model/AttributeRelationship.Custom.cs @@ -39,5 +39,6 @@ public virtual void AssignValuesOf(AttributeSystem.AttributeRelationship other, this.TargetAttribute = gameConfiguration.Attributes.FirstOrDefault(a => a.Id == other.TargetAttribute?.Id) ?? other.TargetAttribute; this.InputOperand = other.InputOperand; this.InputOperator = other.InputOperator; + this.AggregateType = other.AggregateType; } } \ No newline at end of file diff --git a/src/Persistence/EntityFramework/Model/AttributeRelationship.Generated.cs b/src/Persistence/EntityFramework/Model/AttributeRelationship.Generated.cs index 4de94f04f..17680ed55 100644 --- a/src/Persistence/EntityFramework/Model/AttributeRelationship.Generated.cs +++ b/src/Persistence/EntityFramework/Model/AttributeRelationship.Generated.cs @@ -28,22 +28,22 @@ public AttributeRelationship() } /// - public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, System.Single inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute) - : base(targetAttribute, inputOperand, inputAttribute) + public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, System.Single inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute, MUnique.OpenMU.AttributeSystem.AggregateType aggregateType, System.Byte stage) + : base(targetAttribute, inputOperand, inputAttribute, aggregateType, stage) { } /// - public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute) - : base(targetAttribute, inputOperand, inputAttribute) + public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute, MUnique.OpenMU.AttributeSystem.AggregateType aggregateType, System.Byte stage) + : base(targetAttribute, inputOperand, inputAttribute, aggregateType, stage) { } /// - public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, System.Single inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute, MUnique.OpenMU.AttributeSystem.InputOperator inputOperator, MUnique.OpenMU.AttributeSystem.AttributeDefinition operandAttribute) - : base(targetAttribute, inputOperand, inputAttribute, inputOperator, operandAttribute) + public AttributeRelationship(MUnique.OpenMU.AttributeSystem.AttributeDefinition targetAttribute, System.Single inputOperand, MUnique.OpenMU.AttributeSystem.AttributeDefinition inputAttribute, MUnique.OpenMU.AttributeSystem.InputOperator inputOperator, MUnique.OpenMU.AttributeSystem.AttributeDefinition operandAttribute, MUnique.OpenMU.AttributeSystem.AggregateType aggregateType, System.Byte stage) + : base(targetAttribute, inputOperand, inputAttribute, inputOperator, operandAttribute, aggregateType, stage) { } diff --git a/src/Persistence/EntityFramework/Model/ConstValueAttribute.Generated.cs b/src/Persistence/EntityFramework/Model/ConstValueAttribute.Generated.cs index 4325178a0..c19cefcbf 100644 --- a/src/Persistence/EntityFramework/Model/ConstValueAttribute.Generated.cs +++ b/src/Persistence/EntityFramework/Model/ConstValueAttribute.Generated.cs @@ -23,8 +23,8 @@ internal partial class ConstValueAttribute : MUnique.OpenMU.AttributeSystem.Cons { /// - public ConstValueAttribute(System.Single value, MUnique.OpenMU.AttributeSystem.AttributeDefinition definition) - : base(value, definition) + public ConstValueAttribute(System.Single value, MUnique.OpenMU.AttributeSystem.AttributeDefinition definition, MUnique.OpenMU.AttributeSystem.AggregateType aggregateType, System.Byte stage) + : base(value, definition, aggregateType, stage) { } diff --git a/src/Persistence/EntityFramework/Model/ExtendedTypes.Custom.cs b/src/Persistence/EntityFramework/Model/ExtendedTypes.Custom.cs index 4131dda43..e6455425d 100644 --- a/src/Persistence/EntityFramework/Model/ExtendedTypes.Custom.cs +++ b/src/Persistence/EntityFramework/Model/ExtendedTypes.Custom.cs @@ -46,6 +46,15 @@ public AggregateType AggregateType get => this.ConstantValue!.AggregateType; set => this.ConstantValue!.AggregateType = value; } + + /// + /// Gets the calculation stage. + /// + public byte Stage + { + get => this.ConstantValue!.Stage; + set => this.ConstantValue!.Stage = value; + } } /// @@ -82,6 +91,18 @@ public ConstValueAttribute() get => base.Value; set => base.Value = value; } + + public new AggregateType AggregateType + { + get => base.AggregateType; + set => base.AggregateType = value; + } + + public new byte Stage + { + get => base.Stage; + set => base.Stage = value; + } } /// diff --git a/src/Persistence/Initialization/CharacterClasses/CharacterClassHelper.cs b/src/Persistence/Initialization/CharacterClasses/CharacterClassHelper.cs index 34b0812e7..b53b22555 100644 --- a/src/Persistence/Initialization/CharacterClasses/CharacterClassHelper.cs +++ b/src/Persistence/Initialization/CharacterClasses/CharacterClassHelper.cs @@ -139,10 +139,19 @@ public static IEnumerable DetermineCharacterClasses(this GameCon /// The multiplier. /// The source attribute. /// The input operator. - /// The attribute relationship - public static AttributeRelationship CreateAttributeRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, float multiplier, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply) + /// The aggregate type with which the relationship will effect the . + /// The calculation stage at which the product of the relationship will effect the . + /// The attribute relationship. + public static AttributeRelationship CreateAttributeRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, float multiplier, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { - return context.CreateNew(targetAttribute.GetPersistent(gameConfiguration) ?? targetAttribute, multiplier, sourceAttribute.GetPersistent(gameConfiguration) ?? sourceAttribute, inputOperator, default(AttributeDefinition?)); + return context.CreateNew( + targetAttribute.GetPersistent(gameConfiguration) ?? targetAttribute, + multiplier, + sourceAttribute.GetPersistent(gameConfiguration) ?? sourceAttribute, + inputOperator, + default(AttributeDefinition?), + aggregateType, + stage); } /// @@ -154,15 +163,19 @@ public static AttributeRelationship CreateAttributeRelationship(IContext context /// The multiplier attribute. /// The source attribute. /// The input operator. - /// The attribute relationship - public static AttributeRelationship CreateAttributeRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, AttributeDefinition multiplierAttribute, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply) + /// The aggregate type with which the relationship will effect the . + /// The calculation stage at which the product of the relationship will effect the . + /// The attribute relationship. + public static AttributeRelationship CreateAttributeRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, AttributeDefinition multiplierAttribute, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { return context.CreateNew( targetAttribute.GetPersistent(gameConfiguration) ?? targetAttribute, 0f, sourceAttribute.GetPersistent(gameConfiguration) ?? sourceAttribute, inputOperator, - multiplierAttribute.GetPersistent(gameConfiguration) ?? multiplierAttribute); + multiplierAttribute.GetPersistent(gameConfiguration) ?? multiplierAttribute, + aggregateType, + stage); } /// @@ -173,13 +186,17 @@ public static AttributeRelationship CreateAttributeRelationship(IContext context /// The target attribute. /// The conditional attribute. /// The source attribute. - /// The attribute relationship - public static AttributeRelationship CreateConditionalRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, AttributeDefinition conditionalAttribute, AttributeDefinition sourceAttribute) + /// The aggregate type with which the relationship will effect the . + /// The calculation stage at which the product of the relationship will effect the . + /// The attribute relationship. + public static AttributeRelationship CreateConditionalRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, AttributeDefinition conditionalAttribute, AttributeDefinition sourceAttribute, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { return context.CreateNew( targetAttribute.GetPersistent(gameConfiguration) ?? targetAttribute, conditionalAttribute.GetPersistent(gameConfiguration) ?? conditionalAttribute, - sourceAttribute.GetPersistent(gameConfiguration) ?? sourceAttribute); + sourceAttribute.GetPersistent(gameConfiguration) ?? sourceAttribute, + aggregateType, + stage); } /// @@ -189,9 +206,11 @@ public static AttributeRelationship CreateConditionalRelationship(IContext conte /// The game configuration. /// The value. /// The attribute. + /// The aggregate type to effect the . + /// The calculation stage to effect the . /// The constant value attribute. - public static ConstValueAttribute CreateConstValueAttribute(IContext context, GameConfiguration gameConfiguration, float value, AttributeDefinition attribute) + public static ConstValueAttribute CreateConstValueAttribute(IContext context, GameConfiguration gameConfiguration, float value, AttributeDefinition attribute, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { - return context.CreateNew(value, attribute.GetPersistent(gameConfiguration)); + return context.CreateNew(value, attribute.GetPersistent(gameConfiguration), aggregateType, stage); } } \ No newline at end of file diff --git a/src/Persistence/Initialization/CharacterClasses/CharacterClassInitialization.cs b/src/Persistence/Initialization/CharacterClasses/CharacterClassInitialization.cs index 2e2e92dda..b68fab5c4 100644 --- a/src/Persistence/Initialization/CharacterClasses/CharacterClassInitialization.cs +++ b/src/Persistence/Initialization/CharacterClasses/CharacterClassInitialization.cs @@ -69,28 +69,31 @@ private StatAttributeDefinition CreateStatAttributeDefinition(AttributeDefinitio return definition; } - private AttributeRelationship CreateAttributeRelationship(AttributeDefinition targetAttribute, float multiplier, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply) + private AttributeRelationship CreateAttributeRelationship(AttributeDefinition targetAttribute, float multiplier, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { - return CharacterClassHelper.CreateAttributeRelationship(this.Context, this.GameConfiguration, targetAttribute, multiplier, sourceAttribute, inputOperator); + return CharacterClassHelper.CreateAttributeRelationship(this.Context, this.GameConfiguration, targetAttribute, multiplier, sourceAttribute, inputOperator, aggregateType, stage); } - private AttributeRelationship CreateAttributeRelationship(AttributeDefinition targetAttribute, AttributeDefinition multiplierAttribute, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply) + private AttributeRelationship CreateAttributeRelationship(AttributeDefinition targetAttribute, AttributeDefinition multiplierAttribute, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { - return CharacterClassHelper.CreateAttributeRelationship(this.Context, this.GameConfiguration, targetAttribute, multiplierAttribute, sourceAttribute, inputOperator); + return CharacterClassHelper.CreateAttributeRelationship(this.Context, this.GameConfiguration, targetAttribute, multiplierAttribute, sourceAttribute, inputOperator, aggregateType, stage); } - private AttributeRelationship CreateConditionalRelationship(AttributeDefinition targetAttribute, AttributeDefinition conditionalAttribute, AttributeDefinition sourceAttribute) + private AttributeRelationship CreateConditionalRelationship(AttributeDefinition targetAttribute, AttributeDefinition conditionalAttribute, AttributeDefinition sourceAttribute, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { - return CharacterClassHelper.CreateConditionalRelationship(this.Context, this.GameConfiguration, targetAttribute, conditionalAttribute, sourceAttribute); + return CharacterClassHelper.CreateConditionalRelationship(this.Context, this.GameConfiguration, targetAttribute, conditionalAttribute, sourceAttribute, aggregateType, stage); } - private ConstValueAttribute CreateConstValueAttribute(float value, AttributeDefinition attribute) + private ConstValueAttribute CreateConstValueAttribute(float value, AttributeDefinition attribute, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0) { - return CharacterClassHelper.CreateConstValueAttribute(this.Context, this.GameConfiguration, value, attribute); + return CharacterClassHelper.CreateConstValueAttribute(this.Context, this.GameConfiguration, value, attribute, aggregateType, stage); } private void AddCommonAttributeRelationships(ICollection attributeRelationships) { + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.TotalLevel, 1, Stats.Level)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.TotalLevel, 1, Stats.MasterLevel)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.TotalStrength, 1, Stats.BaseStrength)); attributeRelationships.Add(this.CreateAttributeRelationship(Stats.TotalAgility, 1, Stats.BaseAgility)); attributeRelationships.Add(this.CreateAttributeRelationship(Stats.TotalVitality, 1, Stats.BaseVitality)); @@ -99,24 +102,53 @@ private void AddCommonAttributeRelationships(ICollection attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefensePvm, 1, Stats.DefenseBase)); attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefensePvp, 1, Stats.DefenseBase)); - attributeRelationships.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1, Stats.AttackSpeedByWeapon)); - attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1, Stats.AttackSpeedByWeapon)); - - // If two weapons are equipped we subtract the half of the sum of the speeds again from the attack speed + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.AttackSpeedAny, 1, Stats.AttackSpeedByWeapon)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1, Stats.AttackSpeedAny)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1, Stats.AttackSpeedAny)); + + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.SocketBaseMinDmgBonus, 1, Stats.SocketBaseDmgBonus)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.SocketBaseMaxDmgBonus, 1, Stats.SocketBaseDmgBonus)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.HarmonyPhysBaseDmg, stage: 2)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.HarmonyPhysBaseDmg, stage: 2)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.SocketBaseMinDmgBonus, stage: 2)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.SocketBaseMaxDmgBonus, stage: 2)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.ExcellentPhysBaseDmg, stage: 2)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.ExcellentPhysBaseDmg, stage: 2)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.ExcellentPhysTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.ExcellentPhysTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); + + // A double wield (DK, MG, RF) grants 110% physical attack dmg (here 55%, later doubled after base dmg calculations) + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.HasDoubleWield, 1, Stats.DoubleWieldWeaponCount, InputOperator.Maximum)); + var tempDoubleWield = this.Context.CreateNew(Guid.NewGuid(), "Temp Double Wield multiplier", string.Empty); + this.GameConfiguration.Attributes.Add(tempDoubleWield); + attributeRelationships.Add(this.CreateAttributeRelationship(tempDoubleWield, 1, Stats.Level, InputOperator.Minimum)); + attributeRelationships.Add(this.CreateAttributeRelationship(tempDoubleWield, -0.45f, Stats.HasDoubleWield)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, tempDoubleWield, aggregateType: AggregateType.Multiplicate, stage: 3)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, tempDoubleWield, aggregateType: AggregateType.Multiplicate, stage: 3)); + attributeRelationships.Add(this.CreateConditionalRelationship(Stats.MinimumPhysBaseDmgByWeapon, Stats.HasDoubleWield, Stats.MinPhysBaseDmgByRightWeapon)); + attributeRelationships.Add(this.CreateConditionalRelationship(Stats.MaximumPhysBaseDmgByWeapon, Stats.HasDoubleWield, Stats.MaxPhysBaseDmgByRightWeapon)); + + // If two weapons are equipped (DK, MG, Sum, RF) we subtract the half of the sum of the speeds again from the attack speed attributeRelationships.Add(this.CreateAttributeRelationship(Stats.AreTwoWeaponsEquipped, 1, Stats.EquippedWeaponCount)); var tempSpeed = this.Context.CreateNew(Guid.NewGuid(), "Temp Half weapon attack speed", string.Empty); this.GameConfiguration.Attributes.Add(tempSpeed); attributeRelationships.Add(this.CreateAttributeRelationship(tempSpeed, -0.5f, Stats.AttackSpeedByWeapon)); - attributeRelationships.Add(this.CreateConditionalRelationship(Stats.AttackSpeed, Stats.AreTwoWeaponsEquipped, tempSpeed)); - attributeRelationships.Add(this.CreateConditionalRelationship(Stats.MagicSpeed, Stats.AreTwoWeaponsEquipped, tempSpeed)); - - attributeRelationships.Add(this.CreateConditionalRelationship(Stats.DefenseBase, Stats.IsShieldEquipped, Stats.BonusDefenseWithShield)); + attributeRelationships.Add(this.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.AreTwoWeaponsEquipped, tempSpeed)); var tempDefense = this.Context.CreateNew(Guid.NewGuid(), "Temp Defense Bonus multiplier with Shield", string.Empty); this.GameConfiguration.Attributes.Add(tempDefense); - attributeRelationships.Add(this.CreateAttributeRelationship(tempDefense, Stats.IsShieldEquipped, Stats.DefenseIncreaseWithEquippedShield)); - attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefensePvm, tempDefense, Stats.DefenseBase)); - attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefensePvp, tempDefense, Stats.DefenseBase)); + attributeRelationships.Add(this.CreateAttributeRelationship(tempDefense, 1, Stats.Level, inputOperator: InputOperator.Minimum)); + attributeRelationships.Add(this.CreateConditionalRelationship(tempDefense, Stats.IsShieldEquipped, Stats.DefenseIncreaseWithEquippedShield)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1, tempDefense, aggregateType: AggregateType.Multiplicate, stage: 2)); + + attributeRelationships.Add(this.CreateConditionalRelationship(Stats.DefenseBase, Stats.IsShieldEquipped, Stats.BonusDefenseWithShield, stage: 3)); + attributeRelationships.Add(this.CreateConditionalRelationship(Stats.DefenseRatePvm, Stats.IsShieldEquipped, Stats.BonusDefenseRateWithShield, stage: 1)); attributeRelationships.Add(this.CreateAttributeRelationship(Stats.HealthRecoveryMultiplier, 0.01f, Stats.IsInSafezone)); if (this.UseClassicPvp) @@ -130,6 +162,7 @@ private void AddCommonAttributeRelationships(ICollection } attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumGuildSize, 0.1f, Stats.Level)); + attributeRelationships.Add(this.CreateAttributeRelationship(Stats.CanFly, 1, Stats.IsDinorantEquipped)); } private void AddCommonBaseAttributeValues(ICollection baseAttributeValues, bool isMaster) @@ -137,13 +170,15 @@ private void AddCommonBaseAttributeValues(ICollection baseA baseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 27.5f, Stats.ManaRecoveryMultiplier)); baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.DamageReceiveDecrement)); baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.AttackDamageIncrease)); - baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.TwoHandedWeaponDamageIncrease)); baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.MoneyAmountRate)); baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.ExperienceRate)); baseAttributeValues.Add(this.CreateConstValueAttribute(0.03f, Stats.PoisonDamageMultiplier)); baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.ItemDurationIncrease)); baseAttributeValues.Add(this.CreateConstValueAttribute(2, Stats.AbilityRecoveryAbsolute)); baseAttributeValues.Add(this.CreateConstValueAttribute(-1, Stats.AreTwoWeaponsEquipped)); + baseAttributeValues.Add(this.CreateConstValueAttribute(-1, Stats.HasDoubleWield)); + baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.ExcellentPhysTwoPercentInc)); + baseAttributeValues.Add(this.CreateConstValueAttribute(0.5f, Stats.DefenseBase, AggregateType.Multiplicate, stage: 1)); if (isMaster) { diff --git a/src/Persistence/Initialization/CharacterClasses/ClassDarkKnight.cs b/src/Persistence/Initialization/CharacterClasses/ClassDarkKnight.cs index 7f25c1f55..13516fee6 100644 --- a/src/Persistence/Initialization/CharacterClasses/ClassDarkKnight.cs +++ b/src/Persistence/Initialization/CharacterClasses/ClassDarkKnight.cs @@ -50,13 +50,13 @@ protected CharacterClass CreateDarkKnight(CharacterClassNumber number, string na result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 3, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 1.0f / 3, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1.0f / 15, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 20, Stats.TotalAgility)); - - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.5f, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1.0f / 15, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 20, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 1, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.3f, Stats.TotalVitality)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalAgility)); @@ -68,30 +68,18 @@ protected CharacterClass CreateDarkKnight(CharacterClassNumber number, string na result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 3, Stats.TotalVitality)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 6, Stats.TotalStrength)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 4, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.SkillMultiplier, 0.001f, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ComboBonus, 0.5f, Stats.TotalStrength)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ComboBonus, 0.5f, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ComboBonus, 0.5f, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.IsOneHandedSwordEquipped, Stats.WeaponMasteryAttackSpeed)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsOneHandedSwordEquipped, Stats.OneHandedSwordBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsTwoHandedSwordEquipped, Stats.TwoHandedSwordBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsSpearEquipped, Stats.SpearBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsMaceEquipped, Stats.MaceBonusBaseDamage)); - - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(10, Stats.MaximumMana)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(35, Stats.MaximumHealth)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(2, Stats.SkillMultiplier)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0.05f, Stats.AbilityRecoveryMultiplier)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseVitality)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseEnergy)); if (!this.UseClassicPvp) { @@ -105,13 +93,18 @@ protected CharacterClass CreateDarkKnight(CharacterClassNumber number, string na result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.Level, InputOperator.Exponentiate)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f / 30f, Stats.MaximumShieldTemp)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.5f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.5f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.TotalLevel)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4.5f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4.5f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel)); } + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(10, Stats.MaximumMana)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(35, Stats.MaximumHealth)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(2, Stats.SkillMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0.05f, Stats.AbilityRecoveryMultiplier)); + this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster); return result; diff --git a/src/Persistence/Initialization/CharacterClasses/ClassDarkLord.cs b/src/Persistence/Initialization/CharacterClasses/ClassDarkLord.cs index 10d3352b6..6d2e57414 100644 --- a/src/Persistence/Initialization/CharacterClasses/ClassDarkLord.cs +++ b/src/Persistence/Initialization/CharacterClasses/ClassDarkLord.cs @@ -36,7 +36,7 @@ private CharacterClass CreateDarkLord(CharacterClassNumber number, string name, result.LevelRequirementByCreation = 250; result.IsMasterClass = isMaster; result.NextGenerationClass = nextGenerationClass; - result.LevelWarpRequirementReductionPercent = (int) Math.Ceiling(100.0 / 3); + result.LevelWarpRequirementReductionPercent = (int)Math.Ceiling(100.0 / 3); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Level, 1, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.PointsPerLevelUp, 7, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseStrength, 26, true)); @@ -44,8 +44,8 @@ private CharacterClass CreateDarkLord(CharacterClassNumber number, string name, result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseVitality, 20, true)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 15, true)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseLeadership, 25, true)); - result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 1, false)); - result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 1, false)); + result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 90, false)); + result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 40, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentAbility, 1, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.IsInSafezone, 1, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Resets, 0, false)); @@ -57,9 +57,9 @@ private CharacterClass CreateDarkLord(CharacterClassNumber number, string name, result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 7, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 1.0f / 7, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.Level)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 2.5f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.0f / 6, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 3, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.0f / 10, Stats.TotalLeadership)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1.0f / 10, Stats.TotalAgility)); @@ -73,50 +73,47 @@ private CharacterClass CreateDarkLord(CharacterClassNumber number, string name, result.AttributeCombinations.Add(this.CreateAttributeRelationship(energyMinus15, -15, Stats.TotalEnergy, InputOperator.Add)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1.5f, energyMinus15)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 0.5f, Stats.Level)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, Stats.Level)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 3, Stats.TotalVitality)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1.5f, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, Stats.TotalVitality)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 7, Stats.TotalStrength)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 5, Stats.TotalStrength)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 14, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 10, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.SkillMultiplier, 0.0005f, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.PetAttackDamageIncrease, 1.0f / 100, Stats.ScepterRise)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenAttackDamageIncrease, 1.0f / 100, Stats.ScepterRise)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumGuildSize, 0.1f, Stats.TotalLeadership)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DamageReceiveDecrement, 1, Stats.DamageReceiveHorseDecrement, aggregateType: AggregateType.Multiplicate)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalLeadership)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseVitality)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseLeadership)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenMinimumDamage, 1, Stats.RavenBaseDamage)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenMinimumDamage, 1.0f / 8, Stats.TotalLeadership)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenMinimumDamage, 15, Stats.RavenLevel)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenMaximumDamage, 1.0f / 4, Stats.TotalLeadership)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenMaximumDamage, 15, Stats.RavenLevel)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenMaximumDamage, 1, Stats.RavenBaseDamage)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenAttackSpeed, 1.0f / 50, Stats.TotalLeadership)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenAttackSpeed, 4.0f / 5, Stats.RavenLevel)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenAttackRate, 16, Stats.RavenLevel)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.RavenAttackRate, 16f / 15, Stats.RavenLevel)); + + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.RavenBonusDamage, Stats.IsScepterEquipped, Stats.ScepterPetBonusDamage)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.BonusDamageWithScepter, Stats.BonusDamageWithScepterCmdDiv, Stats.TotalLeadership)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MasterSkillPhysBonusDmg, Stats.IsScepterEquipped, Stats.BonusDamageWithScepter)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.DefenseBase, Stats.IsHorseEquipped, Stats.BonusDefenseWithHorse, stage: 3)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ElectricSpikeBonusDmg, 1.0f / 10, Stats.TotalLeadership)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.EarthshakeBonusDmg, 1.0f / 10, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.EarthshakeBonusDmg, 1.0f / 5, Stats.TotalLeadership)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.EarthshakeBonusDmg, 10, Stats.HorseLevel)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ChaoticDiseierBonusDmg, 1.0f / 30, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ChaoticDiseierBonusDmg, 1.0f / 55, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DarkLordGenericSkillBonusDmg, 1.0f / 25, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DarkLordGenericSkillBonusDmg, 1.0f / 50, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsScepterEquipped, Stats.ScepterBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.RavenBaseDamage, Stats.IsScepterEquipped, Stats.ScepterPetBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.DefenseBase, Stats.IsScepterEquipped, Stats.BonusDefenseWithScepter)); - - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BonusDefenseWithScepter, Stats.BonusDefenseWithScepterCmdDiv, Stats.TotalLeadership)); - - /* TODO: Add these stats - Critical dmg = cmd/25+str/30 - Fireburst bonus min dmg = 100+str/25+ene/50 - Fireburst bonus max dmg = 150+str/25+ene/50 - Horse bonus dmg = 100+horseLvl*10+lvl*2.5+str/10+cmd/5 - */ if (!this.UseClassicPvp) { result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentShield, 1, false)); @@ -130,11 +127,11 @@ private CharacterClass CreateDarkLord(CharacterClassNumber number, string name, result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.Level, InputOperator.Exponentiate)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f / 30f, Stats.MaximumShieldTemp)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.5f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.5f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.TotalLevel)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4.0f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4.0f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel)); } result.BaseAttributeValues.Add(this.CreateConstValueAttribute(38, Stats.MaximumMana)); @@ -142,11 +139,13 @@ private CharacterClass CreateDarkLord(CharacterClassNumber number, string name, result.BaseAttributeValues.Add(this.CreateConstValueAttribute(2, Stats.SkillMultiplier)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.PetDurationIncrease)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.DamageReceiveHorseDecrement)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(180, Stats.RavenMinimumDamage)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(200, Stats.RavenMaximumDamage)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(20, Stats.RavenAttackSpeed)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1000, Stats.RavenAttackRate)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0.3f, Stats.RavenCriticalDamageChance)); this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster); diff --git a/src/Persistence/Initialization/CharacterClasses/ClassDarkWizard.cs b/src/Persistence/Initialization/CharacterClasses/ClassDarkWizard.cs index 5bc5c8ddc..dd56706dc 100644 --- a/src/Persistence/Initialization/CharacterClasses/ClassDarkWizard.cs +++ b/src/Persistence/Initialization/CharacterClasses/ClassDarkWizard.cs @@ -48,10 +48,10 @@ protected CharacterClass CreateDarkWizard(CharacterClassNumber number, string na this.AddCommonAttributeRelationships(result.AttributeCombinations); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 10, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 4, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 1.0f / 3, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.5f, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); @@ -69,34 +69,41 @@ protected CharacterClass CreateDarkWizard(CharacterClassNumber number, string na result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, Stats.TotalVitality)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 8, Stats.TotalStrength)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 4, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1.0f / 9, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1.0f / 4, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.WizardryBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.WizardryBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.HarmonyWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.HarmonyWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.SocketBaseMinDmgBonus, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.SocketBaseMaxDmgBonus, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.ExcellentWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.ExcellentWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.ExcellentWizTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.ExcellentWizTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.AncientWizDmgIncrease, aggregateType: AggregateType.Multiplicate, stage: 3)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.AncientWizDmgIncrease, aggregateType: AggregateType.Multiplicate, stage: 3)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.WizardryAttackDamageIncrease, 1.0f / 100, Stats.StaffRise)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.WizardryBaseDmg, Stats.IsOneHandedStaffEquipped, Stats.OneHandedStaffBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.WizardryBaseDmg, Stats.IsTwoHandedStaffEquipped, Stats.TwoHandedStaffBonusBaseDamage)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MinimumWizBaseDmg, Stats.IsOneHandedStaffEquipped, Stats.OneHandedStaffBonusBaseDamage, stage: 4)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaximumWizBaseDmg, Stats.IsOneHandedStaffEquipped, Stats.OneHandedStaffBonusBaseDamage, stage: 4)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.IsOneHandedStaffEquipped, Stats.WeaponMasteryAttackSpeed)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MinimumWizBaseDmg, Stats.IsTwoHandedStaffEquipped, Stats.TwoHandedStaffBonusBaseDamage, stage: 4)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaximumWizBaseDmg, Stats.IsTwoHandedStaffEquipped, Stats.TwoHandedStaffBonusBaseDamage, stage: 4)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseVitality)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.NovaBonusDamage, 1.0f / 2, Stats.TotalStrength)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(30, Stats.MaximumHealth)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.SkillMultiplier)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f, Stats.WizardryAttackDamageIncrease)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier)); - if (!this.UseClassicPvp) { result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentShield, 1, false)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalVitality)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalAgility)); @@ -105,13 +112,19 @@ protected CharacterClass CreateDarkWizard(CharacterClassNumber number, string na result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.Level, InputOperator.Exponentiate)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f / 30f, Stats.MaximumShieldTemp)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.25f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.25f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.TotalLevel)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel)); } + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(30, Stats.MaximumHealth)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f, Stats.WizardryAttackDamageIncrease)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.ExcellentWizTwoPercentInc)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.AncientWizDmgIncrease)); + this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster); return result; diff --git a/src/Persistence/Initialization/CharacterClasses/ClassFairyElf.cs b/src/Persistence/Initialization/CharacterClasses/ClassFairyElf.cs index e8184a94d..0844bf0f5 100644 --- a/src/Persistence/Initialization/CharacterClasses/ClassFairyElf.cs +++ b/src/Persistence/Initialization/CharacterClasses/ClassFairyElf.cs @@ -24,6 +24,9 @@ internal partial class CharacterClassInitialization /// The created character class. protected CharacterClass CreateFairyElf(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated) { + var ammunitionDmgIncrease = this.Context.CreateNew(Guid.NewGuid(), "Ammunition damage increase", string.Empty); + this.GameConfiguration.Attributes.Add(ammunitionDmgIncrease); + var result = this.Context.CreateNew(); result.SetGuid((byte)number); this.GameConfiguration.CharacterClasses.Add(result); @@ -48,10 +51,12 @@ protected CharacterClass CreateFairyElf(CharacterClassNumber number, string name this.AddCommonAttributeRelationships(result.AttributeCombinations); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.TotalStrengthAndAgility, Stats.TotalAgility, Stats.TotalStrength, InputOperator.Add)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 10, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 0.25f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.5f, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); @@ -67,27 +72,30 @@ protected CharacterClass CreateFairyElf(CharacterClassNumber number, string name result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1.5f, Stats.Level)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, Stats.Level)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 7, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 4, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 14, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 8, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalEnergy)); - - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsBowEquipped, Stats.BowBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsCrossBowEquipped, Stats.CrossBowBonusBaseDamage)); - - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(39, Stats.MaximumHealth)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(6, Stats.MaximumMana)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.SkillMultiplier)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ArcheryMinDmg, 1.0f / 7, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ArcheryMaxDmg, 1.0f / 4, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ArcheryMinDmg, 1.0f / 14, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ArcheryMaxDmg, 1.0f / 8, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MeleeMinDmg, 1.0f / 7, Stats.TotalStrengthAndAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MeleeMaxDmg, 1.0f / 4, Stats.TotalStrengthAndAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, ammunitionDmgIncrease, aggregateType: AggregateType.Multiplicate, stage: 3)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, ammunitionDmgIncrease, aggregateType: AggregateType.Multiplicate, stage: 3)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ArcheryAttackMode, 1, Stats.IsBowEquipped)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.ArcheryAttackMode, 1, Stats.IsCrossBowEquipped)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MeleeAttackMode, -1, Stats.ArcheryAttackMode)); + + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MinimumPhysBaseDmg, Stats.ArcheryAttackMode, Stats.ArcheryMinDmg)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaximumPhysBaseDmg, Stats.ArcheryAttackMode, Stats.ArcheryMaxDmg)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(ammunitionDmgIncrease, Stats.ArcheryAttackMode, Stats.AmmunitionDamageBonus)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MinimumPhysBaseDmg, Stats.MeleeAttackMode, Stats.MeleeMinDmg)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaximumPhysBaseDmg, Stats.MeleeAttackMode, Stats.MeleeMaxDmg)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.IsBowEquipped, Stats.WeaponMasteryAttackSpeed)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseVitality)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseEnergy)); if (!this.UseClassicPvp) { @@ -101,14 +109,22 @@ protected CharacterClass CreateFairyElf(CharacterClassNumber number, string name result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.Level, InputOperator.Exponentiate)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f / 30f, Stats.MaximumShieldTemp)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.1f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.1f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.TotalLevel)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 0.6f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 0.6f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel)); } + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(39, Stats.MaximumHealth)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(6, Stats.MaximumMana)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(2, Stats.SkillMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.MeleeAttackMode)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, ammunitionDmgIncrease)); + this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster); + return result; } diff --git a/src/Persistence/Initialization/CharacterClasses/ClassMagicGladiator.cs b/src/Persistence/Initialization/CharacterClasses/ClassMagicGladiator.cs index 98c765400..949b5caf8 100644 --- a/src/Persistence/Initialization/CharacterClasses/ClassMagicGladiator.cs +++ b/src/Persistence/Initialization/CharacterClasses/ClassMagicGladiator.cs @@ -35,7 +35,6 @@ protected CharacterClass CreateMagicGladiator(CharacterClassNumber number, strin result.SetGuid((byte)number); this.GameConfiguration.CharacterClasses.Add(result); result.CanGetCreated = canGetCreated; - result.LevelWarpRequirementReductionPercent = (int) Math.Ceiling(100.0 / 3); result.HomeMap = this.GameConfiguration.Maps.FirstOrDefault(map => map.Number == LorenciaMapId); result.Number = (byte)number; result.Name = name; @@ -43,12 +42,13 @@ protected CharacterClass CreateMagicGladiator(CharacterClassNumber number, strin result.IsMasterClass = isMaster; result.LevelRequirementByCreation = 220; result.NextGenerationClass = nextGenerationClass; + result.LevelWarpRequirementReductionPercent = (int)Math.Ceiling(100.0 / 3); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Level, 1, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.PointsPerLevelUp, 7, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseStrength, 26, true)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseAgility, 26, true)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseVitality, 26, true)); - result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 16, true)); + result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 26, true)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 110, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 60, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentAbility, 1, false)); @@ -57,16 +57,16 @@ protected CharacterClass CreateMagicGladiator(CharacterClassNumber number, strin this.AddCommonAttributeRelationships(result.AttributeCombinations); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 5, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 4, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 1.0f / 3, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1.0f / 15, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 20, Stats.TotalAgility)); - - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.5f, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1.0f / 15, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 20, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.15f, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.3f, Stats.TotalVitality)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.25f, Stats.TotalAgility)); @@ -80,20 +80,28 @@ protected CharacterClass CreateMagicGladiator(CharacterClassNumber number, strin result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 4, Stats.TotalStrength)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 12, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 8, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1.0f / 9, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1.0f / 4, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.WizardryBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.WizardryBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.HarmonyWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.HarmonyWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.SocketBaseMinDmgBonus, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.SocketBaseMaxDmgBonus, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.ExcellentWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.ExcellentWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.ExcellentWizTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.ExcellentWizTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.AncientWizDmgIncrease, aggregateType: AggregateType.Multiplicate, stage: 3)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.AncientWizDmgIncrease, aggregateType: AggregateType.Multiplicate, stage: 3)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.WizardryAttackDamageIncrease, 1.0f / 100, Stats.StaffRise)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsOneHandedSwordEquipped, Stats.OneHandedSwordBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsTwoHandedSwordEquipped, Stats.TwoHandedSwordBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.WizardryBaseDmg, Stats.IsOneHandedStaffEquipped, Stats.OneHandedStaffBonusBaseDamage)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.WizardryBaseDmg, Stats.IsTwoHandedStaffEquipped, Stats.TwoHandedStaffBonusBaseDamage)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MinimumWizBaseDmg, Stats.IsOneHandedStaffEquipped, Stats.OneHandedStaffBonusBaseDamage, stage: 4)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaximumWizBaseDmg, Stats.IsOneHandedStaffEquipped, Stats.OneHandedStaffBonusBaseDamage, stage: 4)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MinimumWizBaseDmg, Stats.IsTwoHandedStaffEquipped, Stats.TwoHandedStaffBonusBaseDamage, stage: 4)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaximumWizBaseDmg, Stats.IsTwoHandedStaffEquipped, Stats.TwoHandedStaffBonusBaseDamage, stage: 4)); if (!this.UseClassicPvp) { @@ -107,24 +115,28 @@ protected CharacterClass CreateMagicGladiator(CharacterClassNumber number, strin result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.Level, InputOperator.Exponentiate)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f / 30f, Stats.MaximumShieldTemp)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.25f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.25f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.TotalLevel)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3.5f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3.5f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel)); } - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseVitality)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseEnergy)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(57, Stats.MaximumHealth)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(7, Stats.MaximumMana)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(2, Stats.SkillMultiplier)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f, Stats.WizardryAttackDamageIncrease)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.ExcellentWizTwoPercentInc)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.AncientWizDmgIncrease)); + this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster); + return result; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/CharacterClasses/ClassRageFighter.cs b/src/Persistence/Initialization/CharacterClasses/ClassRageFighter.cs index 517eaf727..15a6a798b 100644 --- a/src/Persistence/Initialization/CharacterClasses/ClassRageFighter.cs +++ b/src/Persistence/Initialization/CharacterClasses/ClassRageFighter.cs @@ -33,7 +33,7 @@ private CharacterClass CreateRageFighter(CharacterClassNumber number, string nam result.IsMasterClass = isMaster; result.LevelRequirementByCreation = 150; result.NextGenerationClass = nextGenerationClass; - result.LevelWarpRequirementReductionPercent = (int) Math.Ceiling(100.0 / 3); + result.LevelWarpRequirementReductionPercent = (int)Math.Ceiling(100.0 / 3); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Level, 1, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.PointsPerLevelUp, 7, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseStrength, 32, true)); @@ -50,18 +50,17 @@ private CharacterClass CreateRageFighter(CharacterClassNumber number, string nam this.AddCommonAttributeRelationships(result.AttributeCombinations); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 8, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 1.0f / 10, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.113f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.Level)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 3, Stats.Level)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 2.5f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 6, Stats.TotalStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.2f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 1.5f, Stats.TotalLevel)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.5f, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3.5f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.Level)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 1.0f / 5, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3.6f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 2.6f, Stats.TotalLevel)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1.0f / 9, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 9, Stats.TotalAgility)); @@ -87,28 +86,22 @@ private CharacterClass CreateRageFighter(CharacterClassNumber number, string nam result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 5, Stats.TotalStrength)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 15, Stats.TotalVitality)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 12, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1.0f / 9, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1.0f / 4, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.WizardryBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.WizardryBaseDmg)); - - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalEnergy)); - - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.PhysicalBaseDmg, Stats.IsGloveWeaponEquipped, Stats.GloveWeaponBonusBaseDamage)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.SkillMultiplier, 0.001f, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.VitalitySkillMultiplier, 0.001f, Stats.TotalVitality)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseVitality)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseEnergy)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(57, Stats.MaximumHealth)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(7, Stats.MaximumMana)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(2, Stats.SkillMultiplier)); - + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0.5f, Stats.SkillMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0.5f, Stats.VitalitySkillMultiplier)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier)); + this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster); + return result; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/CharacterClasses/ClassSummoner.cs b/src/Persistence/Initialization/CharacterClasses/ClassSummoner.cs index d6e5de428..b6489559a 100644 --- a/src/Persistence/Initialization/CharacterClasses/ClassSummoner.cs +++ b/src/Persistence/Initialization/CharacterClasses/ClassSummoner.cs @@ -27,6 +27,19 @@ private CharacterClass CreateDimensionMaster() private CharacterClass CreateSummoner(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated) { + var statsMinWizAndCurseBaseDmg = this.Context.CreateNew(Guid.NewGuid(), "Stats min wiz and curse base dmg", string.Empty); + this.GameConfiguration.Attributes.Add(statsMinWizAndCurseBaseDmg); + var statsMaxWizAndCurseBaseDmg = this.Context.CreateNew(Guid.NewGuid(), "Stats max wiz and curse base dmg", string.Empty); + this.GameConfiguration.Attributes.Add(statsMaxWizAndCurseBaseDmg); + var berserkerHealthMultiplierDecrement = this.Context.CreateNew(Guid.NewGuid(), "Berserker health multiplier decrement", string.Empty); + this.GameConfiguration.Attributes.Add(berserkerHealthMultiplierDecrement); + var isBerserkerBuffed = this.Context.CreateNew(Guid.NewGuid(), "Is berserker buffed", string.Empty); + this.GameConfiguration.Attributes.Add(isBerserkerBuffed); + var berserkerHealthMultiplier = this.Context.CreateNew(Guid.NewGuid(), "Berserker health multiplier", string.Empty); + this.GameConfiguration.Attributes.Add(berserkerHealthMultiplier); + var finalBerserkerManaMultiplier = this.Context.CreateNew(Guid.NewGuid(), "Final berserker mana multiplier", string.Empty); + this.GameConfiguration.Attributes.Add(finalBerserkerManaMultiplier); + var result = this.Context.CreateNew(); result.SetGuid((byte)number); this.GameConfiguration.CharacterClasses.Add(result); @@ -44,7 +57,7 @@ private CharacterClass CreateSummoner(CharacterClassNumber number, string name, result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseVitality, 18, true)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 23, true)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 70, false)); - result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 20, false)); + result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 40, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentAbility, 1, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentShield, 1, false)); result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.IsInSafezone, 1, false)); @@ -52,17 +65,20 @@ private CharacterClass CreateSummoner(CharacterClassNumber number, string name, this.AddCommonAttributeRelationships(result.AttributeCombinations); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 10, Stats.TotalAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.TotalStrengthAndAgility, Stats.TotalAgility, Stats.TotalStrength, InputOperator.Add)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 3, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 0.25f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.1f, Stats.TotalAgility)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.5f, Stats.BaseAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, Stats.Level)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 5, Stats.TotalLevel)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.5f, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 0.25f, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 0.6f, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.Level)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3.5f, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1.0f / 20, Stats.TotalAgility)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 20, Stats.TotalAgility)); @@ -84,37 +100,77 @@ private CharacterClass CreateSummoner(CharacterClassNumber number, string name, result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1.5f, Stats.Level)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, Stats.Level)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 7, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 4, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmg)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1.0f / 9, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1.0f / 4, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1.0f / 7, Stats.TotalStrengthAndAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 4, Stats.TotalStrengthAndAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(statsMinWizAndCurseBaseDmg, 1.0f / 9, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(statsMaxWizAndCurseBaseDmg, 1.0f / 4, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, statsMinWizAndCurseBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, statsMaxWizAndCurseBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.WizardryBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.WizardryBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.HarmonyWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.HarmonyWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.SocketBaseMinDmgBonus, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.SocketBaseMaxDmgBonus, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.ExcellentWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.ExcellentWizBaseDmg, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.ExcellentWizTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.ExcellentWizTwoPercentInc, aggregateType: AggregateType.Multiplicate, stage: 2)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumWizBaseDmg, 1, Stats.AncientWizDmgIncrease, aggregateType: AggregateType.Multiplicate, stage: 3)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.AncientWizDmgIncrease, aggregateType: AggregateType.Multiplicate, stage: 3)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseDamageBonus, stage: 4)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.WizardryAttackDamageIncrease, 1.0f / 100, Stats.StaffRise)); - - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumCurseBaseDmg, 1.0f / 9, Stats.TotalEnergy)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumCurseBaseDmg, 1.0f / 4, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumCurseBaseDmg, 1, statsMinWizAndCurseBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumCurseBaseDmg, 1, statsMaxWizAndCurseBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumCurseBaseDmg, 1, Stats.CurseBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumCurseBaseDmg, 1, Stats.CurseBaseDmg)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.CurseAttackDamageIncrease, 1.0f / 100, Stats.BookRise)); - result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.WizardryBaseDmg, Stats.IsStickEquipped, Stats.StickBonusBaseDamage)); - - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalStrength)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalAgility)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalVitality)); - result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MinimumWizBaseDmg, Stats.IsStickEquipped, Stats.StickBonusBaseDamage, stage: 4)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaximumWizBaseDmg, Stats.IsStickEquipped, Stats.StickBonusBaseDamage, stage: 4)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.IsBookEquipped, Stats.WeaponMasteryAttackSpeed)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MinimumCurseBaseDmg, Stats.IsBookEquipped, Stats.BookBonusBaseDamage, stage: 2)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaximumCurseBaseDmg, Stats.IsBookEquipped, Stats.BookBonusBaseDamage, stage: 2)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(finalBerserkerManaMultiplier, 1, Stats.BerserkerManaMultiplier)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1, finalBerserkerManaMultiplier, aggregateType: AggregateType.Multiplicate)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(berserkerHealthMultiplierDecrement, -0.1f, Stats.BerserkerHealthMultiplierFactor, InputOperator.Minimum)); // At least -10% HP + result.AttributeCombinations.Add(this.CreateAttributeRelationship(isBerserkerBuffed, 1, Stats.BerserkerMinPhysDmgBonus, InputOperator.Minimum)); + result.AttributeCombinations.Add(this.CreateConditionalRelationship(berserkerHealthMultiplier, isBerserkerBuffed, berserkerHealthMultiplierDecrement)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, berserkerHealthMultiplier, aggregateType: AggregateType.Multiplicate)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerMinPhysDmgBonus, 1, Stats.BerserkerManaMultiplier, aggregateType: AggregateType.Multiplicate)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerMaxPhysDmgBonus, 1, Stats.BerserkerManaMultiplier, aggregateType: AggregateType.Multiplicate)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerWizardryMultiplier, 1, Stats.BerserkerManaMultiplier)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerCurseMultiplier, 1, Stats.BerserkerManaMultiplier)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerWizardryMultiplier, 1, Stats.BerserkerProficiencyMultiplier)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerMinWizDmgBonus, Stats.BerserkerWizardryMultiplier, statsMinWizAndCurseBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerMaxWizDmgBonus, Stats.BerserkerWizardryMultiplier, statsMaxWizAndCurseBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerMinCurseDmgBonus, Stats.BerserkerCurseMultiplier, statsMinWizAndCurseBaseDmg)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.BerserkerMaxCurseDmgBonus, Stats.BerserkerCurseMultiplier, statsMaxWizAndCurseBaseDmg)); + + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseStrength)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.BaseAgility)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.BaseVitality)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.BaseEnergy)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(39, Stats.MaximumHealth)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(6, Stats.MaximumMana)); - result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.SkillMultiplier)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f, Stats.WizardryAttackDamageIncrease)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f, Stats.CurseAttackDamageIncrease)); result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0.015f, statsMaxWizAndCurseBaseDmg)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, finalBerserkerManaMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, berserkerHealthMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.BerserkerManaMultiplier)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.BerserkerHealthMultiplierFactor)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.ExcellentWizTwoPercentInc)); + result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.AncientWizDmgIncrease)); this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster); + return result; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/GameConfigurationInitializerBase.cs b/src/Persistence/Initialization/GameConfigurationInitializerBase.cs index 72572b0b3..105ba544e 100644 --- a/src/Persistence/Initialization/GameConfigurationInitializerBase.cs +++ b/src/Persistence/Initialization/GameConfigurationInitializerBase.cs @@ -70,8 +70,8 @@ public override void Initialize() this.CreateItemOptionTypes(); this.GameConfiguration.ItemOptions.Add(this.CreateLuckOptionDefinition()); this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.DefenseBase, ItemOptionDefinitionNumbers.DefenseOption)); - this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.MaximumPhysBaseDmg, ItemOptionDefinitionNumbers.PhysicalAttack)); - this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.MaximumWizBaseDmg, ItemOptionDefinitionNumbers.WizardryAttack)); + this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.PhysicalBaseDmg, ItemOptionDefinitionNumbers.PhysicalAttack)); + this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.WizardryBaseDmg, ItemOptionDefinitionNumbers.WizardryAttack)); } protected ItemOptionDefinition CreateOptionDefinition(AttributeDefinition attributeDefinition, short number) diff --git a/src/Persistence/Initialization/InitializerBase.cs b/src/Persistence/Initialization/InitializerBase.cs index 2569d90c2..0b1ee8a1e 100644 --- a/src/Persistence/Initialization/InitializerBase.cs +++ b/src/Persistence/Initialization/InitializerBase.cs @@ -119,15 +119,17 @@ protected PowerUpDefinition CreatePowerUpDefinition(AttributeDefinition attribut /// The attribute definition. /// The value. /// Type of the aggregate. + /// The calculation stage. /// /// The created . /// - protected ItemBasePowerUpDefinition CreateItemBasePowerUpDefinition(AttributeDefinition attributeDefinition, float value, AggregateType aggregateType) + protected ItemBasePowerUpDefinition CreateItemBasePowerUpDefinition(AttributeDefinition attributeDefinition, float value, AggregateType aggregateType, byte stage = 0) { var powerUpDefinition = this.Context.CreateNew(); powerUpDefinition.TargetAttribute = attributeDefinition.GetPersistent(this.GameConfiguration); powerUpDefinition.BaseValue = value; powerUpDefinition.AggregateType = aggregateType; + powerUpDefinition.Stage = stage; return powerUpDefinition; } diff --git a/src/Persistence/Initialization/ItemOptionDefinitionNumbers.cs b/src/Persistence/Initialization/ItemOptionDefinitionNumbers.cs index 3bd24ad85..77b99d3a1 100644 --- a/src/Persistence/Initialization/ItemOptionDefinitionNumbers.cs +++ b/src/Persistence/Initialization/ItemOptionDefinitionNumbers.cs @@ -43,6 +43,7 @@ internal static class ItemOptionDefinitionNumbers /// Gets the excellent defense option number. /// public static short ExcellentDefense => 0x12; + /// /// Gets the excellent physical option number. /// @@ -147,6 +148,7 @@ internal static class ItemOptionDefinitionNumbers /// Gets the wing defense option number. /// public static short WingDefense => 0x60; + /// /// Gets the wing physical option number. /// @@ -161,6 +163,7 @@ internal static class ItemOptionDefinitionNumbers /// Gets the wing curse option number. /// public static short WingCurse => 0x63; + /// /// Gets the wing health recover option number. /// @@ -170,6 +173,7 @@ internal static class ItemOptionDefinitionNumbers /// Gets the wing2nd option number. /// public static short Wing2nd => 0x65; + /// /// Gets the cape option number. /// @@ -200,6 +204,26 @@ internal static class ItemOptionDefinitionNumbers /// public static short WizardRing => 0x73; + /// + /// Gets the christmas transformation ring option number. + /// + public static short ChristmasTransformationRing => 0x74; + + /// + /// Gets the robot knight transformation ring option number. + /// + public static short RobotKnightTransformationRing => 0x75; + + /// + /// Gets the mini robot transformation ring option number. + /// + public static short MiniRobotTransformationRing => 0x76; + + /// + /// Gets the great heavenly mage transformation ring option number. + /// + public static short GreatHeavenlyMageTransformationRing => 0x77; + /// /// Gets the dino option number. /// @@ -209,4 +233,9 @@ internal static class ItemOptionDefinitionNumbers /// Gets the fenrir option number. /// public static short Fenrir => 0x81; + + /// + /// Gets the dark horse option number. + /// + public static short Horse => 0x82; } \ No newline at end of file diff --git a/src/Persistence/Initialization/Items/ArmorInitializerBase.cs b/src/Persistence/Initialization/Items/ArmorInitializerBase.cs index faafd0e22..9ab1daadc 100644 --- a/src/Persistence/Initialization/Items/ArmorInitializerBase.cs +++ b/src/Persistence/Initialization/Items/ArmorInitializerBase.cs @@ -142,8 +142,7 @@ protected ItemDefinition CreateGloves(byte number, string name, byte dropLevel, var gloves = this.CreateArmor(number, 5, 2, 2, name, dropLevel, defense, durability, strengthRequirement, agilityRequirement, darkWizardClassLevel, darkKnightClassLevel, elfClassLevel); if (attackSpeed > 0) { - gloves.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.AttackSpeed, attackSpeed, AggregateType.AddRaw)); - gloves.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.MagicSpeed, attackSpeed, AggregateType.AddRaw)); + gloves.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.AttackSpeedAny, attackSpeed, AggregateType.AddRaw)); } return gloves; @@ -154,8 +153,7 @@ protected ItemDefinition CreateGloves(byte number, string name, byte dropLevel, var gloves = this.CreateArmor(number, 5, 2, 2, name, dropLevel, defense, durability, levelRequirement, strengthRequirement, agilityRequirement, 0, 0, 0, darkWizardClassLevel, darkKnightClassLevel, elfClassLevel, magicGladiatorClassLevel, darkLordClassLevel, summonerClassLevel, 0); if (attackSpeed > 0) { - gloves.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.AttackSpeed, attackSpeed, AggregateType.AddRaw)); - gloves.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.MagicSpeed, attackSpeed, AggregateType.AddRaw)); + gloves.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.AttackSpeedAny, attackSpeed, AggregateType.AddRaw)); } return gloves; diff --git a/src/Persistence/Initialization/Items/ExcellentOptions.cs b/src/Persistence/Initialization/Items/ExcellentOptions.cs index 61b9269fd..8b310822f 100644 --- a/src/Persistence/Initialization/Items/ExcellentOptions.cs +++ b/src/Persistence/Initialization/Items/ExcellentOptions.cs @@ -69,9 +69,9 @@ private void CreateCurseAttackOptions() definition.PossibleOptions.Add(this.CreateExcellentOption(1, Stats.ManaAfterMonsterKillMultiplier, 1f / 8f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentCurse)); definition.PossibleOptions.Add(this.CreateExcellentOption(2, Stats.HealthAfterMonsterKillMultiplier, 1f / 8f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentCurse)); - definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.AttackSpeed, 7, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentCurse)); - definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.MaximumCurseBaseDmg, 1.02f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentCurse)); - definition.PossibleOptions.Add(this.CreateRelatedExcellentOption(5, Stats.MaximumCurseBaseDmg, Stats.Level, 1f / 20f, ItemOptionDefinitionNumbers.ExcellentCurse)); + definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.AttackSpeedAny, 7, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentCurse)); + definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.ExcellentWizTwoPercentInc, 1.02f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentCurse)); + definition.PossibleOptions.Add(this.CreateRelatedExcellentOption(5, Stats.ExcellentWizBaseDmg, Stats.TotalLevel, 1f / 20f, ItemOptionDefinitionNumbers.ExcellentCurse)); definition.PossibleOptions.Add(this.CreateExcellentOption(6, Stats.ExcellentDamageChance, 0.1f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentCurse)); } @@ -87,9 +87,9 @@ private void CreateWizardryAttackOptions() definition.PossibleOptions.Add(this.CreateExcellentOption(1, Stats.ManaAfterMonsterKillMultiplier, 1f / 8f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentWizardry)); definition.PossibleOptions.Add(this.CreateExcellentOption(2, Stats.HealthAfterMonsterKillMultiplier, 1f / 8f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentWizardry)); - definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.AttackSpeed, 7, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentWizardry)); - definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.MaximumWizBaseDmg, 1.02f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentWizardry)); - definition.PossibleOptions.Add(this.CreateRelatedExcellentOption(5, Stats.MaximumWizBaseDmg, Stats.Level, 1f / 20f, ItemOptionDefinitionNumbers.ExcellentWizardry)); + definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.AttackSpeedAny, 7, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentWizardry)); + definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.ExcellentWizTwoPercentInc, 1.02f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentWizardry)); + definition.PossibleOptions.Add(this.CreateRelatedExcellentOption(5, Stats.ExcellentWizBaseDmg, Stats.Level, 1f / 20f, ItemOptionDefinitionNumbers.ExcellentWizardry)); definition.PossibleOptions.Add(this.CreateExcellentOption(6, Stats.ExcellentDamageChance, 0.1f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentWizardry)); } @@ -105,9 +105,9 @@ private void CreatePhysicalAttackOptions() definition.PossibleOptions.Add(this.CreateExcellentOption(1, Stats.ManaAfterMonsterKillMultiplier, 1f / 8f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentPhysical)); definition.PossibleOptions.Add(this.CreateExcellentOption(2, Stats.HealthAfterMonsterKillMultiplier, 1f / 8f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentPhysical)); - definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.AttackSpeed, 7, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentPhysical)); - definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.MaximumPhysBaseDmg, 1.02f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentPhysical)); - definition.PossibleOptions.Add(this.CreateRelatedExcellentOption(5, Stats.MaximumPhysBaseDmg, Stats.Level, 1f / 20f, ItemOptionDefinitionNumbers.ExcellentPhysical)); + definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.AttackSpeedAny, 7, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentPhysical)); + definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.ExcellentPhysTwoPercentInc, 1.02f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentPhysical)); + definition.PossibleOptions.Add(this.CreateRelatedExcellentOption(5, Stats.ExcellentPhysBaseDmg, Stats.Level, 1f / 20f, ItemOptionDefinitionNumbers.ExcellentPhysical)); definition.PossibleOptions.Add(this.CreateExcellentOption(6, Stats.ExcellentDamageChance, 0.1f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentPhysical)); } @@ -121,15 +121,20 @@ private void CreateDefenseOptions() definition.AddsRandomly = true; definition.MaximumOptionsPerItem = 2; - definition.PossibleOptions.Add(this.CreateExcellentOption(1, Stats.MoneyAmountRate, 1.4f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentDefense)); - definition.PossibleOptions.Add(this.CreateExcellentOption(2, Stats.DefenseRatePvm, 1.1f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentDefense)); - definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.DamageReflection, 0.04f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.ExcellentDefense)); - definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.DamageReceiveDecrement, 0.96f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentDefense)); - definition.PossibleOptions.Add(this.CreateExcellentOption(5, Stats.MaximumMana, 1.04f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentDefense)); - definition.PossibleOptions.Add(this.CreateExcellentOption(6, Stats.MaximumHealth, 1.04f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.ExcellentDefense)); + definition.PossibleOptions.Add(this.CreateExcellentOption(1, Stats.MoneyAmountRate, 1.4f, AggregateType.Multiplicate, 0, ItemOptionDefinitionNumbers.ExcellentDefense)); + definition.PossibleOptions.Add(this.CreateExcellentOption(2, Stats.DefenseRatePvm, 1.1f, AggregateType.Multiplicate, 1, ItemOptionDefinitionNumbers.ExcellentDefense)); + definition.PossibleOptions.Add(this.CreateExcellentOption(3, Stats.DamageReflection, 0.04f, AggregateType.AddRaw, 0, ItemOptionDefinitionNumbers.ExcellentDefense)); + definition.PossibleOptions.Add(this.CreateExcellentOption(4, Stats.ArmorDamageDecrease, 0.04f, AggregateType.AddRaw, 0, ItemOptionDefinitionNumbers.ExcellentDefense)); + definition.PossibleOptions.Add(this.CreateExcellentOption(5, Stats.MaximumMana, 1.04f, AggregateType.Multiplicate, 0, ItemOptionDefinitionNumbers.ExcellentDefense)); + definition.PossibleOptions.Add(this.CreateExcellentOption(6, Stats.MaximumHealth, 1.04f, AggregateType.Multiplicate, 0, ItemOptionDefinitionNumbers.ExcellentDefense)); } private IncreasableItemOption CreateExcellentOption(short number, AttributeDefinition attributeDefinition, float value, AggregateType aggregateType, short parentNumber) + { + return this.CreateExcellentOption(number, attributeDefinition, value, aggregateType, 0, parentNumber); + } + + private IncreasableItemOption CreateExcellentOption(short number, AttributeDefinition attributeDefinition, float value, AggregateType aggregateType, byte stage, short parentNumber) { var itemOption = this.Context.CreateNew(); itemOption.SetGuid(parentNumber, number); @@ -140,6 +145,7 @@ private IncreasableItemOption CreateExcellentOption(short number, AttributeDefin itemOption.PowerUpDefinition.Boost = this.Context.CreateNew(); itemOption.PowerUpDefinition.Boost.ConstantValue.Value = value; itemOption.PowerUpDefinition.Boost.ConstantValue.AggregateType = aggregateType; + itemOption.PowerUpDefinition.Boost.ConstantValue.Stage = stage; return itemOption; } diff --git a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddFireBlastForDarkLord.cs b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddFireBlastForDarkLord.cs new file mode 100644 index 000000000..2e0c43358 --- /dev/null +++ b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddFireBlastForDarkLord.cs @@ -0,0 +1,26 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.PlugIns.CharacterCreated; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; +using MUnique.OpenMU.Persistence.Initialization.Skills; +using MUnique.OpenMU.PlugIns; + +/// +/// Adds the Fire Blast skill (active in castle siege) to a created dark lord character. +/// +[Guid("49D2D6F2-4E70-4F4B-B7CE-0645EC2F094A")] +[PlugIn(nameof(AddFireBlastForDarkLord), "Adds the Fire Blast skill (active in castle siege) to a created dark lord character.")] +public class AddFireBlastForDarkLord : AddInitialSkillPlugInBase +{ + /// + /// Initializes a new instance of the class. + /// + public AddFireBlastForDarkLord() + : base((byte)CharacterClassNumber.DarkLord, (ushort)SkillNumber.FireBlast) + { + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddManaRaysForMagicGladiator.cs b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddManaRaysForMagicGladiator.cs new file mode 100644 index 000000000..94fa23afa --- /dev/null +++ b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddManaRaysForMagicGladiator.cs @@ -0,0 +1,26 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.PlugIns.CharacterCreated; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; +using MUnique.OpenMU.Persistence.Initialization.Skills; +using MUnique.OpenMU.PlugIns; + +/// +/// Adds the Mana Rays skill (active in castle siege) to a created magic gladiator character. +/// +[Guid("D83347DB-4D33-47E9-B898-5EDB2777B8A1")] +[PlugIn(nameof(AddManaRaysForMagicGladiator), "Adds the Mana Rays skill (active in castle siege) to a created magic gladiator character.")] +public class AddManaRaysForMagicGladiator : AddInitialSkillPlugInBase +{ + /// + /// Initializes a new instance of the class. + /// AddManaRaysForMagicGladiator.cs + public AddManaRaysForMagicGladiator() + : base((byte)CharacterClassNumber.MagicGladiator, (ushort)SkillNumber.ManaRays) + { + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddShortSwordForDarkLord.cs b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddShortSwordForDarkLord.cs new file mode 100644 index 000000000..99c7d16d3 --- /dev/null +++ b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddShortSwordForDarkLord.cs @@ -0,0 +1,26 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.PlugIns.CharacterCreated; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; +using MUnique.OpenMU.Persistence.Initialization.Items; +using MUnique.OpenMU.PlugIns; + +/// +/// Adds a short sword to a created dark lord character. +/// +[Guid("BAC120D0-D981-4EBB-8F5A-0EC19434AF16")] +[PlugIn(nameof(AddShortSwordForDarkLord), "Adds a short sword to a created dark lord character.")] +public class AddShortSwordForDarkLord : AddInitialItemPlugInBase +{ + /// + /// Initializes a new instance of the class. + /// + public AddShortSwordForDarkLord() + : base((byte)CharacterClassNumber.DarkLord, (byte)ItemGroups.Swords, 1, 0) + { + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddShortSwordForMagicGladiator.cs b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddShortSwordForMagicGladiator.cs new file mode 100644 index 000000000..e5e84f356 --- /dev/null +++ b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddShortSwordForMagicGladiator.cs @@ -0,0 +1,26 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.PlugIns.CharacterCreated; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; +using MUnique.OpenMU.Persistence.Initialization.Items; +using MUnique.OpenMU.PlugIns; + +/// +/// Adds a short sword to a created magic gladiator character. +/// +[Guid("3D2790E3-B757-46FD-8618-2441B7E9E2B3")] +[PlugIn(nameof(AddShortSwordForMagicGladiator), "Adds a short sword to a created magic gladiator character.")] +public class AddShortSwordForMagicGladiator : AddInitialItemPlugInBase +{ + /// + /// Initializes a new instance of the class. + /// + public AddShortSwordForMagicGladiator() + : base((byte)CharacterClassNumber.MagicGladiator, (byte)ItemGroups.Swords, 1, 0) + { + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallAxeForMagicGladiator.cs b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallAxeForMagicGladiator.cs deleted file mode 100644 index dbfa8800b..000000000 --- a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallAxeForMagicGladiator.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Licensed under the MIT License. See LICENSE file in the project root for full license information. -// - -namespace MUnique.OpenMU.Persistence.Initialization.PlugIns.CharacterCreated; - -using System.Runtime.InteropServices; -using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; -using MUnique.OpenMU.PlugIns; - -/// -/// Adds a small axe to a created magic gladiator character. -/// -[Guid("3D2790E3-B757-46FD-8618-2441B7E9E2B3")] -[PlugIn(nameof(AddSmallAxeForMagicGladiator), "Adds a small axe to a created magic gladiator character.")] -public class AddSmallAxeForMagicGladiator : AddInitialItemPlugInBase -{ - /// - /// Initializes a new instance of the class. - /// - public AddSmallAxeForMagicGladiator() - : base((byte)CharacterClassNumber.MagicGladiator, 1, 0, 0) - { - } -} \ No newline at end of file diff --git a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallShieldForDarkLord.cs b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallShieldForDarkLord.cs new file mode 100644 index 000000000..a13cdff60 --- /dev/null +++ b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallShieldForDarkLord.cs @@ -0,0 +1,26 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.PlugIns.CharacterCreated; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; +using MUnique.OpenMU.Persistence.Initialization.Items; +using MUnique.OpenMU.PlugIns; + +/// +/// Adds a small shield to a created dark lord character. +/// +[Guid("CD60BD4A-2BD5-4E36-95D0-EDB6B94CDDD8")] +[PlugIn(nameof(AddShortSwordForDarkLord), "Adds a small shield to a created dark lord character.")] +public class AddSmallShieldForDarkLord : AddInitialItemPlugInBase +{ + /// + /// Initializes a new instance of the class. + /// + public AddSmallShieldForDarkLord() + : base((byte)CharacterClassNumber.DarkLord, (byte)ItemGroups.Shields, 0, 1) + { + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallShieldForMagicGladiator.cs b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallShieldForMagicGladiator.cs new file mode 100644 index 000000000..6f43e5f2a --- /dev/null +++ b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSmallShieldForMagicGladiator.cs @@ -0,0 +1,26 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.PlugIns.CharacterCreated; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; +using MUnique.OpenMU.Persistence.Initialization.Items; +using MUnique.OpenMU.PlugIns; + +/// +/// Adds a small shield to a created magic gladiator character. +/// +[Guid("74FC7D85-7AA0-4437-88BA-CE008FD31745")] +[PlugIn(nameof(AddSmallShieldForMagicGladiator), "Adds a small shield to a created magic gladiator character.")] +public class AddSmallShieldForMagicGladiator : AddInitialItemPlugInBase +{ + /// + /// Initializes a new instance of the class. + /// + public AddSmallShieldForMagicGladiator() + : base((byte)CharacterClassNumber.MagicGladiator, (byte)ItemGroups.Shields, 0, 1) + { + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSpiralSlashForMagicGladiator.cs b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSpiralSlashForMagicGladiator.cs index 79e3bf6bb..42e064761 100644 --- a/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSpiralSlashForMagicGladiator.cs +++ b/src/Persistence/Initialization/PlugIns/CharacterCreated/AddSpiralSlashForMagicGladiator.cs @@ -10,10 +10,10 @@ namespace MUnique.OpenMU.Persistence.Initialization.PlugIns.CharacterCreated; using MUnique.OpenMU.PlugIns; /// -/// Adds the Spiral slash skill (active in castle siege) to a created magic gladiator character. +/// Adds the Spiral Slash skill (active in castle siege) to a created magic gladiator character. /// [Guid("83B0D163-7E97-40FC-851A-D5500B4BB33E")] -[PlugIn(nameof(AddEnergyBallForDarkWizard), "Adds the Spiral slash skill (active in castle siege) to a created magic gladiator character.")] +[PlugIn(nameof(AddSpiralSlashForMagicGladiator), "Adds the Spiral Slash skill (active in castle siege) to a created magic gladiator character.")] public class AddSpiralSlashForMagicGladiator : AddInitialSkillPlugInBase { /// diff --git a/src/Persistence/Initialization/Skills/AlcoholEffectInitializer.cs b/src/Persistence/Initialization/Skills/AlcoholEffectInitializer.cs index f8b1a91fe..cfe16ccf0 100644 --- a/src/Persistence/Initialization/Skills/AlcoholEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/AlcoholEffectInitializer.cs @@ -39,14 +39,8 @@ public override void Initialize() var attackSpeedPowerUp = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(attackSpeedPowerUp); - attackSpeedPowerUp.TargetAttribute = Stats.AttackSpeed.GetPersistent(this.GameConfiguration); + attackSpeedPowerUp.TargetAttribute = Stats.AttackSpeedAny.GetPersistent(this.GameConfiguration); attackSpeedPowerUp.Boost = this.Context.CreateNew(); attackSpeedPowerUp.Boost.ConstantValue.Value = 20f; - - var magicSpeedPowerUp = this.Context.CreateNew(); - magicEffect.PowerUpDefinitions.Add(magicSpeedPowerUp); - magicSpeedPowerUp.TargetAttribute = Stats.MagicSpeed.GetPersistent(this.GameConfiguration); - magicSpeedPowerUp.Boost = this.Context.CreateNew(); - magicSpeedPowerUp.Boost.ConstantValue.Value = 20f; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/Skills/BerserkerEffectInitializer.cs b/src/Persistence/Initialization/Skills/BerserkerEffectInitializer.cs new file mode 100644 index 000000000..078af1aaf --- /dev/null +++ b/src/Persistence/Initialization/Skills/BerserkerEffectInitializer.cs @@ -0,0 +1,103 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.Skills; + +using MUnique.OpenMU.AttributeSystem; +using MUnique.OpenMU.DataModel.Attributes; +using MUnique.OpenMU.DataModel.Configuration; +using MUnique.OpenMU.GameLogic.Attributes; + +/// +/// Initializer for the berserker buff effect. +/// +public class BerserkerEffectInitializer : InitializerBase +{ + /// + /// Initializes a new instance of the class. + /// + /// The context. + /// The game configuration. + public BerserkerEffectInitializer(IContext context, GameConfiguration gameConfiguration) + : base(context, gameConfiguration) + { + } + + /// + public override void Initialize() + { + var magicEffect = this.Context.CreateNew(); + this.GameConfiguration.MagicEffects.Add(magicEffect); + magicEffect.Number = (short)MagicEffectNumber.Berserker; + magicEffect.Name = "Berserker Buff Skill Effect"; + magicEffect.InformObservers = true; + magicEffect.SendDuration = false; + magicEffect.StopByDeath = true; + magicEffect.Duration = this.Context.CreateNew(); + magicEffect.Duration.ConstantValue.Value = 30; // 30 Seconds + + var durationPerEnergy = this.Context.CreateNew(); + durationPerEnergy.InputAttribute = Stats.BaseEnergy.GetPersistent(this.GameConfiguration); // BaseEnergy and not TotalEnergy + durationPerEnergy.InputOperator = InputOperator.Multiply; + durationPerEnergy.InputOperand = 1f / 20f; // 20 energy adds 1 second duration + magicEffect.Duration.RelatedValues.Add(durationPerEnergy); + + // Mana (and damage) multiplier (buff) + var manaPowerUpDefinition = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(manaPowerUpDefinition); + manaPowerUpDefinition.TargetAttribute = Stats.BerserkerManaMultiplier.GetPersistent(this.GameConfiguration); + manaPowerUpDefinition.Boost = this.Context.CreateNew(); + + var manaMultiplier = this.Context.CreateNew(); + manaMultiplier.InputAttribute = Stats.BaseEnergy.GetPersistent(this.GameConfiguration); // BaseEnergy and not TotalEnergy + manaMultiplier.InputOperator = InputOperator.Multiply; + manaMultiplier.InputOperand = 1f / 3000f; + manaPowerUpDefinition.Boost.RelatedValues.Add(manaMultiplier); + + // Health multiplier factor (debuff) + var healthPowerUpDefinition = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(healthPowerUpDefinition); + healthPowerUpDefinition.TargetAttribute = Stats.BerserkerHealthMultiplierFactor.GetPersistent(this.GameConfiguration); + healthPowerUpDefinition.Boost = this.Context.CreateNew(); + healthPowerUpDefinition.Boost.ConstantValue.Value = -0.4f; + + var healthMultiplier = this.Context.CreateNew(); + healthMultiplier.InputAttribute = Stats.BaseEnergy.GetPersistent(this.GameConfiguration); // BaseEnergy and not TotalEnergy + healthMultiplier.InputOperator = InputOperator.Multiply; + healthMultiplier.InputOperand = 1f / 6000f; + healthPowerUpDefinition.Boost.RelatedValues.Add(healthMultiplier); + + // Min physical damage bonus (later gets multiplied by the mana multiplier) + var minPhysPowerUpDefinition = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(minPhysPowerUpDefinition); + minPhysPowerUpDefinition.TargetAttribute = Stats.BerserkerMinPhysDmgBonus.GetPersistent(this.GameConfiguration); + minPhysPowerUpDefinition.Boost = this.Context.CreateNew(); + minPhysPowerUpDefinition.Boost.ConstantValue.Value = 140f; + + var minDmgPerStrengthAndAgility = this.Context.CreateNew(); + minDmgPerStrengthAndAgility.InputAttribute = Stats.TotalStrengthAndAgility.GetPersistent(this.GameConfiguration); + minDmgPerStrengthAndAgility.InputOperator = InputOperator.Multiply; + minDmgPerStrengthAndAgility.InputOperand = 1.0f / 50; + minPhysPowerUpDefinition.Boost.RelatedValues.Add(minDmgPerStrengthAndAgility); + + // Max physical damage bonus (later gets multiplied by the mana multiplier) + var maxPhysPowerUpDefinition = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(maxPhysPowerUpDefinition); + maxPhysPowerUpDefinition.TargetAttribute = Stats.BerserkerMaxPhysDmgBonus.GetPersistent(this.GameConfiguration); + maxPhysPowerUpDefinition.Boost = this.Context.CreateNew(); + maxPhysPowerUpDefinition.Boost.ConstantValue.Value = 160f; + + var maxDmgPerStrengthAndAgility = this.Context.CreateNew(); + maxDmgPerStrengthAndAgility.InputAttribute = Stats.TotalStrengthAndAgility.GetPersistent(this.GameConfiguration); + maxDmgPerStrengthAndAgility.InputOperator = InputOperator.Multiply; + maxDmgPerStrengthAndAgility.InputOperand = 1.0f / 30; + maxPhysPowerUpDefinition.Boost.RelatedValues.Add(maxDmgPerStrengthAndAgility); + + // Berserker Proficiency master level multiplier placeholder + var masterLevelDmgMultiplier = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(masterLevelDmgMultiplier); + masterLevelDmgMultiplier.TargetAttribute = Stats.BerserkerProficiencyMultiplier.GetPersistent(this.GameConfiguration); + masterLevelDmgMultiplier.Boost = this.Context.CreateNew(); + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/Skills/DefenseEffectInitializer.cs b/src/Persistence/Initialization/Skills/DefenseEffectInitializer.cs index b4db80656..0006fd1cd 100644 --- a/src/Persistence/Initialization/Skills/DefenseEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/DefenseEffectInitializer.cs @@ -35,15 +35,15 @@ public override void Initialize() magicEffect.SendDuration = false; magicEffect.StopByDeath = true; magicEffect.Duration = this.Context.CreateNew(); - magicEffect.Duration.ConstantValue!.Value = 1; // 1 Second + magicEffect.Duration.ConstantValue!.Value = 4; // 4 Seconds var powerUpDefinition = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(powerUpDefinition); - powerUpDefinition.TargetAttribute = Stats.DamageReceiveDecrement.GetPersistent(this.GameConfiguration); + powerUpDefinition.TargetAttribute = Stats.ShieldSkillReceiveDecrement.GetPersistent(this.GameConfiguration); // Always a 50 % damage reduction powerUpDefinition.Boost = this.Context.CreateNew(); powerUpDefinition.Boost.ConstantValue.Value = 0.50f; - powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.AddRaw; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/Skills/DefenseReductionEffectInitializer.cs b/src/Persistence/Initialization/Skills/DefenseReductionEffectInitializer.cs index 262537f8e..dab088e3e 100644 --- a/src/Persistence/Initialization/Skills/DefenseReductionEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/DefenseReductionEffectInitializer.cs @@ -43,5 +43,6 @@ public override void Initialize() reduceDefenseEffect.Boost = this.Context.CreateNew(); reduceDefenseEffect.Boost.ConstantValue.Value = 0.9f; reduceDefenseEffect.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + reduceDefenseEffect.Boost.ConstantValue.Stage = 3; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/Skills/GreaterDamageEffectInitializer.cs b/src/Persistence/Initialization/Skills/GreaterDamageEffectInitializer.cs index 7640edd79..f864cfc28 100644 --- a/src/Persistence/Initialization/Skills/GreaterDamageEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/GreaterDamageEffectInitializer.cs @@ -38,7 +38,7 @@ public override void Initialize() magicEffect.Duration.ConstantValue.Value = 60; // 60 Seconds var powerUpDefinition = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(powerUpDefinition); - powerUpDefinition.TargetAttribute = Stats.BaseDamageBonus.GetPersistent(this.GameConfiguration); + powerUpDefinition.TargetAttribute = Stats.GreaterDamageBonus.GetPersistent(this.GameConfiguration); // The buff gives 3 + (energy / 7) damage powerUpDefinition.Boost = this.Context.CreateNew(); diff --git a/src/Persistence/Initialization/Skills/GreaterDefenseEffectInitializer.cs b/src/Persistence/Initialization/Skills/GreaterDefenseEffectInitializer.cs index bc0cae430..727f0ef31 100644 --- a/src/Persistence/Initialization/Skills/GreaterDefenseEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/GreaterDefenseEffectInitializer.cs @@ -42,10 +42,11 @@ public override void Initialize() powerUpDefinition.TargetAttribute = Stats.DefenseBase.GetPersistent(this.GameConfiguration); - // The buff gives 2 + (energy / 8) defense + // The buff gives 1 + (energy / 8) defense powerUpDefinition.Boost = this.Context.CreateNew(); - powerUpDefinition.Boost.ConstantValue.Value = 2f; + powerUpDefinition.Boost.ConstantValue.Value = 1f; powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.AddRaw; + powerUpDefinition.Boost.ConstantValue.Stage = 3; var boostPerEnergy = this.Context.CreateNew(); boostPerEnergy.InputAttribute = Stats.TotalEnergy.GetPersistent(this.GameConfiguration); diff --git a/src/Persistence/Initialization/Skills/InfiniteArrowEffectInitializer.cs b/src/Persistence/Initialization/Skills/InfiniteArrowEffectInitializer.cs index 838a62f3c..4ad02bb59 100644 --- a/src/Persistence/Initialization/Skills/InfiniteArrowEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/InfiniteArrowEffectInitializer.cs @@ -35,7 +35,7 @@ public override void Initialize() magicEffect.SendDuration = true; magicEffect.StopByDeath = true; magicEffect.Duration = this.Context.CreateNew(); - magicEffect.Duration.ConstantValue.Value = (float)TimeSpan.FromHours(8).TotalSeconds; + magicEffect.Duration.ConstantValue.Value = 600; // Multiply usage rate with 0, so no arrows are consumed anymore. var reduceAmmonitionUsage = this.Context.CreateNew(); @@ -45,27 +45,18 @@ public override void Initialize() reduceAmmonitionUsage.Boost.ConstantValue.Value = 0f; reduceAmmonitionUsage.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + // Mana loss is 5 plus: 0 (arrows/bolts + 0); 2 (arrows/bolts +1); 5 (arrows/bolts +2 or higher). + // Because the ammo item can be changed during the magic effect duration, the extra loss is added later. var manaLossAfterHit = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(manaLossAfterHit); manaLossAfterHit.TargetAttribute = Stats.ManaLossAfterHit.GetPersistent(this.GameConfiguration); manaLossAfterHit.Boost = this.Context.CreateNew(); - manaLossAfterHit.Boost.ConstantValue.Value = 3f; + manaLossAfterHit.Boost.ConstantValue.Value = 5f; - var damageBonusPerEnergy = this.Context.CreateNew(); - magicEffect.PowerUpDefinitions.Add(damageBonusPerEnergy); - damageBonusPerEnergy.TargetAttribute = Stats.BaseDamageBonus.GetPersistent(this.GameConfiguration); - damageBonusPerEnergy.Boost = this.Context.CreateNew(); - var oneDamagePer7Energy = this.Context.CreateNew(); - damageBonusPerEnergy.Boost.RelatedValues.Add(oneDamagePer7Energy); - oneDamagePer7Energy.InputAttribute = Stats.TotalEnergy.GetPersistent(this.GameConfiguration); - oneDamagePer7Energy.InputOperand = 1f / 7f; - oneDamagePer7Energy.InputOperator = InputOperator.Add; - oneDamagePer7Energy.TargetAttribute = Stats.BaseDamageBonus.GetPersistent(this.GameConfiguration); - - // The next is more like a placeholder in case it's used by the master skill which adds a percentage bonus. + // Placeholder for the Infinity Arrow Strengthener master skill var damageIncreaseByMasterLevel = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(damageIncreaseByMasterLevel); - damageIncreaseByMasterLevel.TargetAttribute = Stats.AttackDamageIncrease.GetPersistent(this.GameConfiguration); + damageIncreaseByMasterLevel.TargetAttribute = Stats.InfinityArrowStrMultiplier.GetPersistent(this.GameConfiguration); damageIncreaseByMasterLevel.Boost = this.Context.CreateNew(); } } \ No newline at end of file diff --git a/src/Persistence/Initialization/Skills/KillingBlowEffectInitializer.cs b/src/Persistence/Initialization/Skills/KillingBlowEffectInitializer.cs new file mode 100644 index 000000000..792b71eaf --- /dev/null +++ b/src/Persistence/Initialization/Skills/KillingBlowEffectInitializer.cs @@ -0,0 +1,48 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.Skills; + +using MUnique.OpenMU.AttributeSystem; +using MUnique.OpenMU.DataModel.Attributes; +using MUnique.OpenMU.DataModel.Configuration; +using MUnique.OpenMU.GameLogic.Attributes; + +/// +/// Initializer for the killing blow skill effect. +/// +public class KillingBlowEffectInitializer : InitializerBase +{ + /// + /// Initializes a new instance of the class. + /// + /// The context. + /// The game configuration. + public KillingBlowEffectInitializer(IContext context, GameConfiguration gameConfiguration) + : base(context, gameConfiguration) + { + } + + /// + public override void Initialize() + { + var magicEffect = this.Context.CreateNew(); + this.GameConfiguration.MagicEffects.Add(magicEffect); + magicEffect.Number = (short)MagicEffectNumber.Weakness; + magicEffect.Name = "Killing Blow Skill Effect"; + magicEffect.InformObservers = true; + magicEffect.SendDuration = false; + magicEffect.StopByDeath = true; + magicEffect.Duration = this.Context.CreateNew(); + magicEffect.Duration.ConstantValue.Value = 10; // 10 seconds + + // Target's damage decreases by 5% + var decDmgPowerUpDefinition = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(decDmgPowerUpDefinition); + decDmgPowerUpDefinition.TargetAttribute = Stats.WeaknessPhysDmgDecrement.GetPersistent(this.GameConfiguration); + decDmgPowerUpDefinition.Boost = this.Context.CreateNew(); + decDmgPowerUpDefinition.Boost.ConstantValue.Value = 0.05f; + decDmgPowerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.AddRaw; + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/Skills/MagicEffectNumber.cs b/src/Persistence/Initialization/Skills/MagicEffectNumber.cs index 1bc738568..1b63f4f85 100644 --- a/src/Persistence/Initialization/Skills/MagicEffectNumber.cs +++ b/src/Persistence/Initialization/Skills/MagicEffectNumber.cs @@ -235,6 +235,11 @@ internal enum MagicEffectNumber : short /// Blind = 0x49, + /// + /// The weakness effect, which decreases inflicted damage. + /// + Weakness = 0x4C, + /// /// The cherry blossom wine effect (+ 700 Mana). /// @@ -250,6 +255,11 @@ internal enum MagicEffectNumber : short /// CherryBlossomFlowerPetal = 0x50, + /// + /// The berserker buff effect. + /// + Berserker = 0x51, + /// /// The wiz enhance effect. /// diff --git a/src/Persistence/Initialization/Skills/SoulBarrierEffectInitializer.cs b/src/Persistence/Initialization/Skills/SoulBarrierEffectInitializer.cs index 4778e3560..e67363b4b 100644 --- a/src/Persistence/Initialization/Skills/SoulBarrierEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/SoulBarrierEffectInitializer.cs @@ -34,34 +34,44 @@ public override void Initialize() magicEffect.InformObservers = true; magicEffect.SendDuration = false; magicEffect.StopByDeath = true; - var powerUpDefinition = this.Context.CreateNew(); - magicEffect.PowerUpDefinitions.Add(powerUpDefinition); - powerUpDefinition.TargetAttribute = Stats.DamageReceiveDecrement.GetPersistent(this.GameConfiguration); magicEffect.Duration = this.Context.CreateNew(); magicEffect.Duration.ConstantValue.Value = 60; + var durationPerEnergy = this.Context.CreateNew(); durationPerEnergy.InputAttribute = Stats.TotalEnergy.GetPersistent(this.GameConfiguration); durationPerEnergy.InputOperator = InputOperator.Multiply; - durationPerEnergy.InputOperand = 1f / 5f; // 5 energy adds 1 second duration + durationPerEnergy.InputOperand = 1f / 40f; // 40 energy adds 1 second duration magicEffect.Duration.RelatedValues.Add(durationPerEnergy); - // one percent per 200 energy + // Soul barrier dmg decrease % = 10 + (Agility/50) + (Energy/200) + var damageDecrement = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(damageDecrement); + damageDecrement.TargetAttribute = Stats.SoulBarrierReceiveDecrement.GetPersistent(this.GameConfiguration); + damageDecrement.Boost = this.Context.CreateNew(); + damageDecrement.Boost.ConstantValue.Value = 0.9f; + var boostPerEnergy = this.Context.CreateNew(); boostPerEnergy.InputAttribute = Stats.TotalEnergy.GetPersistent(this.GameConfiguration); - boostPerEnergy.InputOperator = InputOperator.ExponentiateByAttribute; - boostPerEnergy.InputOperand = 1 - (0.01f / 200f); + boostPerEnergy.InputOperator = InputOperator.Multiply; + boostPerEnergy.InputOperand = -1f / 20000f; // one percent per 200 energy + damageDecrement.Boost.RelatedValues.Add(boostPerEnergy); - // one percent per 50 agility var boostPerAgility = this.Context.CreateNew(); boostPerAgility.InputAttribute = Stats.TotalAgility.GetPersistent(this.GameConfiguration); - boostPerAgility.InputOperator = InputOperator.ExponentiateByAttribute; - boostPerAgility.InputOperand = 1 - (0.01f / 50f); + boostPerAgility.InputOperator = InputOperator.Multiply; + boostPerAgility.InputOperand = -1f / 5000f; // one percent per 50 agility + damageDecrement.Boost.RelatedValues.Add(boostPerAgility); + + // Mana toll = 2% + 0.1% per master skill level (added in skill action plugin) + var manaTollPerHit = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(manaTollPerHit); + manaTollPerHit.TargetAttribute = Stats.SoulBarrierManaTollPerHit.GetPersistent(this.GameConfiguration); + manaTollPerHit.Boost = this.Context.CreateNew(); - // Soul barrier % = 10 + (Agility/50) + (Energy/200) - powerUpDefinition.Boost = this.Context.CreateNew(); - powerUpDefinition.Boost.ConstantValue.Value = 0.9f; - powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; - powerUpDefinition.Boost.RelatedValues.Add(boostPerEnergy); - powerUpDefinition.Boost.RelatedValues.Add(boostPerAgility); + var manaToll = this.Context.CreateNew(); + manaToll.InputAttribute = Stats.MaximumMana.GetPersistent(this.GameConfiguration); + manaToll.InputOperator = InputOperator.Multiply; + manaToll.InputOperand = 0.02f; // two percent per total mana + manaTollPerHit.Boost.RelatedValues.Add(manaToll); } } \ No newline at end of file diff --git a/src/Persistence/Initialization/Skills/SoulPotionEffectInitializer.cs b/src/Persistence/Initialization/Skills/SoulPotionEffectInitializer.cs index 050647f7c..6dcd037ef 100644 --- a/src/Persistence/Initialization/Skills/SoulPotionEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/SoulPotionEffectInitializer.cs @@ -39,16 +39,10 @@ public override void Initialize() var attackSpeedPowerUp = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(attackSpeedPowerUp); - attackSpeedPowerUp.TargetAttribute = Stats.AttackSpeed.GetPersistent(this.GameConfiguration); + attackSpeedPowerUp.TargetAttribute = Stats.AttackSpeedAny.GetPersistent(this.GameConfiguration); attackSpeedPowerUp.Boost = this.Context.CreateNew(); attackSpeedPowerUp.Boost.ConstantValue.Value = 20f; - var magicSpeedPowerUp = this.Context.CreateNew(); - magicEffect.PowerUpDefinitions.Add(magicSpeedPowerUp); - magicSpeedPowerUp.TargetAttribute = Stats.MagicSpeed.GetPersistent(this.GameConfiguration); - magicSpeedPowerUp.Boost = this.Context.CreateNew(); - magicSpeedPowerUp.Boost.ConstantValue.Value = 20f; - var abilityRecoveryIncrease = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(abilityRecoveryIncrease); abilityRecoveryIncrease.TargetAttribute = Stats.AbilityRecoveryAbsolute.GetPersistent(this.GameConfiguration); diff --git a/src/Persistence/Initialization/Version075/Items/Pets.cs b/src/Persistence/Initialization/Version075/Items/Pets.cs index e814c4775..f013e45f9 100644 --- a/src/Persistence/Initialization/Version075/Items/Pets.cs +++ b/src/Persistence/Initialization/Version075/Items/Pets.cs @@ -29,8 +29,8 @@ public Pets(IContext context, GameConfiguration gameConfiguration) /// public override void Initialize() { - this.CreatePet(0, "Guardian Angel", 23, (Stats.DamageReceiveDecrement, 0.8f, AggregateType.Multiplicate), (Stats.MaximumHealth, 50f, AggregateType.AddRaw)); - this.CreatePet(1, "Imp", 28, (Stats.AttackDamageIncrease, 1.3f, AggregateType.Multiplicate)); + this.CreatePet(0, "Guardian Angel", 23, (Stats.GuardianReceiveDecrement, 0.2f, AggregateType.Multiplicate), (Stats.MaximumHealth, 50f, AggregateType.AddRaw)); + this.CreatePet(1, "Imp", 28, (Stats.ImpAttackDamageIncrease, 0.3f, AggregateType.AddRaw)); this.CreatePet(2, "Horn of Uniria", 25); } diff --git a/src/Persistence/Initialization/Version075/Items/Weapons.cs b/src/Persistence/Initialization/Version075/Items/Weapons.cs index 3c07ae359..5f90a93cf 100644 --- a/src/Persistence/Initialization/Version075/Items/Weapons.cs +++ b/src/Persistence/Initialization/Version075/Items/Weapons.cs @@ -29,11 +29,16 @@ internal class Weapons : InitializerBase private static readonly float[] StaffRiseIncreaseByLevelEven = { 0, 3, 7, 10, 14, 17, 21, 24, 28, 31, 35, 40, 45, 50, 56, 63 }; // Staff with even magic power private static readonly float[] StaffRiseIncreaseByLevelOdd = { 0, 4, 7, 11, 14, 18, 21, 25, 28, 32, 36, 40, 45, 51, 57, 63 }; // Staff with odd magic power + private static readonly float[] AmmunitionDamageIncreaseByLevel = { 0, 0.03f, 0.05f, 0.1f }; // Bolts/Arrows + private ItemLevelBonusTable? _weaponDamageIncreaseTable; + private ItemLevelBonusTable? _staffDamageIncreaseTable; private ItemLevelBonusTable? _staffRiseTableEven; private ItemLevelBonusTable? _staffRiseTableOdd; + private ItemLevelBonusTable? _ammunitionDamageIncreaseTable; + /// /// Initializes a new instance of the class. /// @@ -62,7 +67,7 @@ protected ItemOptionDefinition PhysicalDamageOption { get { - return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumPhysBaseDmg)); + return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.PhysicalBaseDmg)); } } @@ -73,7 +78,7 @@ protected ItemOptionDefinition WizardryDamageOption { get { - return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumWizBaseDmg)); + return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.WizardryBaseDmg)); } } @@ -83,8 +88,10 @@ protected ItemOptionDefinition WizardryDamageOption public override void Initialize() { this._weaponDamageIncreaseTable = this.CreateItemBonusTable(DamageIncreaseByLevel, "Damage Increase (Weapons)", "The damage increase by weapon level. It increases by 3 per level, and 1 more after level 10."); + this._staffDamageIncreaseTable = this.CreateItemBonusTable([.. DamageIncreaseByLevel.Select(dmg => dmg /= 2.0f)], "Damage Increase (Staffs)", "The damage increase by staff level. It's half of the physical weapons."); this._staffRiseTableEven = this.CreateItemBonusTable(StaffRiseIncreaseByLevelEven, "Staff Rise (even)", "The staff rise bonus per item level for even magic power staves."); this._staffRiseTableOdd = this.CreateItemBonusTable(StaffRiseIncreaseByLevelOdd, "Staff Rise (odd)", "The staff rise bonus per item level for odd magic power staves."); + this._ammunitionDamageIncreaseTable = this.CreateItemBonusTable(AmmunitionDamageIncreaseByLevel, "Damage Increase % (Bolts/Arrows)", "The damage increase % by ammunition item level."); this.CreateWeapon(0, 0, 0, 0, 1, 2, true, "Kris", 6, 6, 11, 50, 20, 0, 0, 40, 40, 0, 0, 1, 1, 1); this.CreateWeapon(0, 1, 0, 0, 1, 3, true, "Short Sword", 3, 3, 7, 20, 22, 0, 0, 60, 0, 0, 0, 1, 1, 1); @@ -200,6 +207,10 @@ protected void CreateAmmunition(byte @group, byte number, byte slot, byte width, var qualifiedCharacterClasses = this.GameConfiguration.DetermineCharacterClasses(wizardClass == 1, knightClass == 1, elfClass == 1); qualifiedCharacterClasses.ToList().ForEach(item.QualifiedCharacters.Add); + var damagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.AmmunitionDamageBonus, 0f, AggregateType.AddRaw); + damagePowerUp.BonusPerLevelTable = this._ammunitionDamageIncreaseTable; + item.BasePowerUpAttributes.Add(damagePowerUp); + item.IsAmmunition = true; } @@ -266,15 +277,18 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber var qualifiedCharacterClasses = this.GameConfiguration.DetermineCharacterClasses(wizardClass == 1, knightClass == 1, elfClass == 1); qualifiedCharacterClasses.ToList().ForEach(item.QualifiedCharacters.Add); - var minDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MinimumPhysBaseDmgByWeapon, minimumDamage, AggregateType.AddRaw); - minDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; + var dmgDivider = group == (int)ItemGroups.Staff ? 2.0f : 1.0f; + var bonusPerLevelTable = group == (int)ItemGroups.Staff ? this._staffDamageIncreaseTable : this._weaponDamageIncreaseTable; + + var minDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MinimumPhysBaseDmgByWeapon, minimumDamage / dmgDivider, AggregateType.AddRaw); + minDamagePowerUp.BonusPerLevelTable = bonusPerLevelTable; item.BasePowerUpAttributes.Add(minDamagePowerUp); - var maxDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MaximumPhysBaseDmgByWeapon, maximumDamage, AggregateType.AddRaw); - maxDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; + var maxDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MaximumPhysBaseDmgByWeapon, maximumDamage / dmgDivider, AggregateType.AddRaw); + maxDamagePowerUp.BonusPerLevelTable = bonusPerLevelTable; item.BasePowerUpAttributes.Add(maxDamagePowerUp); - var speedPowerUp = this.CreateItemBasePowerUpDefinition(Stats.AttackSpeed, attackSpeed, AggregateType.AddRaw); + var speedPowerUp = this.CreateItemBasePowerUpDefinition(Stats.AttackSpeedByWeapon, attackSpeed, AggregateType.AddRaw); item.BasePowerUpAttributes.Add(speedPowerUp); this.CreateItemRequirementIfNeeded(item, Stats.Level, levelRequirement); @@ -298,21 +312,14 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.BasePowerUpAttributes.Add(staffRisePowerUp); } - item.IsAmmunition = isAmmunition; - if (!item.IsAmmunition) + if (group == (int)ItemGroups.Bows) { - var ammunitionConsumption = this.Context.CreateNew(); - ammunitionConsumption.TargetAttribute = Stats.AmmunitionConsumptionRate.GetPersistent(this.GameConfiguration); - ammunitionConsumption.BaseValue = 1.0f; - item.BasePowerUpAttributes.Add(ammunitionConsumption); + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.AmmunitionConsumptionRate, 1, AggregateType.AddRaw)); } - if (group != (int)ItemGroups.Bows && width == 2) + if (group != (int)ItemGroups.Bows && group != (int)ItemGroups.Staff && width == 2) { - var isTwoHandedWeapon = this.Context.CreateNew(); - isTwoHandedWeapon.TargetAttribute = Stats.IsTwoHandedWeaponEquipped.GetPersistent(this.GameConfiguration); - isTwoHandedWeapon.BaseValue = 1.0f; - item.BasePowerUpAttributes.Add(isTwoHandedWeapon); + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.IsTwoHandedWeaponEquipped, 1, AggregateType.AddRaw)); } } } \ No newline at end of file diff --git a/src/Persistence/Initialization/Version095d/CharacterClassInitialization.cs b/src/Persistence/Initialization/Version095d/CharacterClassInitialization.cs index 7facdebf5..a17818828 100644 --- a/src/Persistence/Initialization/Version095d/CharacterClassInitialization.cs +++ b/src/Persistence/Initialization/Version095d/CharacterClassInitialization.cs @@ -8,7 +8,7 @@ namespace MUnique.OpenMU.Persistence.Initialization.Version095d; using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; /// -/// Initialization of character classes data for Version 0.75. +/// Initialization of character classes data for Version 0.95d. /// internal class CharacterClassInitialization : Initialization.CharacterClasses.CharacterClassInitialization { diff --git a/src/Persistence/Initialization/Version095d/Items/Pets.cs b/src/Persistence/Initialization/Version095d/Items/Pets.cs index fd7e7143c..938b0ee0d 100644 --- a/src/Persistence/Initialization/Version095d/Items/Pets.cs +++ b/src/Persistence/Initialization/Version095d/Items/Pets.cs @@ -30,11 +30,11 @@ public Pets(IContext context, GameConfiguration gameConfiguration) /// public override void Initialize() { - this.CreatePet(0, 0, "Guardian Angel", 23, true, (Stats.DamageReceiveDecrement, 0.8f, AggregateType.Multiplicate), (Stats.MaximumHealth, 50f, AggregateType.AddRaw)); - this.CreatePet(1, 0, "Imp", 28, true, (Stats.AttackDamageIncrease, 1.3f, AggregateType.Multiplicate)); + this.CreatePet(0, 0, "Guardian Angel", 23, true, (Stats.GuardianReceiveDecrement, 0.2f, AggregateType.AddRaw), (Stats.MaximumHealth, 50f, AggregateType.AddRaw)); + this.CreatePet(1, 0, "Imp", 28, true, (Stats.ImpAttackDamageIncrease, 0.3f, AggregateType.AddRaw)); this.CreatePet(2, 0, "Horn of Uniria", 25, true); - var dinorant = this.CreatePet(3, SkillNumber.FireBreath, "Horn of Dinorant", 110, false, (Stats.DamageReceiveDecrement, 0.9f, AggregateType.Multiplicate), (Stats.AttackDamageIncrease, 1.15f, AggregateType.Multiplicate), (Stats.CanFly, 1.0f, AggregateType.AddRaw)); + var dinorant = this.CreatePet(3, SkillNumber.FireBreath, "Horn of Dinorant", 110, false, (Stats.IsDinorantEquipped, 1, AggregateType.AddRaw), (Stats.DamageReceiveDecrement, 0.9f, AggregateType.Multiplicate), (Stats.AttackDamageIncrease, 1.15f, AggregateType.Multiplicate)); this.AddDinorantOptions(dinorant); } @@ -88,7 +88,7 @@ private void AddDinorantOptions(ItemDefinition dinorant) dinoOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.Option, 4, Stats.DamageReceiveDecrement, 0.95f, AggregateType.Multiplicate)); dinoOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.Option, 4, Stats.MaximumAbility, 50f, AggregateType.AddFinal)); - dinoOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.Option, 4, Stats.AttackSpeed, 5f, AggregateType.AddFinal)); + dinoOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.Option, 4, Stats.AttackSpeedAny, 5f, AggregateType.AddFinal)); dinorant.PossibleItemOptions.Add(dinoOptionDefinition); } diff --git a/src/Persistence/Initialization/Version095d/Items/Weapons.cs b/src/Persistence/Initialization/Version095d/Items/Weapons.cs index 6d79c1376..000cce7b3 100644 --- a/src/Persistence/Initialization/Version095d/Items/Weapons.cs +++ b/src/Persistence/Initialization/Version095d/Items/Weapons.cs @@ -29,11 +29,16 @@ internal class Weapons : InitializerBase private static readonly float[] StaffRiseIncreaseByLevelEven = { 0, 3, 7, 10, 14, 17, 21, 24, 28, 31, 35, 40, 45, 50, 56, 63 }; // Staff with even magic power private static readonly float[] StaffRiseIncreaseByLevelOdd = { 0, 4, 7, 11, 14, 18, 21, 25, 28, 32, 36, 40, 45, 51, 57, 63 }; // Staff with odd magic power + private static readonly float[] AmmunitionDamageIncreaseByLevel = { 0, 0.03f, 0.05f, 0.1f }; // Bolts/Arrows + private ItemLevelBonusTable? _weaponDamageIncreaseTable; + private ItemLevelBonusTable? _staffDamageIncreaseTable; private ItemLevelBonusTable? _staffRiseTableEven; private ItemLevelBonusTable? _staffRiseTableOdd; + private ItemLevelBonusTable? _ammunitionDamageIncreaseTable; + /// /// Initializes a new instance of the class. /// @@ -62,7 +67,7 @@ protected ItemOptionDefinition PhysicalDamageOption { get { - return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumPhysBaseDmg)); + return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.PhysicalBaseDmg)); } } @@ -73,7 +78,7 @@ protected ItemOptionDefinition WizardryDamageOption { get { - return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumWizBaseDmg)); + return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.WizardryBaseDmg)); } } @@ -83,8 +88,10 @@ protected ItemOptionDefinition WizardryDamageOption public override void Initialize() { this._weaponDamageIncreaseTable = this.CreateItemBonusTable(DamageIncreaseByLevel, "Damage Increase (Weapons)", "The damage increase by weapon level. It increases by 3 per level, and 1 more after level 10."); + this._staffDamageIncreaseTable = this.CreateItemBonusTable([.. DamageIncreaseByLevel.Select(dmg => dmg /= 2.0f)], "Damage Increase (Staffs)", "The damage increase by staff level. It's half of the physical weapons."); this._staffRiseTableEven = this.CreateItemBonusTable(StaffRiseIncreaseByLevelEven, "Staff Rise (even)", "The staff rise bonus per item level for even magic power staves."); this._staffRiseTableOdd = this.CreateItemBonusTable(StaffRiseIncreaseByLevelOdd, "Staff Rise (odd)", "The staff rise bonus per item level for odd magic power staves."); + this._ammunitionDamageIncreaseTable = this.CreateItemBonusTable(AmmunitionDamageIncreaseByLevel, "Damage Increase % (Bolts/Arrows)", "The damage increase % by ammunition item level."); this.CreateWeapon(0, 0, 0, 0, 1, 2, true, "Kris", 6, 6, 11, 50, 20, 0, 0, 40, 40, 0, 0, 1, 1, 1); this.CreateWeapon(0, 1, 0, 0, 1, 3, true, "Short Sword", 3, 3, 7, 20, 22, 0, 0, 60, 0, 0, 0, 1, 1, 1); @@ -205,6 +212,10 @@ protected void CreateAmmunition(byte @group, byte number, byte slot, byte width, var qualifiedCharacterClasses = this.GameConfiguration.DetermineCharacterClasses(wizardClass == 1, knightClass == 1, elfClass == 1); qualifiedCharacterClasses.ToList().ForEach(item.QualifiedCharacters.Add); + var damagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.AmmunitionDamageBonus, 0f, AggregateType.AddRaw); + damagePowerUp.BonusPerLevelTable = this._ammunitionDamageIncreaseTable; + item.BasePowerUpAttributes.Add(damagePowerUp); + item.IsAmmunition = true; } @@ -253,7 +264,7 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.MaximumItemLevel = isAmmunition ? (byte)0 : Constants.MaximumItemLevel; item.DropsFromMonsters = dropsFromMonsters; item.SetGuid(item.Group, item.Number); - if (slot == 0 && knightClass > 0 && width == 1) + if (slot == 0 && (knightClass > 0 || magicGladiatorClass > 0) && width == 1) { item.ItemSlot = this.GameConfiguration.ItemSlotTypes.First(t => t.ItemSlots.Contains(0) && t.ItemSlots.Contains(1)); } @@ -276,15 +287,18 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber var qualifiedCharacterClasses = this.GameConfiguration.DetermineCharacterClasses(classes); qualifiedCharacterClasses.ToList().ForEach(item.QualifiedCharacters.Add); - var minDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MinimumPhysBaseDmgByWeapon, minimumDamage, AggregateType.AddRaw); - minDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; + var dmgDivider = group == (int)ItemGroups.Staff ? 2.0f : 1.0f; + var bonusPerLevelTable = group == (int)ItemGroups.Staff ? this._staffDamageIncreaseTable : this._weaponDamageIncreaseTable; + + var minDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MinimumPhysBaseDmgByWeapon, minimumDamage / dmgDivider, AggregateType.AddRaw); + minDamagePowerUp.BonusPerLevelTable = bonusPerLevelTable; item.BasePowerUpAttributes.Add(minDamagePowerUp); - var maxDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MaximumPhysBaseDmgByWeapon, maximumDamage, AggregateType.AddRaw); - maxDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; + var maxDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MaximumPhysBaseDmgByWeapon, maximumDamage / dmgDivider, AggregateType.AddRaw); + maxDamagePowerUp.BonusPerLevelTable = bonusPerLevelTable; item.BasePowerUpAttributes.Add(maxDamagePowerUp); - var speedPowerUp = this.CreateItemBasePowerUpDefinition(Stats.AttackSpeed, attackSpeed, AggregateType.AddRaw); + var speedPowerUp = this.CreateItemBasePowerUpDefinition(Stats.AttackSpeedByWeapon, attackSpeed, AggregateType.AddRaw); item.BasePowerUpAttributes.Add(speedPowerUp); this.CreateItemRequirementIfNeeded(item, Stats.Level, levelRequirement); @@ -310,21 +324,14 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.BasePowerUpAttributes.Add(staffRisePowerUp); } - item.IsAmmunition = isAmmunition; - if (!item.IsAmmunition) + if (group == (int)ItemGroups.Bows) { - var ammunitionConsumption = this.Context.CreateNew(); - ammunitionConsumption.TargetAttribute = Stats.AmmunitionConsumptionRate.GetPersistent(this.GameConfiguration); - ammunitionConsumption.BaseValue = 1.0f; - item.BasePowerUpAttributes.Add(ammunitionConsumption); + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.AmmunitionConsumptionRate, 1, AggregateType.AddRaw)); } - if (group != (int)ItemGroups.Bows && width == 2) + if (group != (int)ItemGroups.Bows && group != (int)ItemGroups.Staff && width == 2) { - var isTwoHandedWeapon = this.Context.CreateNew(); - isTwoHandedWeapon.TargetAttribute = Stats.IsTwoHandedWeaponEquipped.GetPersistent(this.GameConfiguration); - isTwoHandedWeapon.BaseValue = 1.0f; - item.BasePowerUpAttributes.Add(isTwoHandedWeapon); + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.IsTwoHandedWeaponEquipped, 1, AggregateType.AddRaw)); } } } \ No newline at end of file diff --git a/src/Persistence/Initialization/VersionSeasonSix/ChaosMixes.cs b/src/Persistence/Initialization/VersionSeasonSix/ChaosMixes.cs index 0910394c2..b803f6810 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/ChaosMixes.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/ChaosMixes.cs @@ -807,6 +807,7 @@ private ItemCrafting DarkHorseCrafting() var crafting = this.Context.CreateNew(); crafting.Name = "Dark Horse"; crafting.Number = 13; + crafting.ItemCraftingHandlerClassName = typeof(DarkHorseCrafting).FullName!; var craftingSettings = this.Context.CreateNew(); craftingSettings.Money = 5_000_000; craftingSettings.SuccessPercent = 60; diff --git a/src/Persistence/Initialization/VersionSeasonSix/GameConfigurationInitializer.cs b/src/Persistence/Initialization/VersionSeasonSix/GameConfigurationInitializer.cs index 62040aac4..af10533b6 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/GameConfigurationInitializer.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/GameConfigurationInitializer.cs @@ -47,8 +47,8 @@ protected override IEnumerable OptionTypes public override void Initialize() { base.Initialize(); - - this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.MaximumCurseBaseDmg, ItemOptionDefinitionNumbers.CurseAttack)); + + this.GameConfiguration.ItemOptions.Add(this.CreateOptionDefinition(Stats.CurseBaseDmg, ItemOptionDefinitionNumbers.CurseAttack)); new CharacterClassInitialization(this.Context, this.GameConfiguration).Initialize(); new SkillsInitializer(this.Context, this.GameConfiguration).Initialize(); diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/AncientSets.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/AncientSets.cs index a864ce4da..0979a8549 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/AncientSets.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/AncientSets.cs @@ -65,8 +65,8 @@ public override void Initialize() 2, (Stats.MaximumHealth, 50.0f), (Stats.TotalAgility, 50.0f), - (Stats.ShieldBlockDamageDecrement, 0.25f), - (Stats.BaseDamageBonus, 30.0f)); + (Stats.DefenseIncreaseWithEquippedShield, 0.25f), + (Stats.FinalDamageBonus, 30.0f)); anonymous.SetGuid(5, 2); this.AddItems( anonymous, @@ -106,13 +106,13 @@ public override void Initialize() var eplete = this.AddAncientSet( "Eplete", // Scale 5, - (Stats.SkillDamageBonus, 15.0f), - (Stats.AttackRatePvm, 50.0f), - (Stats.WizardryAttackDamageIncrease, 0.05f), - (Stats.MaximumHealth, 50.0f), - (Stats.MaximumAbility, 30.0f), - (Stats.CriticalDamageChance, 0.10f), - (Stats.ExcellentDamageChance, 0.10f)); + (Stats.SkillDamageBonus, 15.0f, AggregateType.AddRaw, 0), + (Stats.AttackRatePvm, 1.50f, AggregateType.Multiplicate, 0), + (Stats.AncientWizDmgIncrease, 0.05f, AggregateType.AddRaw, 0), + (Stats.MaximumHealth, 50.0f, AggregateType.AddRaw, 0), + (Stats.MaximumAbility, 30.0f, AggregateType.AddRaw, 0), + (Stats.CriticalDamageChance, 0.10f, AggregateType.AddRaw, 0), + (Stats.ExcellentDamageChance, 0.10f, AggregateType.AddRaw, 0)); eplete.SetGuid(6, 1); this.AddItems( eplete, @@ -125,12 +125,12 @@ public override void Initialize() var berserker = this.AddAncientSet( "Berserker", // Scale 6, - (Stats.MaximumPhysBaseDmg, 10.0f), - (Stats.MaximumPhysBaseDmg, 20.0f), - (Stats.MaximumPhysBaseDmg, 30.0f), - (Stats.MaximumPhysBaseDmg, 40.0f), - (Stats.SkillDamageBonus, 50.0f), - (Stats.TotalStrength, 40.0f)); + (Stats.MaximumPhysBaseDmg, 10.0f, AggregateType.AddRaw, 3), + (Stats.MaximumPhysBaseDmg, 20.0f, AggregateType.AddRaw, 3), + (Stats.MaximumPhysBaseDmg, 30.0f, AggregateType.AddRaw, 3), + (Stats.MaximumPhysBaseDmg, 40.0f, AggregateType.AddRaw, 3), + (Stats.SkillDamageBonus, 50.0f, AggregateType.AddRaw, 0), + (Stats.TotalStrength, 40.0f, AggregateType.AddRaw, 0)); berserker.SetGuid(6, 2); this.AddItems( berserker, @@ -148,7 +148,7 @@ public override void Initialize() (Stats.TotalEnergy, 15.0f), (Stats.MaximumHealth, 50.0f), (Stats.SkillDamageBonus, 25.0f), - (Stats.WizardryAttackDamageIncrease, 0.15f)); + (Stats.AncientWizDmgIncrease, 0.15f)); garuda.SetGuid(8, 1); this.AddItems( garuda, @@ -174,7 +174,7 @@ public override void Initialize() 9, (Stats.TotalEnergy, 15.0f), (Stats.TotalVitality, 30.0f), - (Stats.WizardryAttackDamageIncrease, 0.10f), + (Stats.AncientWizDmgIncrease, 0.10f), (Stats.TotalStrength, 15.0f), (Stats.SkillDamageBonus, 25.0f), (Stats.ExcellentDamageChance, 10.0f), @@ -223,12 +223,12 @@ public override void Initialize() var vicious = this.AddAncientSet( "Vicious", // Dragon 12, - (Stats.SkillDamageBonus, 15.0f), - (Stats.BaseDamageBonus, 15.0f), - (Stats.DoubleDamageChance, 0.10f), - (Stats.MinimumPhysBaseDmg, 20f), - (Stats.MaximumPhysBaseDmg, 30f), - (Stats.DefenseIgnoreChance, 0.05f)); + (Stats.SkillDamageBonus, 15.0f, AggregateType.AddRaw, 0), + (Stats.FinalDamageBonus, 15.0f, AggregateType.AddRaw, 0), + (Stats.DoubleDamageChance, 0.10f, AggregateType.AddRaw, 0), + (Stats.MinimumPhysBaseDmg, 20f, AggregateType.AddRaw, 3), + (Stats.MaximumPhysBaseDmg, 30f, AggregateType.AddRaw, 3), + (Stats.DefenseIgnoreChance, 0.05f, AggregateType.AddRaw, 0)); vicious.SetGuid(1, 2); this.AddItems( vicious, @@ -241,7 +241,7 @@ public override void Initialize() "Apollo", // Pad 13, (Stats.TotalEnergy, 10.0f), - (Stats.WizardryAttackDamageIncrease, 0.05f), + (Stats.AncientWizDmgIncrease, 0.05f), (Stats.SkillDamageBonus, 10.0f), (Stats.MaximumMana, 30.0f), (Stats.MaximumHealth, 30.0f), @@ -263,7 +263,7 @@ public override void Initialize() var barnake = this.AddAncientSet( "Barnake", // Pad 14, - (Stats.WizardryAttackDamageIncrease, 0.10f), + (Stats.AncientWizDmgIncrease, 0.10f), (Stats.TotalEnergy, 20.0f), (Stats.SkillDamageBonus, 30.0f), (Stats.MaximumMana, 100.0f)); @@ -277,12 +277,12 @@ public override void Initialize() var evis = this.AddAncientSet( "Evis", // Bone 15, - (Stats.SkillDamageBonus, 15.0f), - (Stats.TotalVitality, 20.0f), - (Stats.WizardryAttackDamageIncrease, 0.10f), - (Stats.DoubleDamageChance, 0.05f), - (Stats.AttackRatePvm, 50.0f), - (Stats.AbilityRecoveryAbsolute, 5.0f)); + (Stats.SkillDamageBonus, 15.0f, AggregateType.AddRaw, 0), + (Stats.TotalVitality, 20.0f, AggregateType.AddRaw, 0), + (Stats.AncientWizDmgIncrease, 0.10f, AggregateType.AddRaw, 0), + (Stats.DoubleDamageChance, 0.05f, AggregateType.AddRaw, 0), + (Stats.AttackRatePvm, 1.50f, AggregateType.Multiplicate, 0), + (Stats.AbilityRecoveryAbsolute, 5.0f, AggregateType.AddRaw, 0)); evis.SetGuid(4, 1); this.AddItems( evis, @@ -312,15 +312,15 @@ public override void Initialize() var heras = this.AddAncientSet( "Heras", // Sphinx 17, - (Stats.TotalStrength, 15.0f), - (Stats.WizardryAttackDamageIncrease, 0.10f), - (Stats.DefenseIncreaseWithEquippedShield, 0.05f), - (Stats.TotalEnergy, 15.0f), - (Stats.AttackRatePvm, 50.0f), - (Stats.CriticalDamageChance, 0.10f), - (Stats.ExcellentDamageChance, 0.10f), - (Stats.MaximumHealth, 50.0f), - (Stats.MaximumMana, 50.0f)); + (Stats.TotalStrength, 15.0f, AggregateType.AddRaw, 0), + (Stats.AncientWizDmgIncrease, 0.10f, AggregateType.AddRaw, 0), + (Stats.DefenseIncreaseWithEquippedShield, 0.05f, AggregateType.AddRaw, 0), + (Stats.TotalEnergy, 15.0f, AggregateType.AddRaw, 0), + (Stats.AttackRatePvm, 1.50f, AggregateType.Multiplicate, 0), + (Stats.CriticalDamageChance, 0.10f, AggregateType.AddRaw, 0), + (Stats.ExcellentDamageChance, 0.10f, AggregateType.AddRaw, 0), + (Stats.MaximumHealth, 50.0f, AggregateType.AddRaw, 0), + (Stats.MaximumMana, 50.0f, AggregateType.AddRaw, 0)); heras.SetGuid(7, 1); this.AddItems( heras, @@ -350,11 +350,11 @@ public override void Initialize() 19, (Stats.DoubleDamageChance, 0.10f), (Stats.MaximumMana, 50.0f), - (Stats.WizardryAttackDamageIncrease, 0.10f), + (Stats.AncientWizDmgIncrease, 0.10f), (Stats.CriticalDamageChance, 0.15f), (Stats.ExcellentDamageChance, 0.15f), (Stats.CriticalDamageBonus, 20.0f), - (Stats.ExcellentDamageChance, 20.0f)); + (Stats.ExcellentDamageBonus, 20.0f)); anubis.SetGuid(3, 1); this.AddItems( anubis, @@ -369,7 +369,7 @@ public override void Initialize() (Stats.SkillDamageBonus, 10.0f), (Stats.DoubleDamageChance, 0.10f), (Stats.TotalEnergy, 30.0f), - (Stats.WizardryAttackDamageIncrease, 0.10f), + (Stats.AncientWizDmgIncrease, 0.10f), (Stats.DefenseIgnoreChance, 0.05f)); enis.SetGuid(3, 2); this.AddItems( @@ -403,7 +403,7 @@ public override void Initialize() "Drake", // Vine 22, (Stats.TotalAgility, 20.0f), - (Stats.BaseDamageBonus, 25.0f), + (Stats.FinalDamageBonus, 25.0f), (Stats.DoubleDamageChance, 0.20f), (Stats.DefenseBase, 40.0f), (Stats.CriticalDamageChance, 0.10f)); @@ -450,13 +450,13 @@ public override void Initialize() var odin = this.AddAncientSet( "Odin", // Wind 25, - (Stats.TotalEnergy, 15.0f), - (Stats.MaximumHealth, 50.0f), - (Stats.AttackRatePvm, 50.0f), - (Stats.TotalAgility, 30.0f), - (Stats.MaximumMana, 50.0f), - (Stats.DefenseIgnoreChance, 0.05f), - (Stats.MaximumAbility, 50.0f)); + (Stats.TotalEnergy, 15.0f, AggregateType.AddRaw, 0), + (Stats.MaximumHealth, 50.0f, AggregateType.AddRaw, 0), + (Stats.AttackRatePvm, 1.50f, AggregateType.Multiplicate, 0), + (Stats.TotalAgility, 30.0f, AggregateType.AddRaw, 0), + (Stats.MaximumMana, 50.0f, AggregateType.AddRaw, 0), + (Stats.DefenseIgnoreChance, 0.05f, AggregateType.AddRaw, 0), + (Stats.MaximumAbility, 50.0f, AggregateType.AddRaw, 0)); odin.SetGuid(12, 1); this.AddItems( odin, @@ -480,10 +480,10 @@ public override void Initialize() var argo = this.AddAncientSet( "Argo", // Spirit 27, - (Stats.MaximumPhysBaseDmg, 20.0f), - (Stats.SkillDamageBonus, 25.0f), - (Stats.MaximumAbility, 50.0f), - (Stats.DoubleDamageChance, 0.05f)); + (Stats.MaximumPhysBaseDmg, 20.0f, AggregateType.AddRaw, 3), + (Stats.SkillDamageBonus, 25.0f, AggregateType.AddRaw, 0), + (Stats.MaximumAbility, 50.0f, AggregateType.AddRaw, 0), + (Stats.DoubleDamageChance, 0.05f, AggregateType.AddRaw, 0)); argo.SetGuid(13, 1); this.AddItems( argo, @@ -508,14 +508,14 @@ public override void Initialize() var gywen = this.AddAncientSet( "Gywen", // Guardian 29, - (Stats.TotalAgility, 30.0f), - (Stats.MinimumPhysBaseDmg, 20.0f), - (Stats.DefenseBase, 20.0f), - (Stats.MaximumPhysBaseDmg, 20.0f), - (Stats.CriticalDamageChance, 0.15f), - (Stats.ExcellentDamageChance, 0.15f), - (Stats.CriticalDamageBonus, 20.0f), - (Stats.ExcellentDamageBonus, 20.0f)); + (Stats.TotalAgility, 30.0f, AggregateType.AddRaw, 0), + (Stats.MinimumPhysBaseDmg, 20.0f, AggregateType.AddRaw, 3), + (Stats.DefenseBase, 20.0f, AggregateType.AddRaw, 0), + (Stats.MaximumPhysBaseDmg, 20.0f, AggregateType.AddRaw, 3), + (Stats.CriticalDamageChance, 0.15f, AggregateType.AddRaw, 0), + (Stats.ExcellentDamageChance, 0.15f, AggregateType.AddRaw, 0), + (Stats.CriticalDamageBonus, 20.0f, AggregateType.AddRaw, 0), + (Stats.ExcellentDamageBonus, 20.0f, AggregateType.AddRaw, 0)); gywen.SetGuid(14, 1); this.AddItems( gywen, @@ -528,7 +528,7 @@ public override void Initialize() var aruan = this.AddAncientSet( "Aruan", // Guardian 30, - (Stats.BaseDamageBonus, 10.0f), + (Stats.FinalDamageBonus, 10.0f), (Stats.DoubleDamageChance, 0.10f), (Stats.SkillDamageBonus, 20.0f), (Stats.CriticalDamageChance, 0.15f), @@ -550,7 +550,7 @@ public override void Initialize() (Stats.SkillDamageBonus, 15.0f), (Stats.ExcellentDamageChance, 0.15f), (Stats.ExcellentDamageBonus, 30.0f), - (Stats.WizardryAttackDamageIncrease, 0.10f), + (Stats.AncientWizDmgIncrease, 0.10f), (Stats.TotalStrength, 30.0f)); gaion.SetGuid(15, 1); this.AddItems( @@ -564,7 +564,7 @@ public override void Initialize() "Muren", // Storm Crow 32, (Stats.SkillDamageBonus, 10.0f), - (Stats.WizardryAttackDamageIncrease, 0.10f), + (Stats.AncientWizDmgIncrease, 0.10f), (Stats.DoubleDamageChance, 0.10f), (Stats.CriticalDamageChance, 0.15f), (Stats.ExcellentDamageChance, 0.15f), @@ -599,7 +599,7 @@ public override void Initialize() var broy = this.AddAncientSet( "Broy", // Adamantine 34, - (Stats.BaseDamageBonus, 20.0f), + (Stats.FinalDamageBonus, 20.0f), (Stats.SkillDamageBonus, 20.0f), (Stats.TotalEnergy, 30.0f), (Stats.CriticalDamageChance, 0.15f), @@ -635,7 +635,7 @@ public override void Initialize() var semeden = this.AddAncientSet( "Semeden", // Red Wing 36, - (Stats.WizardryAttackDamageIncrease, 0.15f), + (Stats.AncientWizDmgIncrease, 0.15f), (Stats.SkillDamageBonus, 25.0f), (Stats.TotalEnergy, 30.0f), (Stats.CriticalDamageChance, 0.15f), @@ -667,6 +667,11 @@ private void AddItems(ItemSetGroup set, params (short Number, ItemGroups Group, } private ItemSetGroup AddAncientSet(string name, short setNumber, params (AttributeDefinition Attribute, float Value)[] ancientOptions) + { + return this.AddAncientSet(name, setNumber, ancientOptions.Select(ancOpt => (ancOpt.Attribute, ancOpt.Value, AggregateType.AddRaw, (byte)0)).ToArray()); + } + + private ItemSetGroup AddAncientSet(string name, short setNumber, params (AttributeDefinition Attribute, float Value, AggregateType AggregateType, byte Stage)[] ancientOptions) { var set = this.Context.CreateNew(); set.SetGuid(setNumber); @@ -687,7 +692,9 @@ private ItemSetGroup AddAncientSet(string name, short setNumber, params (Attribu option.PowerUpDefinition = this.Context.CreateNew(); option.PowerUpDefinition.TargetAttribute = optionTuple.Attribute.GetPersistent(this.GameConfiguration); option.PowerUpDefinition.Boost = this.Context.CreateNew(); + option.PowerUpDefinition.Boost.ConstantValue.AggregateType = optionTuple.AggregateType; option.PowerUpDefinition.Boost.ConstantValue.Value = optionTuple.Value; + option.PowerUpDefinition.Boost.ConstantValue.Stage = optionTuple.Stage; options.PossibleOptions.Add(option); } diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Armors.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Armors.cs index 3562479e0..e5aba3ceb 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Armors.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Armors.cs @@ -279,7 +279,7 @@ public override void Initialize() this.CreateGloves(44, "Lilium Gloves", 82, 45, 6, 80, 0, 75, 20, 0, 0, 0, 0, 0, 2); this.CreateGloves(45, "Titan Gloves", 100, 56, 7, 86, 0, 222, 32, 0, 1, 0, 0, 0, 0); this.CreateGloves(46, "Brave Gloves", 97, 42, 7, 86, 0, 74, 162, 0, 1, 0, 0, 0, 0); - this.CreateGloves(47, "Destory Gloves", 101, 49, 7, 86, 0, 212, 57, 0, 0, 0, 1, 0, 0); + this.CreateGloves(47, "Destroy Gloves", 101, 49, 7, 86, 0, 212, 57, 0, 0, 0, 1, 0, 0); this.CreateGloves(48, "Phantom Gloves", 99, 40, 7, 86, 0, 62, 19, 0, 0, 0, 1, 0, 0); this.CreateGloves(49, "Seraphim Gloves", 100, 43, 7, 86, 0, 55, 197, 0, 0, 1, 0, 0, 0); this.CreateGloves(50, "Faith Gloves", 95, 36, 7, 86, 0, 32, 29, 0, 0, 1, 0, 0, 0); diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/GuardianOptions.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/GuardianOptions.cs index a49c5a15f..4ffed6a2f 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/GuardianOptions.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/GuardianOptions.cs @@ -57,7 +57,7 @@ private void CreatePantsOption() definition.AddsRandomly = false; definition.PossibleOptions.Add(this.CreateOption(ItemGroups.Pants, Stats.DefenseRatePvp, 10, AggregateType.AddRaw, ItemOptionDefinitionNumbers.GuardianOption1)); - definition.PossibleOptions.Add(this.CreateOption(ItemGroups.Pants, Stats.DefenseBase, 200, AggregateType.AddRaw, ItemOptionDefinitionNumbers.GuardianOption2)); + definition.PossibleOptions.Add(this.CreateOption(ItemGroups.Pants, Stats.DefenseBase, 200 / 2, AggregateType.AddRaw, 3, ItemOptionDefinitionNumbers.GuardianOption2)); } private void CreateArmorOption() @@ -105,6 +105,11 @@ private void CreateBootsOption() } private IncreasableItemOption CreateOption(ItemGroups itemGroup, AttributeDefinition attributeDefinition, float value, AggregateType aggregateType, short optionNumber) + { + return this.CreateOption(itemGroup, attributeDefinition, value, aggregateType, 0, optionNumber); + } + + private IncreasableItemOption CreateOption(ItemGroups itemGroup, AttributeDefinition attributeDefinition, float value, AggregateType aggregateType, byte stage, short optionNumber) { var itemOption = this.Context.CreateNew(); itemOption.SetGuid(optionNumber, (short)itemGroup); @@ -115,6 +120,7 @@ private IncreasableItemOption CreateOption(ItemGroups itemGroup, AttributeDefini itemOption.PowerUpDefinition.Boost = this.Context.CreateNew(); itemOption.PowerUpDefinition.Boost.ConstantValue.Value = value; itemOption.PowerUpDefinition.Boost.ConstantValue.AggregateType = aggregateType; + itemOption.PowerUpDefinition.Boost.ConstantValue.Stage = stage; return itemOption; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/HarmonyOptions.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/HarmonyOptions.cs index 71f205fc7..5c5a23876 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/HarmonyOptions.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/HarmonyOptions.cs @@ -64,14 +64,14 @@ private void CreateCurseAttackOptions() definition.Name = CurseAttackOptionsName; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateHarmonyOptions(1, ItemOptionDefinitionNumbers.HarmonyCurse, 40, Stats.WizardryBaseDmg, AggregateType.AddRaw, 0, 6, 8, 10, 12, 14, 16, 17, 18, 19, 21, 23, 25, 27, 31)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(2, ItemOptionDefinitionNumbers.HarmonyCurse, 40, Stats.RequiredStrengthReduction, AggregateType.AddRaw, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(3, ItemOptionDefinitionNumbers.HarmonyCurse, 40, Stats.RequiredAgilityReduction, AggregateType.AddRaw, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(4, ItemOptionDefinitionNumbers.HarmonyCurse, 30, Stats.SkillDamageBonus, AggregateType.AddRaw, 6, 7, 10, 13, 16, 19, 22, 25, 30)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(5, ItemOptionDefinitionNumbers.HarmonyCurse, 30, Stats.CriticalDamageBonus, AggregateType.AddRaw, 6, 10, 12, 14, 16, 18, 20, 22, 28)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(6, ItemOptionDefinitionNumbers.HarmonyCurse, 20, Stats.ShieldDecreaseRateIncrease, AggregateType.AddRaw, 9, 4, 6, 8, 10, 13)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(7, ItemOptionDefinitionNumbers.HarmonyCurse, 20, Stats.AttackRatePvp, AggregateType.AddRaw, 9, 5, 7, 9, 11, 14)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(8, ItemOptionDefinitionNumbers.HarmonyCurse, 10, Stats.ShieldBypassChance, AggregateType.AddRaw, 13, 0.15f)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(1, ItemOptionDefinitionNumbers.HarmonyCurse, 40, Stats.HarmonyWizBaseDmg, AggregateType.AddRaw, 0, 0, 6, 8, 10, 12, 14, 16, 17, 18, 19, 21, 23, 25, 27, 31)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(2, ItemOptionDefinitionNumbers.HarmonyCurse, 40, Stats.RequiredStrengthReduction, AggregateType.AddRaw, 0, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(3, ItemOptionDefinitionNumbers.HarmonyCurse, 40, Stats.RequiredAgilityReduction, AggregateType.AddRaw, 0, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(4, ItemOptionDefinitionNumbers.HarmonyCurse, 30, Stats.SkillDamageBonus, AggregateType.AddRaw, 0, 6, 7, 10, 13, 16, 19, 22, 25, 30)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(5, ItemOptionDefinitionNumbers.HarmonyCurse, 30, Stats.CriticalDamageBonus, AggregateType.AddRaw, 0, 6, 10, 12, 14, 16, 18, 20, 22, 28)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(6, ItemOptionDefinitionNumbers.HarmonyCurse, 20, Stats.ShieldDecreaseRateIncrease, AggregateType.AddRaw, 0, 9, 4, 6, 8, 10, 13)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(7, ItemOptionDefinitionNumbers.HarmonyCurse, 20, Stats.AttackRatePvp, AggregateType.AddRaw, 0, 9, 5, 7, 9, 11, 14)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(8, ItemOptionDefinitionNumbers.HarmonyCurse, 10, Stats.ShieldBypassChance, AggregateType.AddRaw, 0, 13, 0.15f)); } private void CreateWizardryAttackOptions() @@ -81,14 +81,14 @@ private void CreateWizardryAttackOptions() definition.Name = WizardryAttackOptionsName; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateHarmonyOptions(1, ItemOptionDefinitionNumbers.HarmonyWizardry, 40, Stats.WizardryBaseDmg, AggregateType.AddRaw, 0, 6, 8, 10, 12, 14, 16, 17, 18, 19, 21, 23, 25, 27, 31)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(2, ItemOptionDefinitionNumbers.HarmonyWizardry, 40, Stats.RequiredStrengthReduction, AggregateType.AddRaw, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(3, ItemOptionDefinitionNumbers.HarmonyWizardry, 40, Stats.RequiredAgilityReduction, AggregateType.AddRaw, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(4, ItemOptionDefinitionNumbers.HarmonyWizardry, 30, Stats.SkillDamageBonus, AggregateType.AddRaw, 6, 7, 10, 13, 16, 19, 22, 25, 30)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(5, ItemOptionDefinitionNumbers.HarmonyWizardry, 30, Stats.CriticalDamageBonus, AggregateType.AddRaw, 6, 10, 12, 14, 16, 18, 20, 22, 28)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(6, ItemOptionDefinitionNumbers.HarmonyWizardry, 20, Stats.ShieldDecreaseRateIncrease, AggregateType.AddRaw, 9, 4, 6, 8, 10, 13)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(7, ItemOptionDefinitionNumbers.HarmonyWizardry, 20, Stats.AttackRatePvp, AggregateType.AddRaw, 9, 5, 7, 9, 11, 14)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(8, ItemOptionDefinitionNumbers.HarmonyWizardry, 10, Stats.ShieldBypassChance, AggregateType.AddRaw, 13, 0.15f)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(1, ItemOptionDefinitionNumbers.HarmonyWizardry, 40, Stats.HarmonyWizBaseDmg, AggregateType.AddRaw, 0, 0, 6, 8, 10, 12, 14, 16, 17, 18, 19, 21, 23, 25, 27, 31)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(2, ItemOptionDefinitionNumbers.HarmonyWizardry, 40, Stats.RequiredStrengthReduction, AggregateType.AddRaw, 0, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(3, ItemOptionDefinitionNumbers.HarmonyWizardry, 40, Stats.RequiredAgilityReduction, AggregateType.AddRaw, 0, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(4, ItemOptionDefinitionNumbers.HarmonyWizardry, 30, Stats.SkillDamageBonus, AggregateType.AddRaw, 0, 6, 7, 10, 13, 16, 19, 22, 25, 30)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(5, ItemOptionDefinitionNumbers.HarmonyWizardry, 30, Stats.CriticalDamageBonus, AggregateType.AddRaw, 0, 6, 10, 12, 14, 16, 18, 20, 22, 28)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(6, ItemOptionDefinitionNumbers.HarmonyWizardry, 20, Stats.ShieldDecreaseRateIncrease, AggregateType.AddRaw, 0, 9, 4, 6, 8, 10, 13)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(7, ItemOptionDefinitionNumbers.HarmonyWizardry, 20, Stats.AttackRatePvp, AggregateType.AddRaw, 0, 9, 5, 7, 9, 11, 14)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(8, ItemOptionDefinitionNumbers.HarmonyWizardry, 10, Stats.ShieldBypassChance, AggregateType.AddRaw, 0, 13, 0.15f)); } private void CreatePhysicalAttackOptions() @@ -98,16 +98,16 @@ private void CreatePhysicalAttackOptions() definition.Name = PhysicalAttackOptionsName; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateHarmonyOptions(1, ItemOptionDefinitionNumbers.HarmonyPhysical, 40, Stats.MinimumPhysBaseDmg, AggregateType.AddRaw, 0, 2, 3, 4, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 20)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(2, ItemOptionDefinitionNumbers.HarmonyPhysical, 40, Stats.MaximumPhysBaseDmg, AggregateType.AddRaw, 0, 3, 4, 5, 6, 7, 8, 10, 12, 14, 17, 20, 23, 26, 29)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(3, ItemOptionDefinitionNumbers.HarmonyPhysical, 40, Stats.RequiredStrengthReduction, AggregateType.AddRaw, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(4, ItemOptionDefinitionNumbers.HarmonyPhysical, 40, Stats.RequiredAgilityReduction, AggregateType.AddRaw, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(5, ItemOptionDefinitionNumbers.HarmonyPhysical, 30, Stats.PhysicalBaseDmg, AggregateType.AddRaw, 6, 7, 8, 9, 11, 12, 14, 16, 19)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(6, ItemOptionDefinitionNumbers.HarmonyPhysical, 30, Stats.CriticalDamageBonus, AggregateType.AddRaw, 6, 12, 14, 16, 18, 20, 22, 24, 30)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(7, ItemOptionDefinitionNumbers.HarmonyPhysical, 20, Stats.SkillDamageBonus, AggregateType.AddRaw, 9, 12, 14, 16, 18, 22)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(8, ItemOptionDefinitionNumbers.HarmonyPhysical, 20, Stats.AttackRatePvp, AggregateType.AddRaw, 9, 5, 7, 9, 11, 14)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(9, ItemOptionDefinitionNumbers.HarmonyPhysical, 20, Stats.ShieldDecreaseRateIncrease, AggregateType.AddRaw, 9, 3, 5, 7, 9, 10)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(10, ItemOptionDefinitionNumbers.HarmonyPhysical, 10, Stats.ShieldBypassChance, AggregateType.AddRaw, 13, 0.10f)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(1, ItemOptionDefinitionNumbers.HarmonyPhysical, 40, Stats.MinimumPhysBaseDmg, AggregateType.AddRaw, 2, 0, 2, 3, 4, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 20)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(2, ItemOptionDefinitionNumbers.HarmonyPhysical, 40, Stats.MaximumPhysBaseDmg, AggregateType.AddRaw, 2, 0, 3, 4, 5, 6, 7, 8, 10, 12, 14, 17, 20, 23, 26, 29)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(3, ItemOptionDefinitionNumbers.HarmonyPhysical, 40, Stats.RequiredStrengthReduction, AggregateType.AddRaw, 0, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(4, ItemOptionDefinitionNumbers.HarmonyPhysical, 40, Stats.RequiredAgilityReduction, AggregateType.AddRaw, 0, 0, 6, 8, 10, 12, 14, 16, 20, 23, 26, 29, 32, 35, 37, 40)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(5, ItemOptionDefinitionNumbers.HarmonyPhysical, 30, Stats.HarmonyPhysBaseDmg, AggregateType.AddRaw, 0, 6, 7, 8, 9, 11, 12, 14, 16, 19)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(6, ItemOptionDefinitionNumbers.HarmonyPhysical, 30, Stats.CriticalDamageBonus, AggregateType.AddRaw, 0, 6, 12, 14, 16, 18, 20, 22, 24, 30)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(7, ItemOptionDefinitionNumbers.HarmonyPhysical, 20, Stats.SkillDamageBonus, AggregateType.AddRaw, 0, 9, 12, 14, 16, 18, 22)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(8, ItemOptionDefinitionNumbers.HarmonyPhysical, 20, Stats.AttackRatePvp, AggregateType.AddRaw, 0, 9, 5, 7, 9, 11, 14)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(9, ItemOptionDefinitionNumbers.HarmonyPhysical, 20, Stats.ShieldDecreaseRateIncrease, AggregateType.AddRaw, 0, 9, 3, 5, 7, 9, 10)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(10, ItemOptionDefinitionNumbers.HarmonyPhysical, 10, Stats.ShieldBypassChance, AggregateType.AddRaw, 0, 13, 0.10f)); } private void CreateDefenseOptions() @@ -117,23 +117,24 @@ private void CreateDefenseOptions() definition.Name = DefenseOptionsName; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateHarmonyOptions(1, ItemOptionDefinitionNumbers.HarmonyDefense, 50, Stats.DefenseBase, AggregateType.AddRaw, 0, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 25)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(2, ItemOptionDefinitionNumbers.HarmonyDefense, 40, Stats.MaximumAbility, AggregateType.AddRaw, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(3, ItemOptionDefinitionNumbers.HarmonyDefense, 40, Stats.MaximumHealth, AggregateType.AddRaw, 3, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 30)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(4, ItemOptionDefinitionNumbers.HarmonyDefense, 30, Stats.HealthRecoveryAbsolute, AggregateType.AddRaw, 6, 1, 2, 3, 4, 5, 6, 7, 8)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(5, ItemOptionDefinitionNumbers.HarmonyDefense, 20, Stats.ManaRecoveryAbsolute, AggregateType.AddRaw, 9, 1, 2, 3, 4, 5)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(6, ItemOptionDefinitionNumbers.HarmonyDefense, 20, Stats.DefenseRatePvp, AggregateType.AddRaw, 9, 3, 4, 5, 6, 8)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(7, ItemOptionDefinitionNumbers.HarmonyDefense, 20, Stats.DamageReceiveDecrement, AggregateType.Multiplicate, 9, 0.97f, 0.96f, 0.95f, 0.94f, 0.93f)); - definition.PossibleOptions.Add(this.CreateHarmonyOptions(8, ItemOptionDefinitionNumbers.HarmonyDefense, 10, Stats.ShieldRateIncrease, AggregateType.AddRaw, 13, 0.05f)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(1, ItemOptionDefinitionNumbers.HarmonyDefense, 50, Stats.DefenseBase, AggregateType.AddRaw, 2, 0, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 25)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(2, ItemOptionDefinitionNumbers.HarmonyDefense, 40, Stats.MaximumAbility, AggregateType.AddRaw, 0, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(3, ItemOptionDefinitionNumbers.HarmonyDefense, 40, Stats.MaximumHealth, AggregateType.AddRaw, 0, 3, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 30)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(4, ItemOptionDefinitionNumbers.HarmonyDefense, 30, Stats.HealthRecoveryAbsolute, AggregateType.AddRaw, 0, 6, 1, 2, 3, 4, 5, 6, 7, 8)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(5, ItemOptionDefinitionNumbers.HarmonyDefense, 20, Stats.ManaRecoveryAbsolute, AggregateType.AddRaw, 0, 9, 1, 2, 3, 4, 5)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(6, ItemOptionDefinitionNumbers.HarmonyDefense, 20, Stats.DefenseRatePvp, AggregateType.AddRaw, 0, 9, 3, 4, 5, 6, 8)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(7, ItemOptionDefinitionNumbers.HarmonyDefense, 20, Stats.ArmorDamageDecrease, AggregateType.AddRaw, 0, 9, 0.03f, 0.04f, 0.05f, 0.06f, 0.07f)); + definition.PossibleOptions.Add(this.CreateHarmonyOptions(8, ItemOptionDefinitionNumbers.HarmonyDefense, 10, Stats.ShieldRateIncrease, AggregateType.AddRaw, 0, 13, 0.05f)); } - private IncreasableItemOption CreateHarmonyOptions(short number, short parentNumber, byte weight, AttributeDefinition attributeDefinition, AggregateType aggregateType, byte minimumItemLevel, params float[] values) + private IncreasableItemOption CreateHarmonyOptions(short number, short parentNumber, byte weight, AttributeDefinition attributeDefinition, AggregateType aggregateType, byte stage, byte minimumItemLevel, params float[] values) { var itemOption = this.Context.CreateNew(); itemOption.SetGuid(parentNumber, number); itemOption.OptionType = this.GameConfiguration.ItemOptionTypes.First(t => t == ItemOptionTypes.HarmonyOption); itemOption.Number = number; itemOption.Weight = weight; + int valueDivisor = attributeDefinition == Stats.DefenseBase ? 2 : 1; foreach (var value in values) { var optionOfLevel = this.Context.CreateNew(); @@ -142,8 +143,9 @@ private IncreasableItemOption CreateHarmonyOptions(short number, short parentNum var powerUpDefinition = this.Context.CreateNew(); powerUpDefinition.TargetAttribute = this.GameConfiguration.Attributes.First(a => a == attributeDefinition); powerUpDefinition.Boost = this.Context.CreateNew(); - powerUpDefinition.Boost.ConstantValue.Value = value; + powerUpDefinition.Boost.ConstantValue.Value = value / valueDivisor; powerUpDefinition.Boost.ConstantValue.AggregateType = aggregateType; + powerUpDefinition.Boost.ConstantValue.Stage = stage; optionOfLevel.PowerUpDefinition = powerUpDefinition; itemOption.LevelDependentOptions.Add(optionOfLevel); } diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Jewelery.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Jewelery.cs index c4d8764eb..8f5280202 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Jewelery.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Jewelery.cs @@ -65,48 +65,97 @@ protected override void CreateItems() this.CreateJewelery(115, 9, false, "Sapphire Necklace", 0, 0, null, null, null); */ +#pragma warning disable SA1117 // Parameters should be on same line or separete lines var eliteSkeletonRing = this.CreateTransformationRing(39, "Elite Transfer Skeleton Ring", 10, 255, CharacterTransformationSkin.EliteSkillSoldier); eliteSkeletonRing.PossibleItemOptions.Add( - this.CreateItemOptionDefinition("Elite Transfer Skeleton Ring", - ItemOptionDefinitionNumbers.EliteTransferSkeletonRing, - (Stats.DefenseBase, 10, AggregateType.AddRaw), - (Stats.MaximumHealth, 400, AggregateType.AddRaw))); - this.CreateTransformationRing(40, "Jack Olantern Transformation Ring", 10, 100, CharacterTransformationSkin.JackOlantern); - this.CreateTransformationRing(41, "Christmas Transformation Ring", 1, 100, CharacterTransformationSkin.Christmas); - this.CreateTransformationRing(42, "Game Master Transformation Ring", 0, 255, CharacterTransformationSkin.GameMaster); + this.CreateItemOptionDefinition("Elite Transfer Skeleton Ring", ItemOptionDefinitionNumbers.EliteTransferSkeletonRing, + (Stats.DefenseBase, 1.1f, AggregateType.Multiplicate, 1), + (Stats.MaximumHealth, 400, AggregateType.AddRaw, 0))); // todo: added health should be equal to Stats.TotalLevel + this.CreateTransformationRing(40, "Jack O'lantern Transformation Ring", 10, 100, CharacterTransformationSkin.JackOlantern); + var christmasRing = this.CreateTransformationRing(41, "Christmas Transformation Ring", 1, 100, CharacterTransformationSkin.Christmas); + christmasRing.PossibleItemOptions.Add( + this.CreateItemOptionDefinition("Christmas Transformation Ring", ItemOptionDefinitionNumbers.ChristmasTransformationRing, + (Stats.MinimumPhysBaseDmg, 20, AggregateType.AddRaw, 1), + (Stats.MaximumPhysBaseDmg, 20, AggregateType.AddRaw, 1), + (Stats.MinimumWizBaseDmg, 20, AggregateType.AddRaw, 1), + (Stats.MaximumWizBaseDmg, 20, AggregateType.AddRaw, 1))); + this.CreateTransformationRing(42, "Game Master Transformation Ring", 0, 255, CharacterTransformationSkin.GameMaster); // todo: add options this.CreateTransformationRing(68, "Snowman Transformation Ring", 10, 100, CharacterTransformationSkin.Snowman); var pandaRing = this.CreateTransformationRing(76, "Panda Transformation Ring", 28, 255, CharacterTransformationSkin.Panda); pandaRing.PossibleItemOptions.Add( - this.CreateItemOptionDefinition("Panda Ring", - ItemOptionDefinitionNumbers.PandaRing, - (Stats.MoneyAmountRate, 1.5f, AggregateType.Multiplicate), - (Stats.BaseDamageBonus, 30, AggregateType.AddRaw))); + this.CreateItemOptionDefinition("Panda Transformation Ring", ItemOptionDefinitionNumbers.PandaRing, + (Stats.MinimumPhysBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumPhysBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MinimumWizBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumWizBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MinimumCurseBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumCurseBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MoneyAmountRate, 1.5f, AggregateType.Multiplicate, 1), + (Stats.PandaRingDamageBonus, 30, AggregateType.AddRaw, 0))); var skeletonRing = this.CreateTransformationRing(122, "Skeleton Transformation Ring", 1, 255, CharacterTransformationSkin.Skeleton); skeletonRing.PossibleItemOptions.Add( - this.CreateItemOptionDefinition("Skeleton Transformation Ring", - ItemOptionDefinitionNumbers.SkeletonTransformationRing, - (Stats.BaseDamageBonus, 40, AggregateType.AddRaw), - (Stats.ExperienceRate, 1.5f, AggregateType.Multiplicate))); // todo: exp rate only with equipped skeleton pet - this.CreateTransformationRing(163, "? Transformation Ring", 1, 255, (CharacterTransformationSkin)625); - this.CreateTransformationRing(164, "?? Transformation Ring", 1, 255, (CharacterTransformationSkin)626); - this.CreateTransformationRing(165, "??? Transformation Ring", 1, 255, (CharacterTransformationSkin)642); + this.CreateItemOptionDefinition("Skeleton Transformation Ring", ItemOptionDefinitionNumbers.SkeletonTransformationRing, + (Stats.MinimumPhysBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MaximumPhysBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MinimumWizBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MaximumWizBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MinimumCurseBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MaximumCurseBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.ExperienceRate, 1.5f, AggregateType.Multiplicate, 0))); // todo: exp rate only applies with equipped skeleton pet + var robotKnightRing = this.CreateTransformationRing(163, "Robot Knight Transformation Ring", 1, 255, (CharacterTransformationSkin)625); + robotKnightRing.PossibleItemOptions.Add( + this.CreateItemOptionDefinition("Robot Knight Transformation Ring", ItemOptionDefinitionNumbers.RobotKnightTransformationRing, + (Stats.MinimumPhysBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumPhysBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MinimumWizBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumWizBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MinimumCurseBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumCurseBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.DefenseBase, 10, AggregateType.AddRaw, 2))); + var miniRobotRing = this.CreateTransformationRing(164, "Mini Robot Transformation Ring", 1, 255, (CharacterTransformationSkin)626); + miniRobotRing.PossibleItemOptions.Add( + this.CreateItemOptionDefinition( + "Mini Robot Transformation Ring", + ItemOptionDefinitionNumbers.MiniRobotTransformationRing, + (Stats.MinimumPhysBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumPhysBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MinimumWizBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumWizBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MinimumCurseBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.MaximumCurseBaseDmg, 30, AggregateType.AddRaw, 1), + (Stats.AttackSpeedAny, 7, AggregateType.AddRaw, 0))); + var greatHeavenlyMageRing = this.CreateTransformationRing(165, "Great Heavenly Mage Transformation Ring", 1, 255, (CharacterTransformationSkin)642); + greatHeavenlyMageRing.PossibleItemOptions.Add( + this.CreateItemOptionDefinition("Great Heavenly Mage Transformation Ring", ItemOptionDefinitionNumbers.GreatHeavenlyMageTransformationRing, + (Stats.MinimumPhysBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MaximumPhysBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MinimumWizBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MaximumWizBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MinimumCurseBaseDmg, 40, AggregateType.AddRaw, 1), + (Stats.MaximumCurseBaseDmg, 40, AggregateType.AddRaw, 1))); } +#pragma warning restore SA1011 - private ItemOptionDefinition CreateItemOptionDefinition(string name, short number, params (AttributeDefinition targetOption, float value, AggregateType aggregateType)[] options) + private ItemOptionDefinition CreateItemOptionDefinition(string name, short number, params (AttributeDefinition TargetOption, float Value, AggregateType AggregateType)[] options) + { + return this.CreateItemOptionDefinition(name, number, options.Select(opt => (opt.TargetOption, opt.Value, opt.AggregateType, (byte)0)).ToArray()); + } + + private ItemOptionDefinition CreateItemOptionDefinition(string name, short number, params (AttributeDefinition TargetOption, float Value, AggregateType AggregateType, byte Stage)[] options) { var optionDefinition = this.Context.CreateNew(); optionDefinition.SetGuid(number); this.GameConfiguration.ItemOptions.Add(optionDefinition); optionDefinition.Name = name; - foreach (var (targetOption, value, aggregateType) in options) + foreach (var (targetOption, value, aggregateType, stage) in options) { - optionDefinition.PossibleOptions.Add(this.CreateItemOption(targetOption, value, aggregateType, number)); + optionDefinition.PossibleOptions.Add(this.CreateItemOption(targetOption, value, aggregateType, stage, number)); } return optionDefinition; } - private IncreasableItemOption CreateItemOption(AttributeDefinition targetOption, float value, AggregateType aggregateType, short number) + private IncreasableItemOption CreateItemOption(AttributeDefinition targetOption, float value, AggregateType aggregateType, byte stage, short number) { var itemOption = this.Context.CreateNew(); itemOption.SetGuid(number, targetOption.Id.ExtractFirstTwoBytes()); @@ -115,6 +164,7 @@ private IncreasableItemOption CreateItemOption(AttributeDefinition targetOption, itemOption.PowerUpDefinition.Boost = this.Context.CreateNew(); itemOption.PowerUpDefinition.Boost.ConstantValue.Value = value; itemOption.PowerUpDefinition.Boost.ConstantValue.AggregateType = aggregateType; + itemOption.PowerUpDefinition.Boost.ConstantValue.Stage = stage; return itemOption; } @@ -141,34 +191,54 @@ private void CreateWizardsRing() ring.PossibleItemOptions.Add(optionDefinition); optionDefinition.Name = "Wizard's Ring Options"; - var increaseDamage = this.Context.CreateNew(); - increaseDamage.SetGuid(ItemOptionDefinitionNumbers.WizardRing, 1); - increaseDamage.PowerUpDefinition = this.Context.CreateNew(); - increaseDamage.PowerUpDefinition.TargetAttribute = Stats.AttackDamageIncrease.GetPersistent(this.GameConfiguration); - increaseDamage.PowerUpDefinition.Boost = this.Context.CreateNew(); - increaseDamage.PowerUpDefinition.Boost.ConstantValue.Value = 0.1f; - optionDefinition.PossibleOptions.Add(increaseDamage); - - var increaseSpeed = this.Context.CreateNew(); - increaseSpeed.SetGuid(ItemOptionDefinitionNumbers.WizardRing, 2); - increaseSpeed.PowerUpDefinition = this.Context.CreateNew(); - increaseSpeed.PowerUpDefinition.TargetAttribute = Stats.AttackSpeed.GetPersistent(this.GameConfiguration); - increaseSpeed.PowerUpDefinition.Boost = this.Context.CreateNew(); - increaseSpeed.PowerUpDefinition.Boost.ConstantValue.Value = 10f; - optionDefinition.PossibleOptions.Add(increaseSpeed); - - var increaseWizardryDamage = this.Context.CreateNew(); - increaseWizardryDamage.SetGuid(ItemOptionDefinitionNumbers.WizardRing, 3); - increaseWizardryDamage.PowerUpDefinition = this.Context.CreateNew(); - increaseWizardryDamage.PowerUpDefinition.TargetAttribute = Stats.WizardryAttackDamageIncrease.GetPersistent(this.GameConfiguration); - increaseWizardryDamage.PowerUpDefinition.Boost = this.Context.CreateNew(); - increaseWizardryDamage.PowerUpDefinition.Boost.ConstantValue.Value = 0.1f; - optionDefinition.PossibleOptions.Add(increaseWizardryDamage); + var increaseMinPhysBaseDamage = this.Context.CreateNew(); + increaseMinPhysBaseDamage.SetGuid(ItemOptionDefinitionNumbers.WizardRing, 1); + increaseMinPhysBaseDamage.PowerUpDefinition = this.Context.CreateNew(); + increaseMinPhysBaseDamage.PowerUpDefinition.TargetAttribute = Stats.MinimumPhysBaseDmg.GetPersistent(this.GameConfiguration); + increaseMinPhysBaseDamage.PowerUpDefinition.Boost = this.Context.CreateNew(); + increaseMinPhysBaseDamage.PowerUpDefinition.Boost.ConstantValue.Value = 1.1f; + increaseMinPhysBaseDamage.PowerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + optionDefinition.PossibleOptions.Add(increaseMinPhysBaseDamage); + + var increaseMaxPhysBaseDamage = this.Context.CreateNew(); + increaseMaxPhysBaseDamage.SetGuid(ItemOptionDefinitionNumbers.WizardRing, 2); + increaseMaxPhysBaseDamage.PowerUpDefinition = this.Context.CreateNew(); + increaseMaxPhysBaseDamage.PowerUpDefinition.TargetAttribute = Stats.MaximumPhysBaseDmg.GetPersistent(this.GameConfiguration); + increaseMaxPhysBaseDamage.PowerUpDefinition.Boost = this.Context.CreateNew(); + increaseMaxPhysBaseDamage.PowerUpDefinition.Boost.ConstantValue.Value = 1.1f; + increaseMaxPhysBaseDamage.PowerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + optionDefinition.PossibleOptions.Add(increaseMaxPhysBaseDamage); + + var increaseAttackSpeed = this.Context.CreateNew(); + increaseAttackSpeed.SetGuid(ItemOptionDefinitionNumbers.WizardRing, 3); + increaseAttackSpeed.PowerUpDefinition = this.Context.CreateNew(); + increaseAttackSpeed.PowerUpDefinition.TargetAttribute = Stats.AttackSpeedAny.GetPersistent(this.GameConfiguration); + increaseAttackSpeed.PowerUpDefinition.Boost = this.Context.CreateNew(); + increaseAttackSpeed.PowerUpDefinition.Boost.ConstantValue.Value = 10f; + optionDefinition.PossibleOptions.Add(increaseAttackSpeed); + + var increaseMinWizBaseDamage = this.Context.CreateNew(); + increaseMinWizBaseDamage.SetGuid(ItemOptionDefinitionNumbers.WizardRing, 4); + increaseMinWizBaseDamage.PowerUpDefinition = this.Context.CreateNew(); + increaseMinWizBaseDamage.PowerUpDefinition.TargetAttribute = Stats.MinimumWizBaseDmg.GetPersistent(this.GameConfiguration); + increaseMinWizBaseDamage.PowerUpDefinition.Boost = this.Context.CreateNew(); + increaseMinWizBaseDamage.PowerUpDefinition.Boost.ConstantValue.Value = 1.1f; + increaseMinWizBaseDamage.PowerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + optionDefinition.PossibleOptions.Add(increaseMinWizBaseDamage); + + var increaseMaxWizBaseDamage = this.Context.CreateNew(); + increaseMaxWizBaseDamage.SetGuid(ItemOptionDefinitionNumbers.WizardRing, 5); + increaseMaxWizBaseDamage.PowerUpDefinition = this.Context.CreateNew(); + increaseMaxWizBaseDamage.PowerUpDefinition.TargetAttribute = Stats.MaximumWizBaseDmg.GetPersistent(this.GameConfiguration); + increaseMaxWizBaseDamage.PowerUpDefinition.Boost = this.Context.CreateNew(); + increaseMaxWizBaseDamage.PowerUpDefinition.Boost.ConstantValue.Value = 1.1f; + increaseMaxWizBaseDamage.PowerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + optionDefinition.PossibleOptions.Add(increaseMaxWizBaseDamage); // Always add all options "randomly" when it drops ;) optionDefinition.AddChance = 1.0f; optionDefinition.AddsRandomly = true; - optionDefinition.MaximumOptionsPerItem = 3; + optionDefinition.MaximumOptionsPerItem = 5; } /// diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Pets.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Pets.cs index 9cb279d93..d8a4e0f39 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Pets.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Pets.cs @@ -7,6 +7,7 @@ namespace MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Items; using MUnique.OpenMU.AttributeSystem; +using MUnique.OpenMU.DataModel.Attributes; using MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.DataModel.Configuration.Items; using MUnique.OpenMU.GameLogic; @@ -35,13 +36,14 @@ public Pets(IContext context, GameConfiguration gameConfiguration) /// public override void Initialize() { - this.CreatePet(0, 0, 1, 1, "Guardian Angel", 23, true, true, (Stats.DamageReceiveDecrement, 0.8f, AggregateType.Multiplicate), (Stats.MaximumHealth, 50f, AggregateType.AddRaw)); - this.CreatePet(1, 0, 1, 1, "Imp", 28, true, true, (Stats.AttackDamageIncrease, 1.3f, AggregateType.Multiplicate)); + this.CreatePet(0, 0, 1, 1, "Guardian Angel", 23, true, true, (Stats.GuardianReceiveDecrement, 0.2f, AggregateType.AddRaw), (Stats.MaximumHealth, 50f, AggregateType.AddRaw)); + this.CreatePet(1, 0, 1, 1, "Imp", 28, true, true, (Stats.ImpAttackDamageIncrease, 0.3f, AggregateType.AddRaw, 0)); this.CreatePet(2, 0, 1, 1, "Horn of Uniria", 25, true, true); - var dinorant = this.CreatePet(3, SkillNumber.FireBreath, 1, 1, "Horn of Dinorant", 110, false, true, (Stats.DamageReceiveDecrement, 0.9f, AggregateType.Multiplicate), (Stats.AttackDamageIncrease, 1.15f, AggregateType.Multiplicate), (Stats.CanFly, 1.0f, AggregateType.AddRaw)); + var dinorant = this.CreatePet(3, SkillNumber.FireBreath, 1, 1, "Horn of Dinorant", 110, false, true, (Stats.IsDinorantEquipped, 1, AggregateType.AddRaw), (Stats.DamageReceiveDecrement, 0.9f, AggregateType.Multiplicate), (Stats.AttackDamageIncrease, 1.15f, AggregateType.Multiplicate)); this.AddDinorantOptions(dinorant); var darkHorse = this.CreatePet(4, SkillNumber.Earthshake, 1, 1, "Dark Horse", 218, false, false, (Stats.IsHorseEquipped, 1, AggregateType.AddRaw)); + this.AddDarkHorseOptions(darkHorse); this.GameConfiguration.DetermineCharacterClasses(CharacterClasses.AllLords).ForEach(darkHorse.QualifiedCharacters.Add); darkHorse.PetExperienceFormula = PetExperienceFormula; darkHorse.MaximumItemLevel = 50; @@ -52,15 +54,32 @@ public override void Initialize() darkRaven.MaximumItemLevel = 50; this.GameConfiguration.DetermineCharacterClasses(CharacterClasses.AllLords).ForEach(darkRaven.QualifiedCharacters.Add); - var fenrir = this.CreatePet(37, SkillNumber.PlasmaStorm, 2, 2, "Horn of Fenrir", 300, false, true, (Stats.CanFly, 1.0f, AggregateType.AddRaw)); + var fenrir = this.CreatePet(37, SkillNumber.PlasmaStorm, 2, 2, "Horn of Fenrir", 300, false, true, (Stats.CanFly, 1.0f, AggregateType.AddRaw, 0)); this.AddFenrirOptions(fenrir); - this.CreatePet(64, 0, 1, 1, "Demon", 1, false, true, (Stats.AttackDamageIncrease, 1.4f, AggregateType.Multiplicate), (Stats.AttackSpeed, 10f, AggregateType.AddRaw)); - this.CreatePet(65, 0, 1, 1, "Spirit of Guardian", 1, false, true, (Stats.DamageReceiveDecrement, 0.7f, AggregateType.Multiplicate), (Stats.MaximumHealth, 50f, AggregateType.AddRaw)); +#pragma warning disable SA1117 // Parameters should be on same line or separete lines + this.CreatePet(64, 0, 1, 1, "Demon", 1, false, true, + (Stats.MinimumPhysBaseDmg, 1.4f, AggregateType.Multiplicate, 1), + (Stats.MaximumPhysBaseDmg, 1.4f, AggregateType.Multiplicate, 1), + (Stats.MinimumWizBaseDmg, 1.4f, AggregateType.Multiplicate, 1), + (Stats.MaximumWizBaseDmg, 1.4f, AggregateType.Multiplicate, 1), + (Stats.MinimumCurseBaseDmg, 1.4f, AggregateType.Multiplicate, 1), + (Stats.MaximumCurseBaseDmg, 1.4f, AggregateType.Multiplicate, 1), + (Stats.AttackSpeedAny, 10f, AggregateType.AddRaw, 0)); + this.CreatePet(65, 0, 1, 1, "Spirit of Guardian", 1, false, true, (Stats.GuardianReceiveDecrement, 0.3f, AggregateType.AddRaw), (Stats.MaximumHealth, 50f, AggregateType.AddRaw)); this.CreatePet(67, 0, 1, 1, "Pet Rudolf", 28, false, true); - this.CreatePet(80, 0, 1, 1, "Pet Panda", 1, false, true, (Stats.ExperienceRate, 1.5f, AggregateType.Multiplicate), (Stats.MasterExperienceRate, 1.5f, AggregateType.Multiplicate), (Stats.DefenseBase, 50f, AggregateType.AddRaw)); - this.CreatePet(106, 0, 1, 1, "Pet Unicorn", 28, false, true, (Stats.MoneyAmountRate, 1.5f, AggregateType.Multiplicate), (Stats.DefenseBase, 50f, AggregateType.AddRaw)); - this.CreatePet(123, 0, 1, 1, "Pet Skeleton", 1, false, true, (Stats.AttackDamageIncrease, 1.2f, AggregateType.Multiplicate), (Stats.AttackSpeed, 10f, AggregateType.AddRaw), (Stats.ExperienceRate, 1.3f, AggregateType.Multiplicate)); + this.CreatePet(80, 0, 1, 1, "Pet Panda", 1, false, true, (Stats.ExperienceRate, 1.5f, AggregateType.Multiplicate, 0), (Stats.MasterExperienceRate, 1.5f, AggregateType.Multiplicate, 0), (Stats.DefenseBase, 50f, AggregateType.AddRaw, 2)); + this.CreatePet(106, 0, 1, 1, "Pet Unicorn", 28, false, true, (Stats.MoneyAmountRate, 1.5f, AggregateType.Multiplicate, 0), (Stats.DefenseBase, 50f, AggregateType.AddRaw, 2)); + this.CreatePet(123, 0, 1, 1, "Pet Skeleton", 1, false, true, + (Stats.MinimumPhysBaseDmg, 1.2f, AggregateType.Multiplicate), + (Stats.MaximumPhysBaseDmg, 1.2f, AggregateType.Multiplicate), + (Stats.MinimumWizBaseDmg, 1.2f, AggregateType.Multiplicate), + (Stats.MaximumWizBaseDmg, 1.2f, AggregateType.Multiplicate), + (Stats.MinimumCurseBaseDmg, 1.2f, AggregateType.Multiplicate), + (Stats.MaximumCurseBaseDmg, 1.2f, AggregateType.Multiplicate), + (Stats.AttackSpeedAny, 10f, AggregateType.AddRaw), + (Stats.ExperienceRate, 1.3f, AggregateType.Multiplicate)); +#pragma warning restore SA1011 // Items which are required for crafting: this.CreateSpirit(); @@ -172,7 +191,17 @@ private void CreateSpirit() BaseMapInitializer.RegisterDefaultDropItemGroup(ravenDrop); } + private ItemDefinition CreatePet(byte number, SkillNumber skillNumber, byte width, byte height, string name, int dropLevelAndLevelRequirement, bool dropsFromMonsters, bool addAllCharacterClasses) + { + return this.CreatePet(number, skillNumber, width, height, name, dropLevelAndLevelRequirement, dropsFromMonsters, addAllCharacterClasses, Array.Empty<(AttributeDefinition, float, AggregateType, byte)>()); + } + private ItemDefinition CreatePet(byte number, SkillNumber skillNumber, byte width, byte height, string name, int dropLevelAndLevelRequirement, bool dropsFromMonsters, bool addAllCharacterClasses, params (AttributeDefinition, float, AggregateType)[] basePowerUps) + { + return this.CreatePet(number, skillNumber, width, height, name, dropLevelAndLevelRequirement, dropsFromMonsters, addAllCharacterClasses, basePowerUps.Select(bpu => (bpu.Item1, bpu.Item2, bpu.Item3, (byte)0)).ToArray()); + } + + private ItemDefinition CreatePet(byte number, SkillNumber skillNumber, byte width, byte height, string name, int dropLevelAndLevelRequirement, bool dropsFromMonsters, bool addAllCharacterClasses, params (AttributeDefinition, float, AggregateType, byte)[] basePowerUps) { var pet = this.Context.CreateNew(); pet.SetGuid(13, number); @@ -206,6 +235,7 @@ private ItemDefinition CreatePet(byte number, SkillNumber skillNumber, byte widt powerUpDefinition.TargetAttribute = basePowerUp.Item1.GetPersistent(this.GameConfiguration); powerUpDefinition.BaseValue = basePowerUp.Item2; powerUpDefinition.AggregateType = basePowerUp.Item3; + powerUpDefinition.Stage = basePowerUp.Item4; pet.BasePowerUpAttributes.Add(powerUpDefinition); } } @@ -226,11 +256,25 @@ private void AddDinorantOptions(ItemDefinition dinorant) dinoOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.Option, 4, Stats.DamageReceiveDecrement, 0.95f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.Dino)); // Level 1 dinoOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.Option, 4, Stats.MaximumAbility, 50f, AggregateType.AddFinal, ItemOptionDefinitionNumbers.Dino)); // Level 2 - dinoOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.Option, 4, Stats.AttackSpeed, 5f, AggregateType.AddFinal, ItemOptionDefinitionNumbers.Dino)); // Level 4 + dinoOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.Option, 4, Stats.AttackSpeedAny, 5f, AggregateType.AddFinal, ItemOptionDefinitionNumbers.Dino)); // Level 4 dinorant.PossibleItemOptions.Add(dinoOptionDefinition); } + private void AddDarkHorseOptions(ItemDefinition horse) + { + var horseOptionDefinition = this.Context.CreateNew(); + horseOptionDefinition.SetGuid(ItemOptionDefinitionNumbers.Horse); + this.GameConfiguration.ItemOptions.Add(horseOptionDefinition); + + horseOptionDefinition.Name = "Dark Horse Options"; + + horseOptionDefinition.PossibleOptions.Add(this.CreateRelatedPetOption(ItemOptionTypes.DarkHorse, 1, Stats.DamageReceiveHorseDecrement, AggregateType.AddRaw, 0, ItemOptionDefinitionNumbers.Horse, -0.15f, (Stats.HorseLevel, -0.005f))); + horseOptionDefinition.PossibleOptions.Add(this.CreateRelatedPetOption(ItemOptionTypes.DarkHorse, 2, Stats.DefenseBase, AggregateType.AddRaw, 0, ItemOptionDefinitionNumbers.Horse, 5, (Stats.HorseLevel, 2), (Stats.TotalAgility, 1f / 20))); + + horse.PossibleItemOptions.Add(horseOptionDefinition); + } + /// /// Adds the fenrir options. /// @@ -246,13 +290,15 @@ private void AddFenrirOptions(ItemDefinition fenrir) fenrirOptionDefinition.Name = "Fenrir Options"; - fenrirOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.BlackFenrir, 1, Stats.AttackDamageIncrease, 1.1f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.Fenrir)); - fenrirOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.BlueFenrir, 2, Stats.DamageReceiveDecrement, 0.90f, AggregateType.Multiplicate, ItemOptionDefinitionNumbers.Fenrir)); + fenrirOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.BlackFenrir, 1, Stats.FenrirAttackDamageIncrease, 0.1f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.Fenrir)); + fenrirOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.BlueFenrir, 2, Stats.FenrirDamageReceiveDecrement, 0.1f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.Fenrir)); - fenrirOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.GoldFenrir, 4, Stats.MaximumHealth, 200f, AggregateType.AddFinal, ItemOptionDefinitionNumbers.Fenrir)); - fenrirOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.GoldFenrir, 4, Stats.MaximumMana, 200f, AggregateType.AddFinal, ItemOptionDefinitionNumbers.Fenrir)); - fenrirOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.GoldFenrir, 4, Stats.MaximumPhysBaseDmg, 33f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.Fenrir)); - fenrirOptionDefinition.PossibleOptions.Add(this.CreateOption(ItemOptionTypes.GoldFenrir, 4, Stats.MaximumWizBaseDmg, 16f, AggregateType.AddRaw, ItemOptionDefinitionNumbers.Fenrir)); + fenrirOptionDefinition.PossibleOptions.Add(this.CreateRelatedPetOption(ItemOptionTypes.GoldFenrir, 4, Stats.MaximumHealth, AggregateType.AddFinal, 0, ItemOptionDefinitionNumbers.Fenrir, 0, (Stats.TotalLevel, 0.5f))); + fenrirOptionDefinition.PossibleOptions.Add(this.CreateRelatedPetOption(ItemOptionTypes.GoldFenrir, 4, Stats.MaximumMana, AggregateType.AddFinal, 0, ItemOptionDefinitionNumbers.Fenrir, 0, (Stats.TotalLevel, 0.5f))); + fenrirOptionDefinition.PossibleOptions.Add(this.CreateRelatedPetOption(ItemOptionTypes.GoldFenrir, 4, Stats.MinimumPhysBaseDmg, AggregateType.AddRaw, 1, ItemOptionDefinitionNumbers.Fenrir, 0, (Stats.TotalLevel, 1f / 12f))); + fenrirOptionDefinition.PossibleOptions.Add(this.CreateRelatedPetOption(ItemOptionTypes.GoldFenrir, 4, Stats.MaximumPhysBaseDmg, AggregateType.AddRaw, 1, ItemOptionDefinitionNumbers.Fenrir, 0, (Stats.TotalLevel, 1f / 12f))); + fenrirOptionDefinition.PossibleOptions.Add(this.CreateRelatedPetOption(ItemOptionTypes.GoldFenrir, 4, Stats.MinimumWizBaseDmg, AggregateType.AddRaw, 1, ItemOptionDefinitionNumbers.Fenrir, 0, (Stats.TotalLevel, 1f / 25f))); + fenrirOptionDefinition.PossibleOptions.Add(this.CreateRelatedPetOption(ItemOptionTypes.GoldFenrir, 4, Stats.MaximumWizBaseDmg, AggregateType.AddRaw, 1, ItemOptionDefinitionNumbers.Fenrir, 0, (Stats.TotalLevel, 1f / 25f))); fenrir.PossibleItemOptions.Add(fenrirOptionDefinition); } @@ -266,4 +312,30 @@ private IncreasableItemOption CreateOption(ItemOptionType optionType, int number itemOption.PowerUpDefinition = this.CreatePowerUpDefinition(attributeDefinition, value, aggregateType); return itemOption; } + + private IncreasableItemOption CreateRelatedPetOption(ItemOptionType optionType, int number, AttributeDefinition targetAttribute, AggregateType aggregateType, byte stage, short optionNumber, float baseValue = 0, params (AttributeDefinition SourceAttribute, float Multiplier)[] relatedAttributes) + { + var itemOption = this.Context.CreateNew(); + itemOption.SetGuid(optionNumber, targetAttribute.Id.ExtractFirstTwoBytes()); + itemOption.OptionType = this.GameConfiguration.ItemOptionTypes.First(t => t == optionType); + itemOption.Number = number; + itemOption.PowerUpDefinition = this.Context.CreateNew(); + itemOption.PowerUpDefinition.TargetAttribute = targetAttribute.GetPersistent(this.GameConfiguration); + itemOption.PowerUpDefinition.Boost = this.Context.CreateNew(); + itemOption.PowerUpDefinition.Boost.ConstantValue.Value = baseValue; + itemOption.PowerUpDefinition.Boost.ConstantValue.AggregateType = aggregateType; + itemOption.PowerUpDefinition.Boost.ConstantValue.Stage = stage; + + for (int i = 0; i < relatedAttributes.Length; i++) + { + var attributeRelationship = this.Context.CreateNew(); + attributeRelationship.SetGuid(optionNumber, targetAttribute.Id.ExtractFirstTwoBytes(), (byte)i); + attributeRelationship.InputAttribute = relatedAttributes[i].SourceAttribute.GetPersistent(this.GameConfiguration); + attributeRelationship.InputOperator = InputOperator.Multiply; + attributeRelationship.InputOperand = relatedAttributes[i].Multiplier; + itemOption.PowerUpDefinition.Boost.RelatedValues.Add(attributeRelationship); + } + + return itemOption; + } } \ No newline at end of file diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Potions.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Potions.cs index 785b46fd7..11fa85cf5 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Potions.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Potions.cs @@ -421,7 +421,7 @@ private ItemDefinition CreateJackOLanternBlessings() item.Width = 1; item.Height = 2; item.SetGuid(item.Group, item.Number); - this.CreateConsumeEffect(item, 16, MagicEffectNumber.JackOlanternBlessing, TimeSpan.FromMinutes(32), (Stats.AttackSpeed, 10), (Stats.MagicSpeed, 10)); + this.CreateConsumeEffect(item, 16, MagicEffectNumber.JackOlanternBlessing, TimeSpan.FromMinutes(32), (Stats.AttackSpeedAny, 10)); return item; } @@ -449,7 +449,7 @@ private ItemDefinition CreateJackOLanternCry() item.Width = 1; item.Height = 2; item.SetGuid(item.Group, item.Number); - this.CreateConsumeEffect(item, 16, MagicEffectNumber.JackOlanternCry, TimeSpan.FromMinutes(30), (Stats.DefenseBase, 100)); + this.CreateConsumeEffect(item, 16, MagicEffectNumber.JackOlanternCry, TimeSpan.FromMinutes(30), (Stats.DefenseBase, 100 / 2, 3)); return item; } @@ -524,6 +524,11 @@ private ItemDefinition CreateCherryBlossomFlowerPetal() } private MagicEffectDefinition CreateConsumeEffect(ItemDefinition item, byte subType, MagicEffectNumber effectNumber, TimeSpan duration, params (AttributeDefinition targetAttribute, float boostValue)[] boosts) + { + return this.CreateConsumeEffect(item, subType, effectNumber, duration, boosts.Select(b => (b.targetAttribute, b.boostValue, (byte)0)).ToArray()); + } + + private MagicEffectDefinition CreateConsumeEffect(ItemDefinition item, byte subType, MagicEffectNumber effectNumber, TimeSpan duration, params (AttributeDefinition targetAttribute, float boostValue, byte stage)[] boosts) { var effect = this.Context.CreateNew(); effect.SetGuid(item.Number, (short)effectNumber); @@ -538,12 +543,13 @@ private MagicEffectDefinition CreateConsumeEffect(ItemDefinition item, byte subT effect.Duration = this.Context.CreateNew(); effect.Duration.ConstantValue.Value = (float)duration.TotalSeconds; - foreach (var (targetAttribute, boostValue) in boosts) + foreach (var (targetAttribute, boostValue, stage) in boosts) { var powerUpDefinition = this.Context.CreateNew(); effect.PowerUpDefinitions.Add(powerUpDefinition); powerUpDefinition.Boost = this.Context.CreateNew(); powerUpDefinition.Boost.ConstantValue.Value = boostValue; + powerUpDefinition.Boost.ConstantValue.Stage = stage; powerUpDefinition.TargetAttribute = targetAttribute.GetPersistent(this.GameConfiguration); } diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/SocketSystem.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/SocketSystem.cs index eb98f91e2..12a3c6797 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/SocketSystem.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/SocketSystem.cs @@ -279,11 +279,11 @@ private ItemOptionDefinition CreateFireOptions() definition.MaximumOptionsPerItem = 1; definition.PossibleOptions.Add(this.CreateRelatedSocketOption(0, SocketSubOptionType.Fire, Stats.MaximumPhysBaseDmg, Stats.Level, 1f / 20f, 1f / 19f, 1f / 18f, 1f / 17f, 1f / 14f)); - definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Fire, Stats.AttackSpeed, AggregateType.AddRaw, 7, 8, 9, 10, 11)); - definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Fire, Stats.BaseMaxDamageBonus, AggregateType.AddRaw, 30, 32, 35, 40, 50)); - definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Fire, Stats.BaseMinDamageBonus, AggregateType.AddRaw, 20, 22, 25, 30, 35)); - definition.PossibleOptions.Add(this.CreateSocketOption(4, SocketSubOptionType.Fire, Stats.BaseDamageBonus, AggregateType.AddRaw, 20, 22, 25, 30, 35)); - definition.PossibleOptions.Add(this.CreateSocketOption(5, SocketSubOptionType.Fire, Stats.AbilityUsageReduction, AggregateType.AddRaw, 0.40f, 0.41f, 0.42f, 0.43f, 0.44f)); + definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Fire, Stats.AttackSpeedAny, AggregateType.AddRaw, 0, 7, 8, 9, 10, 11)); + definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Fire, Stats.SocketBaseMaxDmgBonus, AggregateType.AddRaw, 0, 30, 32, 35, 40, 50)); + definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Fire, Stats.SocketBaseMinDmgBonus, AggregateType.AddRaw, 0, 20, 22, 25, 30, 35)); + definition.PossibleOptions.Add(this.CreateSocketOption(4, SocketSubOptionType.Fire, Stats.SocketBaseDmgBonus, AggregateType.AddRaw, 0, 20, 22, 25, 30, 35)); + definition.PossibleOptions.Add(this.CreateSocketOption(5, SocketSubOptionType.Fire, Stats.AbilityUsageReduction, AggregateType.AddRaw, 0, 0.40f, 0.41f, 0.42f, 0.43f, 0.44f)); return definition; } @@ -295,11 +295,11 @@ private ItemOptionDefinition CreateIceOptions() definition.Name = "Socket Options (Ice)"; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Ice, Stats.HealthAfterMonsterKillMultiplier, AggregateType.AddRaw, 1f / 8f, 1f / 7f, 1f / 6f, 1f / 5f, 1f / 4f)); - definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Ice, Stats.ManaAfterMonsterKillMultiplier, AggregateType.AddRaw, 1f / 8f, 1f / 7f, 1f / 6f, 1f / 5f, 1f / 4f)); - definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Ice, Stats.SkillDamageBonus, AggregateType.AddRaw, 37, 40, 45, 50, 60)); - definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Ice, Stats.AttackRatePvm, AggregateType.AddRaw, 25, 27, 30, 35, 40)); - definition.PossibleOptions.Add(this.CreateSocketOption(4, SocketSubOptionType.Ice, Stats.ItemDurationIncrease, AggregateType.Multiplicate, 1.30f, 1.32f, 1.34f, 1.36f, 1.38f)); + definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Ice, Stats.HealthAfterMonsterKillMultiplier, AggregateType.AddRaw, 0, 1f / 8f, 1f / 7f, 1f / 6f, 1f / 5f, 1f / 4f)); + definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Ice, Stats.ManaAfterMonsterKillMultiplier, AggregateType.AddRaw, 0, 1f / 8f, 1f / 7f, 1f / 6f, 1f / 5f, 1f / 4f)); + definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Ice, Stats.SkillDamageBonus, AggregateType.AddRaw, 0, 37, 40, 45, 50, 60)); + definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Ice, Stats.AttackRatePvm, AggregateType.AddRaw, 0, 25, 27, 30, 35, 40)); + definition.PossibleOptions.Add(this.CreateSocketOption(4, SocketSubOptionType.Ice, Stats.ItemDurationIncrease, AggregateType.Multiplicate, 0, 1.30f, 1.32f, 1.34f, 1.36f, 1.38f)); return definition; } @@ -311,10 +311,10 @@ private ItemOptionDefinition CreateLightningOptions() definition.Name = "Socket Options (Lightning)"; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Lightning, Stats.ExcellentDamageBonus, AggregateType.AddRaw, 15, 20, 25, 30, 40)); - definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Lightning, Stats.ExcellentDamageChance, AggregateType.AddRaw, 0.10f, 0.11f, 0.12f, 0.13f, 0.14f)); - definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Lightning, Stats.CriticalDamageBonus, AggregateType.AddRaw, 15, 20, 25, 30, 40)); - definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Lightning, Stats.CriticalDamageChance, AggregateType.AddRaw, 0.08f, 0.09f, 0.10f, 0.11f, 0.12f)); + definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Lightning, Stats.ExcellentDamageBonus, AggregateType.AddRaw, 0, 15, 20, 25, 30, 40)); + definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Lightning, Stats.ExcellentDamageChance, AggregateType.AddRaw, 0, 0.10f, 0.11f, 0.12f, 0.13f, 0.14f)); + definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Lightning, Stats.CriticalDamageBonus, AggregateType.AddRaw, 0, 15, 20, 25, 30, 40)); + definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Lightning, Stats.CriticalDamageChance, AggregateType.AddRaw, 0, 0.08f, 0.09f, 0.10f, 0.11f, 0.12f)); return definition; } @@ -326,12 +326,12 @@ private ItemOptionDefinition CreateWindOptions() definition.Name = "Socket Options (Wind)"; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Wind, Stats.HealthRecoveryAbsolute, AggregateType.AddRaw, 8, 10, 13, 16, 20)); - definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Wind, Stats.MaximumHealth, AggregateType.Multiplicate, 1.04f, 1.05f, 1.06f, 1.07f, 1.08f)); - definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Wind, Stats.MaximumMana, AggregateType.Multiplicate, 1.04f, 1.05f, 1.06f, 1.07f, 1.08f)); - definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Wind, Stats.ManaRecoveryAbsolute, AggregateType.AddRaw, 7, 14, 21, 28, 35)); - definition.PossibleOptions.Add(this.CreateSocketOption(4, SocketSubOptionType.Wind, Stats.MaximumAbility, AggregateType.AddRaw, 25, 30, 35, 40, 50)); - definition.PossibleOptions.Add(this.CreateSocketOption(5, SocketSubOptionType.Wind, Stats.AbilityRecoveryAbsolute, AggregateType.AddRaw, 3, 5, 7, 10, 15)); + definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Wind, Stats.HealthRecoveryAbsolute, AggregateType.AddRaw, 0, 8, 10, 13, 16, 20)); + definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Wind, Stats.MaximumHealth, AggregateType.Multiplicate, 0, 1.04f, 1.05f, 1.06f, 1.07f, 1.08f)); + definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Wind, Stats.MaximumMana, AggregateType.Multiplicate, 0, 1.04f, 1.05f, 1.06f, 1.07f, 1.08f)); + definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Wind, Stats.ManaRecoveryAbsolute, AggregateType.AddRaw, 0, 7, 14, 21, 28, 35)); + definition.PossibleOptions.Add(this.CreateSocketOption(4, SocketSubOptionType.Wind, Stats.MaximumAbility, AggregateType.AddRaw, 0, 25, 30, 35, 40, 50)); + definition.PossibleOptions.Add(this.CreateSocketOption(5, SocketSubOptionType.Wind, Stats.AbilityRecoveryAbsolute, AggregateType.AddRaw, 0, 3, 5, 7, 10, 15)); return definition; } @@ -343,11 +343,11 @@ private ItemOptionDefinition CreateWaterOptions() definition.Name = "Socket Options (Water)"; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Water, Stats.DefenseRatePvm, AggregateType.Multiplicate, 1.10f, 1.11f, 1.12f, 1.13f, 1.14f)); - definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Water, Stats.DefenseBase, AggregateType.AddRaw, 30, 33, 36, 39, 42)); - definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Water, Stats.ShieldDecreaseRateIncrease, AggregateType.AddRaw, 0.07f, 0.10f, 0.15f, 0.20f, 0.30f)); - definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Water, Stats.DamageReceiveDecrement, AggregateType.Multiplicate, 0.96f, 0.95f, 0.94f, 0.93f, 0.92f)); - definition.PossibleOptions.Add(this.CreateSocketOption(4, SocketSubOptionType.Water, Stats.DamageReflection, AggregateType.AddRaw, 0.05f, 0.06f, 0.07f, 0.08f, 0.09f)); + definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Water, Stats.DefenseRatePvm, AggregateType.Multiplicate, 0, 1.10f, 1.11f, 1.12f, 1.13f, 1.14f)); + definition.PossibleOptions.Add(this.CreateSocketOption(1, SocketSubOptionType.Water, Stats.DefenseBase, AggregateType.AddRaw, 2, 30, 33, 36, 39, 42)); + definition.PossibleOptions.Add(this.CreateSocketOption(2, SocketSubOptionType.Water, Stats.DefenseIncreaseWithEquippedShield, AggregateType.AddRaw, 0, 0.07f, 0.10f, 0.15f, 0.20f, 0.30f)); + definition.PossibleOptions.Add(this.CreateSocketOption(3, SocketSubOptionType.Water, Stats.ArmorDamageDecrease, AggregateType.AddRaw, 0, 0.04f, 0.05f, 0.06f, 0.07f, 0.08f)); + definition.PossibleOptions.Add(this.CreateSocketOption(4, SocketSubOptionType.Water, Stats.DamageReflection, AggregateType.AddRaw, 0, 0.05f, 0.06f, 0.07f, 0.08f, 0.09f)); return definition; } @@ -359,7 +359,7 @@ private ItemOptionDefinition CreateEarthOptions() definition.Name = "Socket Options (Earth)"; definition.MaximumOptionsPerItem = 1; - definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Earth, Stats.MaximumHealth, AggregateType.AddRaw, 30, 32, 34, 36, 38)); + definition.PossibleOptions.Add(this.CreateSocketOption(0, SocketSubOptionType.Earth, Stats.MaximumHealth, AggregateType.AddRaw, 0, 30, 32, 34, 36, 38)); return definition; } @@ -371,7 +371,7 @@ private ItemOptionDefinition CreateBonusOptionForPhysicalWeapons() definition.Name = "Socket Bonus Options (Physical)"; definition.MaximumOptionsPerItem = 1; definition.AddChance = 0.30f; - definition.PossibleOptions.Add(this.CreateSocketBonusOption(0, Stats.BaseDamageBonus, 11)); + definition.PossibleOptions.Add(this.CreateSocketBonusOption(0, Stats.SocketBaseDmgBonus, 11)); definition.PossibleOptions.Add(this.CreateSocketBonusOption(1, Stats.SkillDamageBonus, 11)); return definition; } @@ -384,7 +384,7 @@ private ItemOptionDefinition CreateBonusOptionForStaffs() definition.Name = "Socket Bonus Options (Wizardry)"; definition.MaximumOptionsPerItem = 1; definition.AddChance = 0.30f; - definition.PossibleOptions.Add(this.CreateSocketBonusOption(2, Stats.BaseDamageBonus, 5)); + definition.PossibleOptions.Add(this.CreateSocketBonusOption(2, Stats.SocketBaseDmgBonus, 5)); definition.PossibleOptions.Add(this.CreateSocketBonusOption(3, Stats.SkillDamageBonus, 11)); return definition; } @@ -419,7 +419,7 @@ private IncreasableItemOption CreateSocketBonusOption(short number, AttributeDef return itemOption; } - private IncreasableItemOption CreateSocketOption(short number, SocketSubOptionType subOptionType, AttributeDefinition attributeDefinition, AggregateType aggregateType, params float[] values) + private IncreasableItemOption CreateSocketOption(short number, SocketSubOptionType subOptionType, AttributeDefinition attributeDefinition, AggregateType aggregateType, byte stage, params float[] values) { var itemOption = this.Context.CreateNew(); itemOption.SetGuid((short)(ItemOptionDefinitionNumbers.SocketFire + subOptionType), number); @@ -436,6 +436,7 @@ private IncreasableItemOption CreateSocketOption(short number, SocketSubOptionTy powerUpDefinition.Boost = this.Context.CreateNew(); powerUpDefinition.Boost.ConstantValue.Value = value; powerUpDefinition.Boost.ConstantValue.AggregateType = aggregateType; + powerUpDefinition.Boost.ConstantValue.Stage = stage; optionOfLevel.PowerUpDefinition = powerUpDefinition; itemOption.LevelDependentOptions.Add(optionOfLevel); if (optionOfLevel.Level == 1) diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs index a65b13dbe..37eda6c17 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs @@ -7,6 +7,7 @@ namespace MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Items; using MUnique.OpenMU.AttributeSystem; using MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.DataModel.Configuration.Items; +using MUnique.OpenMU.GameLogic; using MUnique.OpenMU.GameLogic.Attributes; using MUnique.OpenMU.Persistence.Initialization.CharacterClasses; using MUnique.OpenMU.Persistence.Initialization.Items; @@ -38,7 +39,10 @@ internal class Weapons : InitializerBase private static readonly float[] ScepterRiseIncreaseByLevelEven = { 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 18, 21, 24, 28, 33 }; // Scepter with even magic power private static readonly float[] ScepterRiseIncreaseByLevelOdd = { 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 18, 21, 25, 29, 33 }; // Scepter with odd magic power + private static readonly float[] AmmunitionDamageIncreaseByLevel = { 0, 0.03f, 0.05f, 0.1f }; // Bolts/Arrows + private ItemLevelBonusTable? _weaponDamageIncreaseTable; + private ItemLevelBonusTable? _staffDamageIncreaseTable; private ItemLevelBonusTable? _staffRiseTableEven; private ItemLevelBonusTable? _staffRiseTableOdd; @@ -46,6 +50,8 @@ internal class Weapons : InitializerBase private ItemLevelBonusTable? _scepterRiseTableEven; private ItemLevelBonusTable? _scepterRiseTableOdd; + private ItemLevelBonusTable? _ammunitionDamageIncreaseTable; + /// /// Initializes a new instance of the class. /// @@ -74,7 +80,7 @@ protected ItemOptionDefinition PhysicalDamageOption { get { - return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumPhysBaseDmg)); + return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.PhysicalBaseDmg)); } } @@ -85,7 +91,7 @@ protected ItemOptionDefinition WizardryDamageOption { get { - return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumWizBaseDmg)); + return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.WizardryBaseDmg)); } } @@ -96,7 +102,7 @@ protected ItemOptionDefinition CurseDamageOption { get { - return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumCurseBaseDmg)); + return this.GameConfiguration.ItemOptions.First(iod => iod.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.CurseBaseDmg)); } } @@ -110,10 +116,12 @@ protected ItemOptionDefinition CurseDamageOption public override void Initialize() { this._weaponDamageIncreaseTable = this.CreateItemBonusTable(DamageIncreaseByLevel, "Damage Increase (Weapons)", "The damage increase by weapon level. It increases by 3 per level, and 1 more after level 10."); + this._staffDamageIncreaseTable = this.CreateItemBonusTable([.. DamageIncreaseByLevel.Select(dmg => dmg /= 2.0f)], "Damage Increase (Staffs/Sticks)", "The damage increase by staff/stick level. It's half of the physical weapons."); this._staffRiseTableEven = this.CreateItemBonusTable(StaffRiseIncreaseByLevelEven, "Staff Rise (even)", "The staff rise bonus per item level for even magic power staves."); this._staffRiseTableOdd = this.CreateItemBonusTable(StaffRiseIncreaseByLevelOdd, "Staff Rise (odd)", "The staff rise bonus per item level for odd magic power staves."); this._scepterRiseTableEven = this.CreateItemBonusTable(ScepterRiseIncreaseByLevelEven, "Scepter Rise (even)", "The scepter rise bonus per item level for even magic power scepters."); this._scepterRiseTableOdd = this.CreateItemBonusTable(ScepterRiseIncreaseByLevelOdd, "Scepter Rise (odd)", "The scepter rise bonus per item level for odd magic power scepters."); + this._ammunitionDamageIncreaseTable = this.CreateItemBonusTable(AmmunitionDamageIncreaseByLevel, "Damage Increase % (Bolts/Arrows)", "The damage increase % per ammunition item level."); this.CreateWeapon(0, 0, 0, 0, 1, 2, true, "Kris", 6, 6, 11, 50, 20, 0, 0, 40, 40, 0, 0, 1, 1, 1, 1, 1, 1, 1); this.CreateWeapon(0, 1, 0, 0, 1, 3, true, "Short Sword", 3, 3, 7, 20, 22, 0, 0, 60, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1); @@ -134,7 +142,7 @@ public override void Initialize() this.CreateWeapon(0, 16, 0, 22, 1, 4, true, "Sword of Destruction", 82, 82, 90, 35, 84, 0, 0, 160, 60, 0, 0, 0, 1, 0, 1, 0, 0, 0); this.CreateWeapon(0, 17, 0, 23, 2, 4, true, "Dark Breaker", 104, 128, 153, 40, 89, 0, 0, 180, 50, 0, 0, 0, 2, 0, 0, 0, 0, 0); this.CreateWeapon(0, 18, 0, 23, 2, 3, true, "Thunder Blade", 105, 140, 168, 40, 86, 0, 0, 180, 50, 0, 0, 0, 0, 0, 1, 0, 0, 0); - this.CreateWeapon(0, 19, 0, 22, 1, 4, false, "Divine Sword of Archangel", 86, 120, 130, 35, 168, 0, 0, 140, 50, 0, 0, 0, 1, 0, 1, 1, 0, 0); + this.CreateWeapon(0, 19, 0, 22, 1, 4, false, "Divine Sword of Archangel", 86, 220, 230, 45, 168, 0, 0, 140, 50, 0, 0, 0, 1, 0, 1, 1, 0, 0); this.CreateWeapon(0, 20, 0, 22, 1, 4, true, "Knight Blade", 140, 107, 115, 35, 90, 0, 0, 116, 38, 0, 0, 0, 2, 0, 0, 0, 0, 0); this.CreateWeapon(0, 21, 0, 56, 2, 4, true, "Dark Reign Blade", 140, 115, 142, 40, 100, 115, 0, 116, 53, 9, 0, 0, 0, 0, 1, 0, 0, 0); this.CreateWeapon(0, 22, 0, 22, 1, 4, true, "Bone Blade", 147, 122, 135, 40, 95, 0, 380, 100, 35, 0, 0, 0, 2, 0, 0, 0, 0, 0); @@ -173,7 +181,7 @@ public override void Initialize() this.CreateWeapon(2, 10, 0, 66, 1, 4, true, "Great Scepter", 82, 74, 85, 45, 65, 35, 0, 100, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0); this.CreateWeapon(2, 11, 0, 66, 1, 4, true, "Lord Scepter", 98, 91, 102, 40, 72, 52, 0, 105, 23, 0, 0, 0, 0, 0, 0, 1, 0, 0); this.CreateWeapon(2, 12, 0, 66, 1, 4, true, "Great Lord Scepter", 140, 108, 120, 40, 84, 67, 0, 90, 20, 0, 0, 0, 0, 0, 0, 1, 0, 0); - this.CreateWeapon(2, 13, 0, 66, 1, 4, false, "Divine Scepter of Archangel", 150, 120, 143, 45, 90, 78, 0, 75, 16, 0, 0, 0, 0, 0, 0, 1, 0, 0); + this.CreateWeapon(2, 13, 0, 66, 1, 4, false, "Divine Scepter of Archangel", 150, 200, 233, 45, 90, 138, 0, 75, 16, 0, 0, 0, 0, 0, 0, 1, 0, 0); this.CreateWeapon(2, 14, 0, 66, 1, 4, true, "Soleil Scepter", 146, 130, 153, 40, 95, 84, 380, 80, 15, 0, 0, 0, 0, 0, 0, 1, 0, 0); this.CreateWeapon(2, 15, 0, 66, 1, 4, true, "Shining Scepter", 110, 99, 111, 40, 78, 60, 0, 108, 22, 0, 0, 0, 0, 0, 0, 1, 0, 0); this.CreateWeapon(2, 16, 0, 0, 1, 3, true, "Frost Mace", 121, 106, 146, 50, 80, 0, 0, 27, 19, 0, 0, 0, 0, 2, 0, 0, 0, 0); @@ -212,7 +220,7 @@ public override void Initialize() this.CreateWeapon(4, 15, 0, 0, 1, 1, false, "Arrows", 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0); this.CreateWeapon(4, 16, 0, 24, 2, 4, true, "Saint Crossbow", 84, 102, 127, 35, 72, 0, 0, 50, 160, 0, 0, 0, 0, 1, 0, 0, 0, 0); this.CreateWeapon(4, 17, 1, 24, 2, 4, true, "Celestial Bow", 92, 127, 155, 35, 76, 0, 0, 54, 198, 0, 0, 0, 0, 2, 0, 0, 0, 0); - this.CreateWeapon(4, 18, 0, 24, 2, 3, false, "Divine Crossbow of Archangel", 100, 144, 166, 35, 200, 0, 0, 40, 110, 0, 0, 0, 0, 1, 0, 0, 0, 0); + this.CreateWeapon(4, 18, 0, 24, 2, 3, false, "Divine Crossbow of Archangel", 100, 224, 246, 45, 200, 0, 0, 40, 110, 0, 0, 0, 0, 1, 0, 0, 0, 0); this.CreateWeapon(4, 19, 0, 24, 2, 3, true, "Great Reign Crossbow", 100, 150, 172, 40, 80, 0, 0, 61, 285, 0, 0, 0, 0, 2, 0, 0, 0, 0); this.CreateWeapon(4, 20, 1, 24, 2, 4, true, "Arrow Viper Bow", 135, 166, 190, 45, 86, 0, 0, 52, 245, 0, 0, 0, 0, 2, 0, 0, 0, 0); this.CreateWeapon(4, 21, 1, 24, 2, 4, true, "Sylph Wind Bow", 147, 177, 200, 45, 93, 0, 380, 46, 210, 0, 0, 0, 0, 2, 0, 0, 0, 0); @@ -300,7 +308,7 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.MaximumItemLevel = MaximumItemLevel; item.DropsFromMonsters = dropsFromMonsters; item.SetGuid(item.Group, item.Number); - if (slot == 0 && knightClass > 0 && width == 1) + if (slot == 0 && (knightClass > 0 || magicGladiatorClass > 0) && width == 1) { item.ItemSlot = this.GameConfiguration.ItemSlotTypes.First(t => t.ItemSlots.Contains(0) && t.ItemSlots.Contains(1)); } @@ -319,14 +327,27 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber var qualifiedCharacterClasses = this.GameConfiguration.DetermineCharacterClasses(wizardClass, knightClass, elfClass, magicGladiatorClass, darkLordClass, summonerClass, ragefighterClass); qualifiedCharacterClasses.ToList().ForEach(item.QualifiedCharacters.Add); + if (height == 1) // bolts and arrows + { + var damagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.AmmunitionDamageBonus, 0f, AggregateType.AddRaw); + damagePowerUp.BonusPerLevelTable = this._ammunitionDamageIncreaseTable; + item.BasePowerUpAttributes.Add(damagePowerUp); + + item.IsAmmunition = true; + return; + } + if (minimumDamage > 0) { - var minDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MinimumPhysBaseDmgByWeapon, minimumDamage, AggregateType.AddRaw); - minDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; + var dmgDivider = group == (int)ItemGroups.Staff ? 2.0f : 1.0f; + var bonusPerLevelTable = group == (int)ItemGroups.Staff ? this._staffDamageIncreaseTable : this._weaponDamageIncreaseTable; + + var minDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MinimumPhysBaseDmgByWeapon, minimumDamage / dmgDivider, AggregateType.AddRaw); + minDamagePowerUp.BonusPerLevelTable = bonusPerLevelTable; item.BasePowerUpAttributes.Add(minDamagePowerUp); - var maxDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MaximumPhysBaseDmgByWeapon, maximumDamage, AggregateType.AddRaw); - maxDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; + var maxDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MaximumPhysBaseDmgByWeapon, maximumDamage / dmgDivider, AggregateType.AddRaw); + maxDamagePowerUp.BonusPerLevelTable = bonusPerLevelTable; item.BasePowerUpAttributes.Add(maxDamagePowerUp); } @@ -341,18 +362,30 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.PossibleItemOptions.Add(this.Luck); - if (magicPower == 0 || darkLordClass > 0) + if (magicPower == 0 || darkLordClass > 0 || group == (int)ItemGroups.Swords) { item.PossibleItemOptions.Add(this.PhysicalDamageOption); item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == ExcellentOptions.PhysicalAttackOptionsName)); item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == HarmonyOptions.PhysicalAttackOptionsName)); - if (darkLordClass > 0) + if (darkLordClass > 0 && skillNumber == 66) { var scepterRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.ScepterRise, magicPower / 2.0f, AggregateType.AddRaw); scepterRisePowerUp.BonusPerLevelTable = magicPower % 2 == 0 ? this._scepterRiseTableEven : this._scepterRiseTableOdd; item.BasePowerUpAttributes.Add(scepterRisePowerUp); } + else if (magicPower > 0) // MG swords can have wizardry rise, functioning as both sword and staff + { + item.PossibleItemOptions.Add(this.WizardryDamageOption); + + var swordRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.StaffRise, magicPower / 2.0f, AggregateType.AddRaw); + swordRisePowerUp.BonusPerLevelTable = magicPower % 2 == 0 ? this._staffRiseTableEven : this._staffRiseTableOdd; + item.BasePowerUpAttributes.Add(swordRisePowerUp); + } + else + { + // Nothing to do here + } } else { @@ -377,26 +410,27 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber } } - if (height > 1) // exclude bolts and arrows + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.EquippedWeaponCount, 1, AggregateType.AddRaw)); + + if (group < (int)ItemGroups.Spears && width == 1) { - item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.EquippedWeaponCount, 1, AggregateType.AddRaw)); + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.DoubleWieldWeaponCount, 1, AggregateType.AddRaw)); } - if (group == (int)ItemGroups.Bows && height > 1) + if (group == (int)ItemGroups.Bows) { item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.AmmunitionConsumptionRate, 1, AggregateType.AddRaw)); + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(slot == 0 ? Stats.IsCrossBowEquipped : Stats.IsBowEquipped, 1, AggregateType.AddRaw)); } - item.IsAmmunition = group == (int)ItemGroups.Bows && height == 1; - - if (group != (int)ItemGroups.Bows && width == 2) + if (group != (int)ItemGroups.Bows && group != (int)ItemGroups.Staff && width == 2) { item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.IsTwoHandedWeaponEquipped, 1, AggregateType.AddRaw)); } - if (group == (int)ItemGroups.Swords) + if (group == (int)ItemGroups.Swords || (group == (int)ItemGroups.Scepters && number == 5)) // Crystal Sword { - if (ragefighterClass == 0 || number < 3) + if (ragefighterClass == 0 || number < 2) { if (width == 1) { @@ -440,20 +474,15 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber { item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.IsStickEquipped, 1, AggregateType.AddRaw)); } - else if (wizardClass == 1) + else if (wizardClass > 0) { item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(width == 1 ? Stats.IsOneHandedStaffEquipped : Stats.IsTwoHandedStaffEquipped, 1, AggregateType.AddRaw)); } else { - // It's a book. Nothing to do here. + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.IsBookEquipped, 1, AggregateType.AddRaw)); } } - - if (group == (int)ItemGroups.Bows && !item.IsAmmunition) - { - item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(slot == 0 ? Stats.IsCrossBowEquipped : Stats.IsBowEquipped, 1, AggregateType.AddRaw)); - } } private void AddGuardianOptions() diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Wings.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Wings.cs index 846bb7c03..8f4e31980 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Wings.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Wings.cs @@ -215,7 +215,7 @@ private ItemDefinition CreateWing(byte number, byte width, byte height, string n { var powerUp = this.CreateItemBasePowerUpDefinition(Stats.DefenseBase, defense, AggregateType.AddRaw); wing.BasePowerUpAttributes.Add(powerUp); - powerUp.BonusPerLevelTable = levelRequirement == 300 ? this._defenseBonusByLevelTableThird : this._defenseBonusByLevelTable; + powerUp.BonusPerLevelTable = levelRequirement == 400 ? this._defenseBonusByLevelTableThird : this._defenseBonusByLevelTable; } var classes = this.GameConfiguration.DetermineCharacterClasses(darkWizardClassLevel, darkKnightClassLevel, elfClassLevel, magicGladiatorClassLevel, darkLordClassLevel, summonerClassLevel, ragefighterClassLevel); diff --git a/src/Persistence/Initialization/VersionSeasonSix/Maps/RaklionBoss.cs b/src/Persistence/Initialization/VersionSeasonSix/Maps/RaklionBoss.cs index 2f19c5fc7..5b6939b25 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Maps/RaklionBoss.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Maps/RaklionBoss.cs @@ -109,9 +109,12 @@ protected override void CreateMonsters() { Stats.IceResistance, 254f / 255 }, { Stats.WaterResistance, 150f / 255 }, { Stats.FireResistance, 150f / 255 }, + { Stats.SkillMultiplier, 2 }, }; monster.AddAttributes(attributes, this.Context, this.GameConfiguration); monster.SetGuid(monster.Number); + + // TODO: Selupan appears to have 4 different types of skill attacks, which have damage multipliers and magic effects. } { diff --git a/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs b/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs index 2e288927e..7cca6e9e6 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs @@ -60,12 +60,13 @@ internal class SkillsInitializer : SkillsInitializerBase { SkillNumber.Heal, MagicEffectNumber.Heal }, { SkillNumber.Recovery, MagicEffectNumber.ShieldRecover }, { SkillNumber.InfinityArrow, MagicEffectNumber.InfiniteArrow }, - { SkillNumber.InfinityArrowStr, MagicEffectNumber.InfiniteArrow }, { SkillNumber.FireSlash, MagicEffectNumber.DefenseReduction }, { SkillNumber.IgnoreDefense, MagicEffectNumber.IgnoreDefense }, { SkillNumber.IncreaseHealth, MagicEffectNumber.IncreaseHealth }, { SkillNumber.IncreaseBlock, MagicEffectNumber.IncreaseBlock }, { SkillNumber.ExpansionofWizardry, MagicEffectNumber.WizEnhance }, + { SkillNumber.Berserker, MagicEffectNumber.Berserker }, + { SkillNumber.KillingBlow, MagicEffectNumber.Weakness }, }; private readonly IDictionary _masterSkillRoots; @@ -139,7 +140,7 @@ public override void Initialize() this.CreateSkill(SkillNumber.RagefulBlow, "Rageful Blow", CharacterClasses.BladeKnightAndBladeMaster, DamageType.Physical, 60, 3, 20, 25, 170, elementalModifier: ElementalType.Earth, skillType: SkillType.AreaSkillAutomaticHits); this.CreateSkill(SkillNumber.DeathStab, "Death Stab", CharacterClasses.BladeKnightAndBladeMaster, DamageType.Physical, 70, 2, 12, 15, 160, elementalModifier: ElementalType.Wind, skillType: SkillType.DirectHit, skillTarget: SkillTarget.ExplicitWithImplicitInRange, implicitTargetRange: 1); this.CreateSkill(SkillNumber.CrescentMoonSlash, "Crescent Moon Slash", CharacterClasses.AllKnights, DamageType.Physical, 90, 4, 15, 22, movesToTarget: true, movesTarget: true); - this.CreateSkill(SkillNumber.Lance, "Lance", CharacterClasses.SoulMasterAndGrandMaster | CharacterClasses.AllSummoners, DamageType.All, 90, 6, 10, 150); + this.CreateSkill(SkillNumber.Lance, "Lance", CharacterClasses.SoulMasterAndGrandMaster | CharacterClasses.AllSummoners, DamageType.Wizardry, 90, 6, 10, 150); this.CreateSkill(SkillNumber.Starfall, "Starfall", CharacterClasses.AllElfs, DamageType.Physical, 120, 8, 15, 20); this.CreateSkill(SkillNumber.Impale, "Impale", CharacterClasses.AllKnights | CharacterClasses.AllMGs, DamageType.Physical, 15, 3, manaConsumption: 8, levelRequirement: 28); this.CreateSkill(SkillNumber.SwellLife, "Swell Life", CharacterClasses.AllKnights, abilityConsumption: 24, manaConsumption: 22, levelRequirement: 120, skillType: SkillType.Buff, skillTarget: SkillTarget.ImplicitParty); @@ -153,14 +154,14 @@ public override void Initialize() this.CreateSkill(SkillNumber.PowerSlash, "Power Slash", CharacterClasses.AllMGs, DamageType.Physical, distance: 5, manaConsumption: 15, energyRequirement: 100, skillType: SkillType.AreaSkillAutomaticHits); this.AddAreaSkillSettings(SkillNumber.PowerSlash, true, 1.0f, 6.0f, 6.0f); this.CreateSkill(SkillNumber.SpiralSlash, "Spiral Slash", CharacterClasses.AllMGs, DamageType.Physical, 75, 5, 15, 20); - this.CreateSkill(SkillNumber.Force, "Force", CharacterClasses.AllLords, DamageType.Physical, 10, 4, manaConsumption: 10); - this.CreateSkill(SkillNumber.FireBurst, "Fire Burst", CharacterClasses.AllLords, DamageType.Physical, 100, 6, manaConsumption: 25, energyRequirement: 79, skillType: SkillType.DirectHit, skillTarget: SkillTarget.ExplicitWithImplicitInRange, implicitTargetRange: 1); - this.CreateSkill(SkillNumber.Earthshake, "Earthshake", CharacterClasses.AllLords, DamageType.Physical, 150, 10, 50, elementalModifier: ElementalType.Lightning, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.Force, "Force", CharacterClasses.AllLords, DamageType.DarkLordGenericSkill, 10, 4, manaConsumption: 10); + this.CreateSkill(SkillNumber.FireBurst, "Fire Burst", CharacterClasses.AllLords, DamageType.DarkLordGenericSkill, 100, 6, manaConsumption: 25, energyRequirement: 79, skillType: SkillType.DirectHit, skillTarget: SkillTarget.ExplicitWithImplicitInRange, implicitTargetRange: 1); + this.CreateSkill(SkillNumber.Earthshake, "Earthshake", CharacterClasses.AllLords, DamageType.Earthshake, 150, 10, 50, elementalModifier: ElementalType.Lightning, skillType: SkillType.AreaSkillAutomaticHits); this.CreateSkill(SkillNumber.Summon, "Summon", CharacterClasses.AllLords, abilityConsumption: 30, manaConsumption: 70, energyRequirement: 153, leadershipRequirement: 400, skillType: SkillType.Other); - this.CreateSkill(SkillNumber.IncreaseCriticalDamage, "Increase Critical Damage", CharacterClasses.AllLords, abilityConsumption: 50, manaConsumption: 50, energyRequirement: 102, leadershipRequirement: 300, skillType: SkillType.Buff, skillTarget: SkillTarget.ImplicitParty); - this.CreateSkill(SkillNumber.ElectricSpike, "Electric Spike", CharacterClasses.AllLords, DamageType.Physical, 250, 10, 100, energyRequirement: 126, leadershipRequirement: 340, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.IncreaseCriticalDamage, "Increase Critical Damage", CharacterClasses.AllLords, abilityConsumption: 50, manaConsumption: 50, /*check */energyRequirement: 102, leadershipRequirement: 300, skillType: SkillType.Buff, skillTarget: SkillTarget.ImplicitParty); + this.CreateSkill(SkillNumber.ElectricSpike, "Electric Spike", CharacterClasses.AllLords, DamageType.ElectricSpike, 250, 10, 100, energyRequirement: 126, leadershipRequirement: 340, skillType: SkillType.AreaSkillAutomaticHits); this.AddAreaSkillSettings(SkillNumber.ElectricSpike, true, 1.5f, 1.5f, 12f, useDeferredHits: true, delayPerOneDistance: TimeSpan.FromMilliseconds(10)); - this.CreateSkill(SkillNumber.ForceWave, "Force Wave", CharacterClasses.AllLords, DamageType.Physical, 50, 4, manaConsumption: 10, skillType: SkillType.DirectHit, skillTarget: SkillTarget.ExplicitWithImplicitInRange); + this.CreateSkill(SkillNumber.ForceWave, "Force Wave", CharacterClasses.AllLords, DamageType.DarkLordGenericSkill, 50, 4, manaConsumption: 10, skillType: SkillType.DirectHit, skillTarget: SkillTarget.ExplicitWithImplicitInRange); this.AddAreaSkillSettings(SkillNumber.ForceWave, true, 1f, 1f, 4f); this.CreateSkill(SkillNumber.Stun, "Stun", CharacterClasses.All, distance: 2, abilityConsumption: 50, manaConsumption: 70, skillType: SkillType.AreaSkillAutomaticHits, cooldownMinutes: 4); this.AddAreaSkillSettings(SkillNumber.Stun, true, 1.5f, 1.5f, 3f); @@ -170,12 +171,12 @@ public override void Initialize() this.CreateSkill(SkillNumber.CancelInvisibility, "Cancel Invisibility", CharacterClasses.All, abilityConsumption: 30, manaConsumption: 40, cooldownMinutes: 2); this.CreateSkill(SkillNumber.AbolishMagic, "Abolish Magic", CharacterClasses.AllLords, abilityConsumption: 70, manaConsumption: 90, cooldownMinutes: 8); this.CreateSkill(SkillNumber.ManaRays, "Mana Rays", CharacterClasses.AllMGs, DamageType.Wizardry, 85, 6, 7, 130); - this.CreateSkill(SkillNumber.FireBlast, "Fire Blast", CharacterClasses.AllLords, DamageType.Physical, 150, 6, 10, 30); + this.CreateSkill(SkillNumber.FireBlast, "Fire Blast", CharacterClasses.AllLords, DamageType.DarkLordGenericSkill, 150, 6, 10, 30); this.CreateSkill(SkillNumber.PlasmaStorm, "Plasma Storm", CharacterClasses.AllMastersAndSecondClass, DamageType.Fenrir, damage: 60, distance: 6, abilityConsumption: 20, manaConsumption: 50, levelRequirement: 110, skillType: SkillType.AreaSkillAutomaticHits); this.CreateSkill(SkillNumber.InfinityArrow, "Infinity Arrow", CharacterClasses.MuseElfAndHighElf, distance: 6, abilityConsumption: 10, manaConsumption: 50, levelRequirement: 220, skillType: SkillType.Buff, targetRestriction: SkillTargetRestriction.Self); - this.CreateSkill(SkillNumber.FireScream, "Fire Scream", CharacterClasses.AllLords, DamageType.Physical, 130, 6, 10, 45, energyRequirement: 70, leadershipRequirement: 150, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.FireScream, "Fire Scream", CharacterClasses.AllLords, DamageType.DarkLordGenericSkill, 130, 6, 10, 45, energyRequirement: 70, leadershipRequirement: 150, skillType: SkillType.AreaSkillAutomaticHits); this.AddAreaSkillSettings(SkillNumber.FireScream, true, 2f, 3f, 6f); - this.CreateSkill(SkillNumber.Explosion79, "Explosion", CharacterClasses.AllLords, DamageType.Physical, distance: 2); + this.CreateSkill(SkillNumber.Explosion79, "Explosion", CharacterClasses.AllLords, DamageType.DarkLordGenericSkill, distance: 2); this.CreateSkill(SkillNumber.SummonMonster, "Summon Monster", manaConsumption: 40, energyRequirement: 90); this.CreateSkill(SkillNumber.MagicAttackImmunity, "Magic Attack Immunity", manaConsumption: 40, energyRequirement: 90); this.CreateSkill(SkillNumber.PhysicalAttackImmunity, "Physical Attack Immunity", manaConsumption: 40, energyRequirement: 90); @@ -185,26 +186,26 @@ public override void Initialize() this.CreateSkill(SkillNumber.SpellofRestriction, "Spell of Restriction", CharacterClasses.All, distance: 3, manaConsumption: 30, elementalModifier: ElementalType.Ice, cooldownMinutes: 5); this.CreateSkill(SkillNumber.SpellofPursuit, "Spell of Pursuit", CharacterClasses.All, manaConsumption: 30, elementalModifier: ElementalType.Ice, cooldownMinutes: 10); this.CreateSkill(SkillNumber.ShieldBurn, "Shield-Burn", CharacterClasses.All, distance: 3, manaConsumption: 30, elementalModifier: ElementalType.Ice, cooldownMinutes: 5); - this.CreateSkill(SkillNumber.DrainLife, "Drain Life", CharacterClasses.AllSummoners, DamageType.Curse, 35, 6, manaConsumption: 50, energyRequirement: 150, skillType: SkillType.AreaSkillExplicitTarget); - this.CreateSkill(SkillNumber.ChainLightning, "Chain Lightning", CharacterClasses.AllSummoners, DamageType.Curse, 70, 6, manaConsumption: 85, energyRequirement: 245, skillType: SkillType.AreaSkillExplicitTarget, skillTarget: SkillTarget.Explicit); - this.CreateSkill(SkillNumber.DamageReflection, "Damage Reflection", CharacterClasses.AllSummoners, distance: 5, abilityConsumption: 10, manaConsumption: 40, energyRequirement: 375); - this.CreateSkill(SkillNumber.Berserker, "Berserker", CharacterClasses.AllSummoners, DamageType.Curse, distance: 5, abilityConsumption: 50, manaConsumption: 100, energyRequirement: 620); - this.CreateSkill(SkillNumber.Sleep, "Sleep", CharacterClasses.AllSummoners, distance: 6, abilityConsumption: 3, manaConsumption: 20, energyRequirement: 180); - this.CreateSkill(SkillNumber.Weakness, "Weakness", CharacterClasses.AllSummoners, distance: 6, abilityConsumption: 15, manaConsumption: 50, energyRequirement: 663); - this.CreateSkill(SkillNumber.Innovation, "Innovation", CharacterClasses.AllSummoners, distance: 6, abilityConsumption: 15, manaConsumption: 70, energyRequirement: 912); - this.CreateSkill(SkillNumber.Explosion223, "Explosion", CharacterClasses.AllSummoners, DamageType.Curse, 40, 6, 5, 90, energyRequirement: 100, elementalModifier: ElementalType.Fire); - this.CreateSkill(SkillNumber.Requiem, "Requiem", CharacterClasses.AllSummoners, DamageType.Curse, 65, 6, 10, 110, energyRequirement: 99, elementalModifier: ElementalType.Wind); - this.CreateSkill(SkillNumber.Pollution, "Pollution", CharacterClasses.AllSummoners, DamageType.Curse, 80, 6, 15, 120, energyRequirement: 115, elementalModifier: ElementalType.Lightning); - this.CreateSkill(SkillNumber.LightningShock, "Lightning Shock", CharacterClasses.AllSummoners, DamageType.Curse, 95, 6, 7, 115, energyRequirement: 823, elementalModifier: ElementalType.Lightning); + this.CreateSkill(SkillNumber.DrainLife, "Drain Life", CharacterClasses.AllSummoners, DamageType.Wizardry, 35, 6, manaConsumption: 50, energyRequirement: 150, skillType: SkillType.AreaSkillExplicitTarget); + this.CreateSkill(SkillNumber.ChainLightning, "Chain Lightning", CharacterClasses.AllSummoners, DamageType.Wizardry, 70, 6, manaConsumption: 85, energyRequirement: 245, skillType: SkillType.AreaSkillExplicitTarget, skillTarget: SkillTarget.Explicit); + this.CreateSkill(SkillNumber.DamageReflection, "Damage Reflection", CharacterClasses.AllSummoners, distance: 5, abilityConsumption: 10, manaConsumption: 40, energyRequirement: 375, skillType: SkillType.Buff, targetRestriction: SkillTargetRestriction.Self); + this.CreateSkill(SkillNumber.Berserker, "Berserker", CharacterClasses.AllSummoners, distance: 5, abilityConsumption: 50, manaConsumption: 100, energyRequirement: 620, skillType: SkillType.Buff, targetRestriction: SkillTargetRestriction.Self); + this.CreateSkill(SkillNumber.Sleep, "Sleep", CharacterClasses.AllSummoners, distance: 6, abilityConsumption: 3, manaConsumption: 20, energyRequirement: 180, skillType: SkillType.Buff); + this.CreateSkill(SkillNumber.Weakness, "Weakness", CharacterClasses.AllSummoners, distance: 6, abilityConsumption: 15, manaConsumption: 50, energyRequirement: 663, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.Innovation, "Innovation", CharacterClasses.AllSummoners, distance: 6, abilityConsumption: 15, manaConsumption: 70, energyRequirement: 912, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.Explosion223, "Explosion", CharacterClasses.AllSummoners, DamageType.Curse, 40, 6, 5, 90, energyRequirement: 100, elementalModifier: ElementalType.Fire); // Book of Samut's skill + this.CreateSkill(SkillNumber.Requiem, "Requiem", CharacterClasses.AllSummoners, DamageType.Curse, 65, 6, 10, 110, energyRequirement: 99, elementalModifier: ElementalType.Wind); // Book of Neil's skill + this.CreateSkill(SkillNumber.Pollution, "Pollution", CharacterClasses.AllSummoners, DamageType.Curse, 80, 6, 15, 120, energyRequirement: 115, elementalModifier: ElementalType.Lightning); // Book of Lagle's skill + this.CreateSkill(SkillNumber.LightningShock, "Lightning Shock", CharacterClasses.AllSummoners, DamageType.Wizardry, 95, 6, 7, 115, energyRequirement: 823, elementalModifier: ElementalType.Lightning); this.CreateSkill(SkillNumber.StrikeofDestruction, "Strike of Destruction", CharacterClasses.BladeKnightAndBladeMaster, DamageType.Physical, 110, 5, 24, 30, 100, elementalModifier: ElementalType.Ice, skillType: SkillType.AreaSkillAutomaticHits); this.CreateSkill(SkillNumber.ExpansionofWizardry, "Expansion of Wizardry", CharacterClasses.SoulMasterAndGrandMaster, distance: 6, abilityConsumption: 50, manaConsumption: 200, levelRequirement: 220, energyRequirement: 118, skillType: SkillType.Buff, targetRestriction: SkillTargetRestriction.Player, skillTarget: SkillTarget.ImplicitPlayer); this.CreateSkill(SkillNumber.Recovery, "Recovery", CharacterClasses.MuseElfAndHighElf, distance: 6, abilityConsumption: 10, manaConsumption: 40, levelRequirement: 100, energyRequirement: 37, skillType: SkillType.Regeneration, targetRestriction: SkillTargetRestriction.Player); - this.CreateSkill(SkillNumber.MultiShot, "Multi-Shot", CharacterClasses.MuseElfAndHighElf, DamageType.Physical, 40, 6, 7, 10, 100, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.MultiShot, "Multi-Shot", CharacterClasses.MuseElfAndHighElf, DamageType.MultiShot, 40, 6, 7, 10, 100, skillType: SkillType.AreaSkillAutomaticHits); this.AddAreaSkillSettings(SkillNumber.MultiShot, true, 1f, 6f, 7f); this.CreateSkill(SkillNumber.FlameStrike, "Flame Strike", CharacterClasses.AllMGs, DamageType.Physical, 140, 3, 25, 20, 100, elementalModifier: ElementalType.Fire, skillType: SkillType.AreaSkillAutomaticHits); this.AddAreaSkillSettings(SkillNumber.FlameStrike, true, 5f, 2f, 4f); this.CreateSkill(SkillNumber.GiganticStorm, "Gigantic Storm", CharacterClasses.AllMGs, DamageType.Wizardry, 110, 6, 10, 120, 220, 118, elementalModifier: ElementalType.Wind, skillType: SkillType.AreaSkillAutomaticHits); - this.CreateSkill(SkillNumber.ChaoticDiseier, "Chaotic Diseier", CharacterClasses.AllLords, DamageType.Physical, 190, 6, 15, 50, 100, 16, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.ChaoticDiseier, "Chaotic Diseier", CharacterClasses.AllLords, DamageType.ChaoticDiseier, 190, 6, 15, 50, 100, 16, skillType: SkillType.AreaSkillAutomaticHits); this.AddAreaSkillSettings(SkillNumber.ChaoticDiseier, true, 1.5f, 1.5f, 6f); this.CreateSkill(SkillNumber.DoppelgangerSelfExplosion, "Doppelganger Self Explosion", CharacterClasses.AllMGs, DamageType.Wizardry, 140, 3, 25, 20, 100, elementalModifier: ElementalType.Fire); this.CreateSkill(SkillNumber.KillingBlow, "Killing Blow", CharacterClasses.AllFighters, DamageType.Physical, distance: 2, manaConsumption: 9, elementalModifier: ElementalType.Earth); @@ -324,16 +325,16 @@ public override void Initialize() this.CreateSkill(SkillNumber.WindTomeMastery, "Wind Tome Mastery", CharacterClasses.DimensionMaster, damage: 1, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.LightningTomeMastery, "Lightning Tome Mastery", CharacterClasses.DimensionMaster, DamageType.Curse, 7, elementalModifier: ElementalType.Lightning, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.SleepStrengthener, "Sleep Strengthener", CharacterClasses.DimensionMaster, damage: 1, distance: 6, abilityConsumption: 7, manaConsumption: 30, levelRequirement: 40, energyRequirement: 100); - this.CreateSkill(SkillNumber.ChainLightningStr, "Chain Lightning Str", CharacterClasses.DimensionMaster, DamageType.Curse, 22, 6, manaConsumption: 103, levelRequirement: 75, energyRequirement: 75, skillTarget: SkillTarget.Explicit, skillType: SkillType.AreaSkillExplicitTarget); - this.CreateSkill(SkillNumber.LightningShockStr, "Lightning Shock Str", CharacterClasses.DimensionMaster, DamageType.Curse, 22, 6, 10, 125, 93, 216, elementalModifier: ElementalType.Lightning); - this.CreateSkill(SkillNumber.MagicMasterySummoner, "Magic Mastery", CharacterClasses.DimensionMaster, DamageType.Curse, 22, skillType: SkillType.PassiveBoost); - this.CreateSkill(SkillNumber.DrainLifeStrengthener, "Drain Life Strengthener", CharacterClasses.DimensionMaster, DamageType.Curse, 22, 6, manaConsumption: 57, levelRequirement: 35, energyRequirement: 93); - this.CreateSkill(SkillNumber.StickStrengthener, "Stick Strengthener", CharacterClasses.DimensionMaster, DamageType.Curse, 22, skillType: SkillType.PassiveBoost); + this.CreateSkill(SkillNumber.ChainLightningStr, "Chain Lightning Str", CharacterClasses.DimensionMaster, DamageType.Wizardry, 22, 6, manaConsumption: 103, levelRequirement: 75, energyRequirement: 75, skillTarget: SkillTarget.Explicit, skillType: SkillType.AreaSkillExplicitTarget); + this.CreateSkill(SkillNumber.LightningShockStr, "Lightning Shock Str", CharacterClasses.DimensionMaster, DamageType.Wizardry, 22, 6, 10, 125, 93, 216, elementalModifier: ElementalType.Lightning); + this.CreateSkill(SkillNumber.MagicMasterySummoner, "Magic Mastery", CharacterClasses.DimensionMaster, DamageType.Wizardry, 22, skillType: SkillType.PassiveBoost); + this.CreateSkill(SkillNumber.DrainLifeStrengthener, "Drain Life Strengthener", CharacterClasses.DimensionMaster, DamageType.Wizardry, 22, 6, manaConsumption: 57, levelRequirement: 35, energyRequirement: 93); + this.CreateSkill(SkillNumber.StickStrengthener, "Stick Strengthener", CharacterClasses.DimensionMaster, DamageType.Wizardry, 22, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.OtherWorldTomeStreng, "Other World Tome Streng", CharacterClasses.DimensionMaster, DamageType.Curse, 3, skillType: SkillType.PassiveBoost); - this.CreateSkill(SkillNumber.StickMastery, "Stick Mastery", CharacterClasses.DimensionMaster, DamageType.Curse, 5, skillType: SkillType.PassiveBoost); + this.CreateSkill(SkillNumber.StickMastery, "Stick Mastery", CharacterClasses.DimensionMaster, DamageType.Wizardry, 5, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.OtherWorldTomeMastery, "Other World Tome Mastery", CharacterClasses.DimensionMaster, damage: 23, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.BerserkerStrengthener, "Berserker Strengthener", CharacterClasses.DimensionMaster, DamageType.Curse, 7, 5, 75, 150, 83, 181); - this.CreateSkill(SkillNumber.BerserkerProficiency, "Berserker Proficiency", CharacterClasses.DimensionMaster, DamageType.Curse, 7, 5, 82, 165, 83, 181); + this.CreateSkill(SkillNumber.BerserkerProficiency, "Berserker Proficiency", CharacterClasses.DimensionMaster, DamageType.Wizardry, 7, 5, 82, 165, 83, 181); this.CreateSkill(SkillNumber.MinimumWizCurseInc, "Minimum Wiz/Curse Inc", CharacterClasses.DimensionMaster, damage: 22, skillType: SkillType.PassiveBoost); // Duel Master (MG): @@ -351,17 +352,18 @@ public override void Initialize() this.CreateSkill(SkillNumber.BloodAttackStrengthen, "Blood Attack Strengthen", CharacterClasses.DuelMaster, damage: 22, distance: 3, abilityConsumption: 22, manaConsumption: 15, elementalModifier: ElementalType.Poison); // Lord Emperor (DL): - this.CreateSkill(SkillNumber.FireBurstStreng, "Fire Burst Streng", CharacterClasses.LordEmperor, DamageType.Physical, 22, 6, manaConsumption: 25, levelRequirement: 74, energyRequirement: 20); - this.CreateSkill(SkillNumber.ForceWaveStreng, "Force Wave Streng", CharacterClasses.LordEmperor, DamageType.Physical, 3, 4, manaConsumption: 15); + this.CreateSkill(SkillNumber.FireBurstStreng, "Fire Burst Streng", CharacterClasses.LordEmperor, DamageType.DarkLordGenericSkill, 22, 6, manaConsumption: 25, levelRequirement: 74, energyRequirement: 20); + this.CreateSkill(SkillNumber.ForceWaveStreng, "Force Wave Streng", CharacterClasses.LordEmperor, DamageType.DarkLordGenericSkill, 3, 4, manaConsumption: 15); + this.CreateSkill((SkillNumber)5090, "Force Wave Streng (scepter with skill)", CharacterClasses.LordEmperor, DamageType.DarkLordGenericSkill, 3, 4, manaConsumption: 15); this.CreateSkill(SkillNumber.DarkHorseStreng1, "Dark Horse Streng (1)", CharacterClasses.LordEmperor, damage: 17, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.CriticalDmgIncPowUp, "Critical DMG Inc PowUp", CharacterClasses.LordEmperor, damage: 3, abilityConsumption: 75, manaConsumption: 75, levelRequirement: 82, energyRequirement: 25, leadershipRequirement: 300); - this.CreateSkill(SkillNumber.EarthshakeStreng, "Earthshake Streng", CharacterClasses.LordEmperor, DamageType.Physical, 22, 10, 75, elementalModifier: ElementalType.Lightning); + this.CreateSkill(SkillNumber.EarthshakeStreng, "Earthshake Streng", CharacterClasses.LordEmperor, DamageType.Earthshake, 22, 10, 75, elementalModifier: ElementalType.Lightning); this.CreateSkill(SkillNumber.WeaponMasteryLordEmperor, "Weapon Mastery", CharacterClasses.LordEmperor, damage: 22, skillType: SkillType.PassiveBoost); - this.CreateSkill(SkillNumber.FireBurstMastery, "Fire Burst Mastery", CharacterClasses.LordEmperor, DamageType.Physical, 1, 6, manaConsumption: 27, levelRequirement: 74, energyRequirement: 20); + this.CreateSkill(SkillNumber.FireBurstMastery, "Fire Burst Mastery", CharacterClasses.LordEmperor, DamageType.DarkLordGenericSkill, 1, 6, manaConsumption: 27, levelRequirement: 74, energyRequirement: 20); this.CreateSkill(SkillNumber.CritDmgIncPowUp2, "Crit DMG Inc PowUp (2)", CharacterClasses.LordEmperor, damage: 10, abilityConsumption: 82, manaConsumption: 82, levelRequirement: 82, energyRequirement: 25, leadershipRequirement: 300); - this.CreateSkill(SkillNumber.EarthshakeMastery, "Earthshake Mastery", CharacterClasses.LordEmperor, DamageType.Physical, 1, 10, 75, elementalModifier: ElementalType.Lightning); + this.CreateSkill(SkillNumber.EarthshakeMastery, "Earthshake Mastery", CharacterClasses.LordEmperor, DamageType.Earthshake, 1, 10, 75, elementalModifier: ElementalType.Lightning); this.CreateSkill(SkillNumber.CritDmgIncPowUp3, "Crit DMG Inc PowUp (3)", CharacterClasses.LordEmperor, damage: 7, abilityConsumption: 100, manaConsumption: 100, levelRequirement: 82, energyRequirement: 25, leadershipRequirement: 300); - this.CreateSkill(SkillNumber.FireScreamStren, "Fire Scream Stren", CharacterClasses.LordEmperor, DamageType.Physical, 22, 6, 11, 45, 102, 32, 70); + this.CreateSkill(SkillNumber.FireScreamStren, "Fire Scream Stren", CharacterClasses.LordEmperor, DamageType.DarkLordGenericSkill, 22, 6, 11, 45, 102, 32, 70); this.CreateSkill(SkillNumber.DarkSpiritStr, "Dark Spirit Str", CharacterClasses.LordEmperor, damage: 3, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.ScepterStrengthener, "Scepter Strengthener", CharacterClasses.LordEmperor, DamageType.Physical, 22, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.ShieldStrengthenerLordEmperor, "Shield Strengthener", CharacterClasses.LordEmperor, damage: 10, skillType: SkillType.PassiveBoost); @@ -444,7 +446,7 @@ private void InitializeNextSeasonMasterSkills() this.CreateSkill(SkillNumber.WingofStormAbsPowUp, "Wing of Storm Abs PowUp", CharacterClasses.BladeMaster, damage: 1, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.WingofStormDefPowUp, "Wing of Storm Def PowUp", CharacterClasses.BladeMaster, damage: 17, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.IronDefense, "Iron Defense", CharacterClasses.AllMasters, damage: 1); - this.CreateSkill(SkillNumber.WingofStormAttPowUp, "Wing of Storm Att PowUp", CharacterClasses.BladeMaster, damage: 17, skillType: SkillType.PassiveBoost); + this.CreateSkill(SkillNumber.WingofStormAttPowUp, "Wing of Storm Att PowUp", CharacterClasses.BladeMaster, damage: 17, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.DeathStabProficiency, "Death Stab Proficiency", CharacterClasses.BladeMaster, DamageType.Physical, 7, 2, 26, 30, 160, elementalModifier: ElementalType.Wind); this.CreateSkill(SkillNumber.StrikeofDestrProf, "Strike of Destr Prof", CharacterClasses.BladeMaster, DamageType.Physical, 7, 5, 24, 30, 100, elementalModifier: ElementalType.Ice); this.CreateSkill(SkillNumber.MaximumAgIncrease, "Maximum AG Increase", CharacterClasses.AllMastersExceptFistMaster, damage: 8, skillType: SkillType.PassiveBoost); @@ -470,7 +472,7 @@ private void InitializeNextSeasonMasterSkills() // High Elf: this.CreateSkill(SkillNumber.IllusionWingsAbsPowUp, "Illusion Wings Abs PowUp", CharacterClasses.HighElf, damage: 1, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.IllusionWingsDefPowUp, "Illusion Wings Def PowUp", CharacterClasses.HighElf, damage: 17, skillType: SkillType.PassiveBoost); - this.CreateSkill(SkillNumber.MultiShotStreng, "Multi-Shot Streng", CharacterClasses.HighElf, DamageType.Physical, 22, 6, 7, 11, 100, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.MultiShotStreng, "Multi-Shot Streng", CharacterClasses.HighElf, DamageType.MultiShot, 22, 6, 7, 11, 100, skillType: SkillType.AreaSkillAutomaticHits); this.CreateSkill(SkillNumber.IllusionWingsAttPowUp, "Illusion Wings Att PowUp", CharacterClasses.HighElf, damage: 17, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.Cure, "Cure", CharacterClasses.HighElf, distance: 6, abilityConsumption: 10, manaConsumption: 72); this.CreateSkill(SkillNumber.PartyHealing, "Party Healing", CharacterClasses.HighElf, distance: 6, abilityConsumption: 12, manaConsumption: 66, energyRequirement: 100); @@ -478,7 +480,7 @@ private void InitializeNextSeasonMasterSkills() this.CreateSkill(SkillNumber.SummonedMonsterStr3, "Summoned Monster Str (3)", CharacterClasses.HighElf, damage: 16, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.PartyHealingStr, "Party Healing Str", CharacterClasses.HighElf, damage: 22, distance: 6, abilityConsumption: 13, manaConsumption: 72, energyRequirement: 100); this.CreateSkill(SkillNumber.Bless, "Bless", CharacterClasses.HighElf, distance: 6, abilityConsumption: 18, manaConsumption: 108, energyRequirement: 100); - this.CreateSkill(SkillNumber.MultiShotMastery, "Multi-Shot Mastery", CharacterClasses.HighElf, DamageType.Physical, 1, 6, 8, 12, 100, skillType: SkillType.AreaSkillAutomaticHits); + this.CreateSkill(SkillNumber.MultiShotMastery, "Multi-Shot Mastery", CharacterClasses.HighElf, DamageType.MultiShot, 1, 6, 8, 12, 100, skillType: SkillType.AreaSkillAutomaticHits); this.CreateSkill(SkillNumber.SummonSatyros, "Summon Satyros", CharacterClasses.HighElf, abilityConsumption: 52, manaConsumption: 525, energyRequirement: 280); this.CreateSkill(SkillNumber.BlessStrengthener, "Bless Strengthener", CharacterClasses.HighElf, damage: 10, distance: 6, abilityConsumption: 20, manaConsumption: 118, energyRequirement: 100); this.CreateSkill(SkillNumber.PoisonArrowStr, "Poison Arrow Str", CharacterClasses.HighElf, DamageType.Physical, 22, 6, 29, 24, elementalModifier: ElementalType.Poison); @@ -513,11 +515,11 @@ private void InitializeNextSeasonMasterSkills() this.CreateSkill(SkillNumber.EmperorCapeDefPowUp, "Emperor Cape Def PowUp", CharacterClasses.LordEmperor, damage: 17, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.AddsCommandStat, "Adds Command Stat", CharacterClasses.LordEmperor, damage: 17, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.EmperorCapeAttPowUp, "Emperor Cape Att PowUp", CharacterClasses.LordEmperor, damage: 17, skillType: SkillType.PassiveBoost); - this.CreateSkill(SkillNumber.ElectricSparkStreng, "Electric Spark Streng", CharacterClasses.LordEmperor, DamageType.Physical, 3, 10, 150, levelRequirement: 92, energyRequirement: 29, leadershipRequirement: 340); - this.CreateSkill(SkillNumber.FireScreamMastery, "Fire Scream Mastery", CharacterClasses.LordEmperor, DamageType.Physical, 5, 6, 12, 49, 102, 32, 70); + this.CreateSkill(SkillNumber.ElectricSparkStreng, "Electric Spark Streng", CharacterClasses.LordEmperor, DamageType.ElectricSpike, 3, 10, 150, levelRequirement: 92, energyRequirement: 29, leadershipRequirement: 340); + this.CreateSkill(SkillNumber.FireScreamMastery, "Fire Scream Mastery", CharacterClasses.LordEmperor, DamageType.DarkLordGenericSkill, 5, 6, 12, 49, 102, 32, 70); this.CreateSkill(SkillNumber.IronDefenseLordEmperor, "Iron Defense", CharacterClasses.LordEmperor, damage: 28, abilityConsumption: 29, manaConsumption: 64); this.CreateSkill(SkillNumber.CriticalDamageIncM, "Critical Damage Inc M", CharacterClasses.LordEmperor, damage: 1, abilityConsumption: 110, manaConsumption: 110, levelRequirement: 82, energyRequirement: 25, leadershipRequirement: 300); - this.CreateSkill(SkillNumber.ChaoticDiseierStr, "Chaotic Diseier Str", CharacterClasses.LordEmperor, DamageType.Physical, 22, 6, 22, 75, 100, 16); + this.CreateSkill(SkillNumber.ChaoticDiseierStr, "Chaotic Diseier Str", CharacterClasses.LordEmperor, DamageType.ChaoticDiseier, 22, 6, 22, 75, 100, 16); this.CreateSkill(SkillNumber.IronDefenseStr, "Iron Defense Str", CharacterClasses.LordEmperor, damage: 3, abilityConsumption: 31, manaConsumption: 70); this.CreateSkill(SkillNumber.DarkSpiritStr4, "Dark Spirit Str (4)", CharacterClasses.LordEmperor, damage: 23, skillType: SkillType.PassiveBoost); this.CreateSkill(SkillNumber.DarkSpiritStr5, "Dark Spirit Str (5)", CharacterClasses.LordEmperor, damage: 1, skillType: SkillType.PassiveBoost); @@ -592,6 +594,8 @@ private void InitializeEffects() new AlcoholEffectInitializer(this.Context, this.GameConfiguration).Initialize(); new SoulPotionEffectInitializer(this.Context, this.GameConfiguration).Initialize(); new BlessPotionEffectInitializer(this.Context, this.GameConfiguration).Initialize(); + new BerserkerEffectInitializer(this.Context, this.GameConfiguration).Initialize(); + new KillingBlowEffectInitializer(this.Context, this.GameConfiguration).Initialize(); } private void MapSkillsToEffects() @@ -633,14 +637,14 @@ private void InitializeMasterSkillData() this.AddMasterSkillDefinition(SkillNumber.SdRecoverySpeedInc, SkillNumber.MaximumSDincrease, SkillNumber.Undefined, 1, 3, SkillNumber.Undefined, 20, Formula120); this.AddPassiveMasterSkillDefinition(SkillNumber.AutomaticHpRecInc, Stats.HealthRecoveryMultiplier, AggregateType.AddRaw, FormulaRecoveryIncrease120, Formula120, 3, 1, SkillNumber.AutomaticManaRecInc, SkillNumber.Undefined, 20); this.AddPassiveMasterSkillDefinition(SkillNumber.LightningResistanceInc, Stats.LightningResistance, AggregateType.AddRaw, Formula120Value, Formula120, 2, 1, requiredSkill1: SkillNumber.PoisonResistanceInc); - this.AddPassiveMasterSkillDefinition(SkillNumber.DefenseIncrease, Stats.DefenseBase, AggregateType.AddRaw, Formula6020, 4, 1); + this.AddPassiveMasterSkillDefinition(SkillNumber.DefenseIncrease, Stats.DefenseBase, AggregateType.AddFinal, Formula6020, 4, 1); this.AddPassiveMasterSkillDefinition(SkillNumber.AutomaticAgRecInc, Stats.AbilityRecoveryMultiplier, AggregateType.AddRaw, FormulaRecoveryIncrease120, Formula120, 4, 1, SkillNumber.AutomaticHpRecInc, SkillNumber.Undefined, 20); this.AddPassiveMasterSkillDefinition(SkillNumber.IceResistanceIncrease, Stats.IceResistance, AggregateType.AddRaw, Formula120Value, Formula120, 2, 1, requiredSkill1: SkillNumber.LightningResistanceInc); this.AddPassiveMasterSkillDefinition(SkillNumber.DurabilityReduction3, Stats.ItemDurationIncrease, AggregateType.Multiplicate, Formula1204, 5, 1, SkillNumber.DurabilityReduction2); - this.AddPassiveMasterSkillDefinition(SkillNumber.DefenseSuccessRateInc, Stats.DefenseRatePvm, AggregateType.AddRaw, Formula120, 5, 1, SkillNumber.DefenseIncrease); + this.AddPassiveMasterSkillDefinition(SkillNumber.DefenseSuccessRateInc, Stats.DefenseRatePvm, AggregateType.Multiplicate, Formula120, 5, 1, SkillNumber.DefenseIncrease); // DK - this.AddPassiveMasterSkillDefinition(SkillNumber.AttackSuccRateInc, Stats.AttackRatePvm, AggregateType.AddRaw, Formula51173, 1, 2); + this.AddPassiveMasterSkillDefinition(SkillNumber.AttackSuccRateInc, Stats.AttackRatePvm, AggregateType.AddFinal, Formula51173, 1, 2); this.AddMasterSkillDefinition(SkillNumber.CycloneStrengthener, SkillNumber.Cyclone, SkillNumber.Undefined, 2, 2, SkillNumber.Cyclone, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.SlashStrengthener, SkillNumber.Slash, SkillNumber.Undefined, 2, 2, SkillNumber.Slash, 20, Formula632); this.AddMasterSkillDefinition(SkillNumber.FallingSlashStreng, SkillNumber.FallingSlash, SkillNumber.Undefined, 2, 2, SkillNumber.FallingSlash, 20, Formula632); @@ -650,17 +654,17 @@ private void InitializeMasterSkillData() this.AddMasterSkillDefinition(SkillNumber.TwistingSlashMastery, SkillNumber.TwistingSlashStreng, SkillNumber.Undefined, 2, 4, SkillNumber.TwistingSlash, 20, Formula120); this.AddMasterSkillDefinition(SkillNumber.RagefulBlowMastery, SkillNumber.RagefulBlowStreng, SkillNumber.Undefined, 2, 4, SkillNumber.RagefulBlow, 20, Formula120); this.AddPassiveMasterSkillDefinition(SkillNumber.MaximumLifeIncrease, Stats.MaximumHealth, AggregateType.AddRaw, Formula10235, 4, 2); - this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryBladeMaster, Stats.PhysicalBaseDmg, AggregateType.AddRaw, Formula502, 4, 2); + this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryBladeMaster, Stats.MasterSkillPhysBonusDmg, AggregateType.AddRaw, Formula502, 4, 2); this.AddMasterSkillDefinition(SkillNumber.DeathStabStrengthener, SkillNumber.DeathStab, SkillNumber.Undefined, 2, 5, SkillNumber.DeathStab, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.StrikeofDestrStr, SkillNumber.StrikeofDestruction, SkillNumber.Undefined, 2, 5, SkillNumber.StrikeofDestruction, 20, Formula502); this.AddPassiveMasterSkillDefinition(SkillNumber.MaximumManaIncrease, Stats.MaximumMana, AggregateType.AddRaw, Formula10235, 5, 2, SkillNumber.MaximumLifeIncrease); this.AddPassiveMasterSkillDefinition(SkillNumber.PvPAttackRate, Stats.AttackRatePvp, AggregateType.AddRaw, Formula81877, 1, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedSwordStrengthener, Stats.TwoHandedSwordBonusBaseDamage, AggregateType.AddRaw, Formula883, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.OneHandedSwordStrengthener, Stats.OneHandedSwordBonusBaseDamage, AggregateType.AddRaw, Formula502, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.MaceStrengthener, Stats.MaceBonusBaseDamage, AggregateType.AddRaw, Formula632, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.SpearStrengthener, Stats.SpearBonusBaseDamage, AggregateType.AddRaw, Formula632, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedSwordMaster, Stats.TwoHandedSwordBonusBaseDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.TwoHandedSwordStrengthener); // todo: this is only pvp damage - this.AddPassiveMasterSkillDefinition(SkillNumber.OneHandedSwordMaster, Stats.AttackSpeed, AggregateType.AddRaw, Formula1, 3, 3, SkillNumber.OneHandedSwordStrengthener, SkillNumber.Undefined, 10); + this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedSwordStrengthener, Stats.TwoHandedSwordStrBonusDamage, AggregateType.AddRaw, Formula883, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.OneHandedSwordStrengthener, Stats.OneHandedSwordBonusDamage, AggregateType.AddRaw, Formula502, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.MaceStrengthener, Stats.MaceBonusDamage, AggregateType.AddRaw, Formula632, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.SpearStrengthener, Stats.SpearBonusDamage, AggregateType.AddRaw, Formula632, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedSwordMaster, Stats.TwoHandedSwordMasteryBonusDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.TwoHandedSwordStrengthener); + this.AddPassiveMasterSkillDefinition(SkillNumber.OneHandedSwordMaster, Stats.WeaponMasteryAttackSpeed, AggregateType.AddRaw, Formula1, 3, 3, SkillNumber.OneHandedSwordStrengthener, SkillNumber.Undefined, 10); // todo: Probability of stunning the target for 2 seconds according to the assigned Skill Level while using a Mace. this.AddMasterSkillDefinition(SkillNumber.MaceMastery, SkillNumber.MaceStrengthener, SkillNumber.Undefined, 3, 3, SkillNumber.Undefined, 20, Formula120); @@ -689,14 +693,14 @@ private void InitializeMasterSkillData() this.AddMasterSkillDefinition(SkillNumber.DecayStrengthener, SkillNumber.Decay, SkillNumber.PoisonStrengthener, 2, 4, SkillNumber.Decay, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.HellfireStrengthener, SkillNumber.Hellfire, SkillNumber.Undefined, 2, 5, SkillNumber.Hellfire, 20, Formula632); this.AddMasterSkillDefinition(SkillNumber.IceStrengthener, SkillNumber.Ice, SkillNumber.Undefined, 2, 5, SkillNumber.Ice, 20, Formula632); - this.AddPassiveMasterSkillDefinition(SkillNumber.OneHandedStaffStrengthener, Stats.WizardryBaseDmg, AggregateType.AddRaw, Formula502, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedStaffStrengthener, Stats.WizardryBaseDmg, AggregateType.AddRaw, Formula883, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldStrengthenerGrandMaster, Stats.BonusDefenseWithShield, AggregateType.AddRaw, Formula803, 2, 3); // todo: check if this is correct - this.AddPassiveMasterSkillDefinition(SkillNumber.OneHandedStaffMaster, Stats.AttackSpeed, AggregateType.AddRaw, Formula1, 3, 3, SkillNumber.OneHandedStaffStrengthener, SkillNumber.Undefined, 10); - this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedStaffMaster, Stats.TwoHandedStaffBonusBaseDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.TwoHandedStaffStrengthener); // todo: only pvp - this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldMasteryGrandMaster, Stats.BonusDefenseWithShield, AggregateType.AddRaw, Formula1204, 3, 3, SkillNumber.ShieldStrengthenerGrandMaster); - this.AddMasterSkillDefinition(SkillNumber.SoulBarrierStrength, SkillNumber.SoulBarrier, SkillNumber.Undefined, 3, 4, SkillNumber.SoulBarrier, 20, Formula181); - this.AddMasterSkillDefinition(SkillNumber.SoulBarrierProficie, SkillNumber.SoulBarrierStrength, SkillNumber.Undefined, 3, 5, SkillNumber.SoulBarrier, 20, Formula803); + this.AddPassiveMasterSkillDefinition(SkillNumber.OneHandedStaffStrengthener, Stats.OneHandedStaffBonusBaseDamage, AggregateType.AddRaw, Formula502, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedStaffStrengthener, Stats.TwoHandedStaffBonusBaseDamage, AggregateType.AddRaw, Formula883, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldStrengthenerGrandMaster, Stats.BonusDefenseWithShield, AggregateType.AddRaw, Formula803, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.OneHandedStaffMaster, Stats.WeaponMasteryAttackSpeed, AggregateType.AddRaw, Formula1, 3, 3, SkillNumber.OneHandedStaffStrengthener, SkillNumber.Undefined, 10); + this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedStaffMaster, Stats.TwoHandedStaffMasteryBonusDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.TwoHandedStaffStrengthener); + this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldMasteryGrandMaster, Stats.BonusDefenseRateWithShield, AggregateType.AddRaw, Formula1204, 3, 3, SkillNumber.ShieldStrengthenerGrandMaster); + this.AddMasterSkillDefinition(SkillNumber.SoulBarrierStrength, SkillNumber.SoulBarrier, SkillNumber.Undefined, 3, 4, SkillNumber.SoulBarrier, 20, $"-{Formula181} / 100", Formula181, Stats.SoulBarrierReceiveDecrement, AggregateType.AddRaw); + this.AddMasterSkillDefinition(SkillNumber.SoulBarrierProficie, SkillNumber.SoulBarrierStrength, SkillNumber.Undefined, 3, 5, SkillNumber.SoulBarrierStrength, 20, Formula803, extendsDuration: true); this.AddPassiveMasterSkillDefinition(SkillNumber.MinimumWizardryInc, Stats.MinimumWizBaseDmg, AggregateType.AddRaw, Formula502, 5, 3); // ELF @@ -708,38 +712,38 @@ private void InitializeMasterSkillData() this.AddMasterSkillDefinition(SkillNumber.TripleShotMastery, SkillNumber.TripleShotStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.TripleShot, 10, Formula1WhenComplete); this.AddPassiveMasterSkillDefinition(SkillNumber.SummonedMonsterStr2, Stats.SummonedMonsterDefenseIncrease, AggregateType.AddRaw, Formula6020, 2, 3, SkillNumber.SummonGoblin); this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseStr, SkillNumber.GreaterDamage, SkillNumber.Undefined, 2, 4, SkillNumber.GreaterDamage, 20, Formula502); - this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryHighElf, Stats.PhysicalBaseDmg, AggregateType.AddRaw, Formula502, 4, 2); + this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryHighElf, Stats.MasterSkillPhysBonusDmg, AggregateType.AddRaw, Formula502, 4, 2); this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseMastery, SkillNumber.AttackIncreaseStr, SkillNumber.Undefined, 2, 5, SkillNumber.GreaterDamage, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.DefenseIncreaseMastery, SkillNumber.DefenseIncreaseStr, SkillNumber.Undefined, 2, 5, SkillNumber.GreaterDefense, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.IceArrowStrengthener, SkillNumber.IceArrow, SkillNumber.Undefined, 2, 5, SkillNumber.IceArrow, 20, Formula502); - this.AddPassiveMasterSkillDefinition(SkillNumber.BowStrengthener, Stats.BowBonusBaseDamage, AggregateType.AddRaw, Formula502, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.CrossbowStrengthener, Stats.CrossBowBonusBaseDamage, AggregateType.AddRaw, Formula632, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.BowStrengthener, Stats.BowStrBonusDamage, AggregateType.AddRaw, Formula502, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.CrossbowStrengthener, Stats.CrossBowStrBonusDamage, AggregateType.AddRaw, Formula632, 2, 3); this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldStrengthenerHighElf, Stats.BonusDefenseWithShield, AggregateType.AddRaw, Formula803, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.BowMastery, Stats.AttackSpeed, AggregateType.AddRaw, Formula1, 3, 3, SkillNumber.BowStrengthener, SkillNumber.Undefined, 10); - this.AddPassiveMasterSkillDefinition(SkillNumber.CrossbowMastery, Stats.CrossBowBonusBaseDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.CrossbowStrengthener); // todo only pvp - this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldMasteryHighElf, Stats.BonusDefenseWithShield, AggregateType.AddRaw, Formula1806, 3, 3, SkillNumber.ShieldStrengthenerHighElf); - this.AddMasterSkillDefinition(SkillNumber.InfinityArrowStr, SkillNumber.InfinityArrow, SkillNumber.Undefined, 3, 5, SkillNumber.InfinityArrow, 20, $"{Formula120} / 100", Formula120, Stats.AttackDamageIncrease, AggregateType.AddRaw); + this.AddPassiveMasterSkillDefinition(SkillNumber.BowMastery, Stats.WeaponMasteryAttackSpeed, AggregateType.AddRaw, Formula1, 3, 3, SkillNumber.BowStrengthener, SkillNumber.Undefined, 10); + this.AddPassiveMasterSkillDefinition(SkillNumber.CrossbowMastery, Stats.CrossBowMasteryBonusDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.CrossbowStrengthener); + this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldMasteryHighElf, Stats.BonusDefenseRateWithShield, AggregateType.AddRaw, Formula1806, 3, 3, SkillNumber.ShieldStrengthenerHighElf); + this.AddMasterSkillDefinition(SkillNumber.InfinityArrowStr, SkillNumber.InfinityArrow, SkillNumber.Undefined, 3, 5, SkillNumber.InfinityArrow, 20, $"{Formula120} / 100", Formula120, Stats.InfinityArrowStrMultiplier, AggregateType.AddRaw); this.AddPassiveMasterSkillDefinition(SkillNumber.MinimumAttPowerInc, Stats.MinimumPhysBaseDmg, AggregateType.AddRaw, Formula502, 5, 3); // SUM - this.AddMasterSkillDefinition(SkillNumber.FireTomeStrengthener, SkillNumber.Undefined, SkillNumber.Undefined, 2, 2, SkillNumber.Undefined, 20, Formula632); - this.AddMasterSkillDefinition(SkillNumber.WindTomeStrengthener, SkillNumber.Undefined, SkillNumber.Undefined, 2, 2, SkillNumber.Undefined, 20, Formula632); - this.AddMasterSkillDefinition(SkillNumber.LightningTomeStren, SkillNumber.Undefined, SkillNumber.Undefined, 2, 2, SkillNumber.Undefined, 20, Formula632); + this.AddPassiveMasterSkillDefinition(SkillNumber.FireTomeStrengthener, Stats.ExplosionBonusDmg, AggregateType.AddRaw, Formula632, 2, 2); + this.AddPassiveMasterSkillDefinition(SkillNumber.WindTomeStrengthener, Stats.RequiemBonusDmg, AggregateType.AddRaw, Formula632, 2, 2); + this.AddPassiveMasterSkillDefinition(SkillNumber.LightningTomeStren, Stats.PollutionBonusDmg, AggregateType.AddRaw, Formula632, 2, 2); this.AddMasterSkillDefinition(SkillNumber.FireTomeMastery, SkillNumber.FireTomeStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula181); this.AddMasterSkillDefinition(SkillNumber.WindTomeMastery, SkillNumber.WindTomeStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula120); this.AddMasterSkillDefinition(SkillNumber.LightningTomeMastery, SkillNumber.LightningTomeStren, SkillNumber.Undefined, 2, 3, SkillNumber.Undefined, 20, Formula181); this.AddMasterSkillDefinition(SkillNumber.SleepStrengthener, SkillNumber.Sleep, SkillNumber.Undefined, 2, 3, SkillNumber.Sleep, 20, Formula120); this.AddMasterSkillDefinition(SkillNumber.ChainLightningStr, SkillNumber.ChainLightning, SkillNumber.Undefined, 2, 4, SkillNumber.ChainLightning, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.LightningShockStr, SkillNumber.LightningShock, SkillNumber.Undefined, 2, 4, SkillNumber.LightningShock, 20, Formula502); - this.AddPassiveMasterSkillDefinition(SkillNumber.MagicMasterySummoner, Stats.WizardryBaseDmg, AggregateType.AddRaw, Formula502, 5, 2); // todo? curse AND wiz bonus, + this.AddPassiveMasterSkillDefinition(SkillNumber.MagicMasterySummoner, Stats.WizardryAndCurseDmgBonus, AggregateType.AddRaw, Formula502, 5, 2); this.AddMasterSkillDefinition(SkillNumber.DrainLifeStrengthener, SkillNumber.DrainLife, SkillNumber.Undefined, 2, 5, SkillNumber.DrainLife, 20, Formula502); this.AddPassiveMasterSkillDefinition(SkillNumber.StickStrengthener, Stats.StickBonusBaseDamage, AggregateType.AddRaw, Formula502, 2, 3); - this.AddMasterSkillDefinition(SkillNumber.OtherWorldTomeStreng, SkillNumber.Undefined, SkillNumber.Undefined, 3, 2, SkillNumber.Undefined, 20, Formula632); - this.AddPassiveMasterSkillDefinition(SkillNumber.StickMastery, Stats.StickBonusBaseDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.StickStrengthener); // todo: only PVP - this.AddPassiveMasterSkillDefinition(SkillNumber.OtherWorldTomeMastery, Stats.AttackSpeed, AggregateType.AddRaw, Formula1, 3, 3, SkillNumber.OtherWorldTomeStreng, SkillNumber.Undefined, 10); - this.AddMasterSkillDefinition(SkillNumber.BerserkerStrengthener, SkillNumber.Berserker, SkillNumber.Undefined, 3, 4, SkillNumber.Berserker, 20, Formula181); - this.AddMasterSkillDefinition(SkillNumber.BerserkerProficiency, SkillNumber.BerserkerStrengthener, SkillNumber.Undefined, 3, 5, SkillNumber.Undefined, 20, Formula181); - this.AddPassiveMasterSkillDefinition(SkillNumber.MinimumWizCurseInc, Stats.MinimumCurseBaseDmg, AggregateType.AddRaw, Formula502, 5, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.OtherWorldTomeStreng, Stats.BookBonusBaseDamage, AggregateType.AddRaw, Formula632, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.StickMastery, Stats.StickMasteryBonusDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.StickStrengthener); + this.AddPassiveMasterSkillDefinition(SkillNumber.OtherWorldTomeMastery, Stats.WeaponMasteryAttackSpeed, AggregateType.AddRaw, Formula1, 3, 3, SkillNumber.OtherWorldTomeStreng, SkillNumber.Undefined, 10); + this.AddMasterSkillDefinition(SkillNumber.BerserkerStrengthener, SkillNumber.Berserker, SkillNumber.Undefined, 3, 4, SkillNumber.Berserker, 20, Formula181, Formula181, Stats.BerserkerCurseMultiplier, AggregateType.AddRaw); + this.AddMasterSkillDefinition(SkillNumber.BerserkerProficiency, SkillNumber.BerserkerStrengthener, SkillNumber.Undefined, 3, 5, SkillNumber.Berserker, 20, $"{Formula181} / 100", Formula181, Stats.BerserkerProficiencyMultiplier, AggregateType.AddRaw); + this.AddPassiveMasterSkillDefinition(SkillNumber.MinimumWizCurseInc, Stats.MinWizardryAndCurseDmgBonus, AggregateType.AddRaw, Formula502, 5, 3); // MG this.AddMasterSkillDefinition(SkillNumber.CycloneStrengthenerDuelMaster, SkillNumber.Cyclone, SkillNumber.Undefined, 2, 2, SkillNumber.Cyclone, 20, Formula502); @@ -748,7 +752,7 @@ private void InitializeMasterSkillData() this.AddMasterSkillDefinition(SkillNumber.PowerSlashStreng, SkillNumber.PowerSlash, SkillNumber.Undefined, 2, 2, SkillNumber.PowerSlash, 20, Formula632); this.AddMasterSkillDefinition(SkillNumber.FlameStrengthenerDuelMaster, SkillNumber.Flame, SkillNumber.Undefined, 2, 3, SkillNumber.Flame, 20, Formula632); this.AddMasterSkillDefinition(SkillNumber.BlastStrengthenerDuelMaster, SkillNumber.Cometfall, SkillNumber.LightningStrengthenerDuelMaster, 2, 3, SkillNumber.Cometfall, 20, Formula502); - this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryDuelMaster, Stats.PhysicalBaseDmg, AggregateType.AddRaw, Formula502, 3, 2, SkillNumber.TwistingSlashStrengthenerDuelMaster, SkillNumber.PowerSlashStreng); + this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryDuelMaster, Stats.MasterSkillPhysBonusDmg, AggregateType.AddRaw, Formula502, 3, 2, SkillNumber.TwistingSlashStrengthenerDuelMaster, SkillNumber.PowerSlashStreng); this.AddMasterSkillDefinition(SkillNumber.InfernoStrengthenerDuelMaster, SkillNumber.Inferno, SkillNumber.FlameStrengthenerDuelMaster, 2, 4, SkillNumber.Inferno, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.EvilSpiritStrengthenerDuelMaster, SkillNumber.EvilSpirit, SkillNumber.Undefined, 2, 4, SkillNumber.EvilSpirit, 20, Formula502); this.AddPassiveMasterSkillDefinition(SkillNumber.MagicMasteryDuelMaster, Stats.WizardryBaseDmg, AggregateType.AddRaw, Formula502, 4, 2, SkillNumber.EvilSpiritStrengthenerDuelMaster); @@ -758,24 +762,25 @@ private void InitializeMasterSkillData() // DL this.AddMasterSkillDefinition(SkillNumber.FireBurstStreng, SkillNumber.FireBurst, SkillNumber.Undefined, 2, 2, SkillNumber.FireBurst, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.ForceWaveStreng, SkillNumber.Force, SkillNumber.Undefined, 2, 2, SkillNumber.Force, 20, Formula632); + this.AddMasterSkillDefinition((SkillNumber)5090, SkillNumber.Force, SkillNumber.Undefined, 2, 2, SkillNumber.ForceWave, 20, Formula632); this.AddPassiveMasterSkillDefinition(SkillNumber.DarkHorseStreng1, Stats.BonusDefenseWithHorse, AggregateType.AddRaw, Formula1204, 2, 2); this.AddMasterSkillDefinition(SkillNumber.CriticalDmgIncPowUp, SkillNumber.IncreaseCriticalDamage, SkillNumber.Undefined, 2, 3, SkillNumber.IncreaseCriticalDamage, 20, Formula632); this.AddMasterSkillDefinition(SkillNumber.EarthshakeStreng, SkillNumber.Earthshake, SkillNumber.DarkHorseStreng1, 2, 3, SkillNumber.Earthshake, 20, Formula502); - this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryLordEmperor, Stats.PhysicalBaseDmg, AggregateType.AddRaw, Formula502, 3, 2); + this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryLordEmperor, Stats.MasterSkillPhysBonusDmg, AggregateType.AddRaw, Formula502, 3, 2); this.AddMasterSkillDefinition(SkillNumber.FireBurstMastery, SkillNumber.FireBurstStreng, SkillNumber.Undefined, 2, 4, SkillNumber.FireBurst, 20, Formula120); this.AddMasterSkillDefinition(SkillNumber.CritDmgIncPowUp2, SkillNumber.CriticalDmgIncPowUp, SkillNumber.Undefined, 2, 4, SkillNumber.IncreaseCriticalDamage, 20, Formula803); this.AddMasterSkillDefinition(SkillNumber.EarthshakeMastery, SkillNumber.EarthshakeStreng, SkillNumber.Undefined, 2, 4, SkillNumber.Earthshake, 20, Formula120); this.AddMasterSkillDefinition(SkillNumber.CritDmgIncPowUp3, SkillNumber.CritDmgIncPowUp2, SkillNumber.Undefined, 2, 5, SkillNumber.IncreaseCriticalDamage, 20, Formula181); this.AddMasterSkillDefinition(SkillNumber.FireScreamStren, SkillNumber.FireScream, SkillNumber.Undefined, 2, 5, SkillNumber.FireScream, 20, Formula502); - this.AddPassiveMasterSkillDefinition(SkillNumber.DarkSpiritStr, Stats.RavenBaseDamage, AggregateType.AddRaw, Formula632, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.ScepterStrengthener, Stats.ScepterBonusBaseDamage, AggregateType.AddRaw, Formula502, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.DarkSpiritStr, Stats.RavenBonusDamage, AggregateType.AddRaw, Formula632, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.ScepterStrengthener, Stats.ScepterStrBonusDamage, AggregateType.AddRaw, Formula502, 2, 3); this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldStrengthenerLordEmperor, Stats.BonusDefenseWithShield, AggregateType.AddRaw, Formula803, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.UseScepterPetStr, Stats.ScepterPetBonusBaseDamage, AggregateType.AddRaw, Formula632, 2, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.DarkSpiritStr2, Stats.RavenCriticalDamageChanceBonus, AggregateType.AddRaw, $"{Formula181} / 100", Formula181, 3, 3, SkillNumber.DarkSpiritStr); - this.AddPassiveMasterSkillDefinition(SkillNumber.ScepterMastery, Stats.ScepterBonusBaseDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.ScepterStrengthener); // todo pvp - this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldMastery, Stats.BonusDefenseWithShield, AggregateType.AddRaw, Formula1204, 3, 3, SkillNumber.ShieldStrengthenerLordEmperor); - this.AddPassiveMasterSkillDefinition(SkillNumber.CommandAttackInc, Stats.BonusDefenseWithScepterCmdDiv, AggregateType.AddRaw, $"1 / ({Formula3822})", Formula3822, 3, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.DarkSpiritStr3, Stats.RavenExcDamageChanceBonus, AggregateType.AddRaw, $"{Formula120} / 100", Formula120,5, 3, SkillNumber.DarkSpiritStr2); + this.AddPassiveMasterSkillDefinition(SkillNumber.UseScepterPetStr, Stats.ScepterPetBonusDamage, AggregateType.AddRaw, Formula632, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.DarkSpiritStr2, Stats.RavenCriticalDamageChance, AggregateType.AddRaw, $"{Formula181} / 100", Formula181, 3, 3, SkillNumber.DarkSpiritStr); + this.AddPassiveMasterSkillDefinition(SkillNumber.ScepterMastery, Stats.ScepterMasteryBonusDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.ScepterStrengthener); + this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldMastery, Stats.BonusDefenseRateWithShield, AggregateType.AddRaw, Formula1204, 3, 3, SkillNumber.ShieldStrengthenerLordEmperor); + this.AddPassiveMasterSkillDefinition(SkillNumber.CommandAttackInc, Stats.BonusDamageWithScepterCmdDiv, AggregateType.AddRaw, $"1 / ({Formula3822})", Formula3822, 3, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.DarkSpiritStr3, Stats.RavenExcDamageChance, AggregateType.AddRaw, $"{Formula120} / 100", Formula120, 5, 3, SkillNumber.DarkSpiritStr2); this.AddPassiveMasterSkillDefinition(SkillNumber.PetDurabilityStr, Stats.PetDurationIncrease, AggregateType.Multiplicate, Formula1204, 5, 3); // RF @@ -784,29 +789,31 @@ private void InitializeMasterSkillData() this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseMaximumSd, Stats.MaximumShield, AggregateType.AddRaw, Formula30704, 2, 1); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseManaRecoveryRate, Stats.ManaRecoveryMultiplier, AggregateType.AddRaw, FormulaRecoveryIncrease181, Formula181, 2, 1, SkillNumber.Undefined, SkillNumber.Undefined, 20); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreasePoisonResistance, Stats.PoisonResistance, AggregateType.AddRaw, Formula120Value, Formula120, 2, 1); - this.AddPassiveMasterSkillDefinition(SkillNumber.DurabilityReduction2FistMaster, Stats.ItemDurationIncrease, AggregateType.Multiplicate,Formula1204, 3, 1, SkillNumber.DurabilityReduction1FistMaster); + this.AddPassiveMasterSkillDefinition(SkillNumber.DurabilityReduction2FistMaster, Stats.ItemDurationIncrease, AggregateType.Multiplicate, Formula1204, 3, 1, SkillNumber.DurabilityReduction1FistMaster); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseSdRecoveryRate, Stats.ShieldRecoveryMultiplier, AggregateType.AddRaw, FormulaRecoveryIncrease120, Formula120, 3, 1, SkillNumber.IncreaseMaximumSd, SkillNumber.Undefined, 20); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseHpRecoveryRate, Stats.HealthRecoveryMultiplier, AggregateType.AddRaw, FormulaRecoveryIncrease120, Formula120, 3, 1, SkillNumber.IncreaseManaRecoveryRate, SkillNumber.Undefined, 20); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseLightningResistance, Stats.LightningResistance, AggregateType.AddRaw, Formula120Value, Formula120, 3, 1, requiredSkill1: SkillNumber.IncreasePoisonResistance); - this.AddPassiveMasterSkillDefinition(SkillNumber.IncreasesDefense, Stats.DefenseBase, AggregateType.AddRaw, Formula3371, 4, 1); + this.AddPassiveMasterSkillDefinition(SkillNumber.IncreasesDefense, Stats.DefenseBase, AggregateType.AddFinal, Formula3371, 4, 1); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreasesAgRecoveryRate, Stats.AbilityRecoveryMultiplier, AggregateType.AddRaw, FormulaRecoveryIncrease120, Formula120, 4, 1, SkillNumber.IncreaseHpRecoveryRate, SkillNumber.Undefined, 20); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseIceResistance, Stats.IceResistance, AggregateType.AddRaw, Formula120Value, Formula120, 4, 1, requiredSkill1: SkillNumber.IncreaseLightningResistance); this.AddPassiveMasterSkillDefinition(SkillNumber.DurabilityReduction3FistMaster, Stats.ItemDurationIncrease, AggregateType.Multiplicate, Formula1204, 5, 1, SkillNumber.DurabilityReduction2FistMaster); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseDefenseSuccessRate, Stats.DefenseRatePvm, AggregateType.Multiplicate, FormulaIncreaseMultiplicator120, Formula120, 5, 1, SkillNumber.IncreasesDefense, SkillNumber.Undefined, 20); - this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseAttackSuccessRate, Stats.AttackRatePvm, AggregateType.AddRaw, Formula20469, 1, 2); + this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseAttackSuccessRate, Stats.AttackRatePvm, AggregateType.AddFinal, Formula20469, 1, 2); this.AddMasterSkillDefinition(SkillNumber.KillingBlowStrengthener, SkillNumber.Undefined, SkillNumber.Undefined, 2, 2, SkillNumber.KillingBlow, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.BeastUppercutStrengthener, SkillNumber.Undefined, SkillNumber.Undefined, 2, 2, SkillNumber.BeastUppercut, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.KillingBlowMastery, SkillNumber.KillingBlowStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.KillingBlow, 20, Formula120); this.AddMasterSkillDefinition(SkillNumber.BeastUppercutMastery, SkillNumber.BeastUppercutStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.BeastUppercut, 20, Formula120); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseMaximumHp, Stats.MaximumHealth, AggregateType.AddRaw, Formula5418, 4, 2); - this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryFistMaster, Stats.PhysicalBaseDmg, AggregateType.AddRaw, Formula502, 4, 2); + this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryFistMaster, Stats.MasterSkillPhysBonusDmg, AggregateType.AddRaw, Formula502, 4, 2); this.AddMasterSkillDefinition(SkillNumber.ChainDriveStrengthener, SkillNumber.ChainDrive, SkillNumber.Undefined, 2, 5, SkillNumber.ChainDrive, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.DarkSideStrengthener, SkillNumber.DarkSide, SkillNumber.Undefined, 2, 5, SkillNumber.DarkSide, 20, Formula502); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreaseMaximumMana, Stats.MaximumMana, AggregateType.AddRaw, Formula5418, 5, 2, SkillNumber.IncreaseMaximumHp); this.AddMasterSkillDefinition(SkillNumber.DragonRoarStrengthener, SkillNumber.DragonRoar, SkillNumber.Undefined, 2, 5, SkillNumber.DragonRoar, 20, Formula502); this.AddPassiveMasterSkillDefinition(SkillNumber.IncreasePvPAttackRate, Stats.AttackRatePvp, AggregateType.AddRaw, Formula32751, 1, 3); - this.AddPassiveMasterSkillDefinition(SkillNumber.EquippedWeaponStrengthener, Stats.GloveWeaponBonusBaseDamage, AggregateType.AddRaw, Formula502, 2, 3); + this.AddPassiveMasterSkillDefinition(SkillNumber.EquippedWeaponStrengthener, Stats.GloveWeaponBonusDamage, AggregateType.AddRaw, Formula502, 2, 3); this.AddMasterSkillDefinition(SkillNumber.DefSuccessRateIncPowUp, SkillNumber.IncreaseBlock, SkillNumber.Undefined, 3, 2, SkillNumber.IncreaseBlock, 20, Formula502); + + // todo: Increases the probability of Double Damage while using gloves according to the assigned Skill Level. this.AddMasterSkillDefinition(SkillNumber.EquippedWeaponMastery, SkillNumber.EquippedWeaponStrengthener, SkillNumber.Undefined, 3, 3, SkillNumber.Undefined, 20, Formula120); this.AddMasterSkillDefinition(SkillNumber.DefSuccessRateIncMastery, SkillNumber.DefSuccessRateIncPowUp, SkillNumber.Undefined, 3, 3, SkillNumber.IncreaseBlock, 20, Formula502); this.AddMasterSkillDefinition(SkillNumber.StaminaIncreaseStrengthener, SkillNumber.IncreaseHealth, SkillNumber.Undefined, 3, 4, SkillNumber.IncreaseHealth, 20, Formula1154); @@ -827,12 +834,12 @@ private void AddPassiveMasterSkillDefinition(SkillNumber skillNumber, AttributeD this.AddMasterSkillDefinition(skillNumber, requiredSkill1, requiredSkill2, root, rank, SkillNumber.Undefined, maximumLevel, valueFormula, valueFormula, targetAttribute, aggregateType); } - private void AddMasterSkillDefinition(SkillNumber skillNumber, SkillNumber requiredSkill1, SkillNumber requiredSkill2, byte root, byte rank, SkillNumber regularSkill, byte maximumLevel, string valueFormula) + private void AddMasterSkillDefinition(SkillNumber skillNumber, SkillNumber requiredSkill1, SkillNumber requiredSkill2, byte root, byte rank, SkillNumber regularSkill, byte maximumLevel, string valueFormula, bool extendsDuration = false) { - this.AddMasterSkillDefinition(skillNumber, requiredSkill1, requiredSkill2, root, rank, regularSkill, maximumLevel, valueFormula, valueFormula, null, AggregateType.AddRaw); + this.AddMasterSkillDefinition(skillNumber, requiredSkill1, requiredSkill2, root, rank, regularSkill, maximumLevel, valueFormula, valueFormula, null, AggregateType.AddRaw, extendsDuration); } - private void AddMasterSkillDefinition(SkillNumber skillNumber, SkillNumber requiredSkill1, SkillNumber requiredSkill2, byte root, byte rank, SkillNumber regularSkill, byte maximumLevel, string valueFormula, string displayValueFormula, AttributeDefinition? targetAttribute, AggregateType aggregateType) + private void AddMasterSkillDefinition(SkillNumber skillNumber, SkillNumber requiredSkill1, SkillNumber requiredSkill2, byte root, byte rank, SkillNumber regularSkill, byte maximumLevel, string valueFormula, string displayValueFormula, AttributeDefinition? targetAttribute, AggregateType aggregateType, bool extendsDuration = false) { var skill = this.GameConfiguration.Skills.First(s => s.Number == (short)skillNumber); skill.MasterDefinition = this.Context.CreateNew(); @@ -844,6 +851,7 @@ private void AddMasterSkillDefinition(SkillNumber skillNumber, SkillNumber requi skill.MasterDefinition.TargetAttribute = targetAttribute?.GetPersistent(this.GameConfiguration); skill.MasterDefinition.Aggregation = aggregateType; skill.MasterDefinition.ReplacedSkill = this.GameConfiguration.Skills.FirstOrDefault(s => s.Number == (short)regularSkill); + skill.MasterDefinition.ExtendsDuration = extendsDuration; if (requiredSkill1 != SkillNumber.Undefined) { skill.MasterDefinition.RequiredMasterSkills.Add(this.GameConfiguration.Skills.First(s => s.Number == (short)requiredSkill1)); diff --git a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/AccountInitializerBase.cs b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/AccountInitializerBase.cs index 1d77d89a3..324a01a2b 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/AccountInitializerBase.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/AccountInitializerBase.cs @@ -544,6 +544,16 @@ protected Item CreateWeapon(byte itemSlot, byte group, byte number, byte level, .First(o => o.OptionType == ItemOptionTypes.Option); optionLink.Level = optionLevel; weapon.ItemOptions.Add(optionLink); + + if (group == 0 && weapon.Definition.BasePowerUpAttributes.Any(bpua => bpua.TargetAttribute == Stats.StaffRise)) + { + // Double item option MG sword + var doubleOptionLink = this.Context.CreateNew(); + doubleOptionLink.ItemOption = weapon.Definition.PossibleItemOptions.SelectMany(o => o.PossibleOptions) + .First(o => o != optionLink.ItemOption); + doubleOptionLink.Level = optionLevel; + weapon.ItemOptions.Add(doubleOptionLink); + } } if (luck) @@ -609,6 +619,26 @@ protected Item CreateFenrir(byte itemSlot, ItemOptionType? color = null) return fenrir; } + /// + /// Creates the horse. + /// + /// The item slot. + /// The created dark horse. + protected Item CreateHorse(byte itemSlot) + { + var horse = this.CreatePet(itemSlot, 4); + + var options = horse.Definition!.PossibleItemOptions.First().PossibleOptions.Where(p => p.OptionType == ItemOptionTypes.DarkHorse); + foreach (var option in options) + { + var optionLink = this.Context.CreateNew(); + optionLink.ItemOption = option; + horse.ItemOptions.Add(optionLink); + } + + return horse; + } + /// /// Creates the pet. /// @@ -620,6 +650,7 @@ protected Item CreatePet(byte itemSlot, byte itemNumber) var pet = this.Context.CreateNew(); pet.Definition = this.GameConfiguration.Items.First(def => def.Group == 13 && def.Number == itemNumber); pet.Durability = 255; + pet.Level = 1; pet.ItemSlot = itemSlot; if (pet.Definition?.Skill != null) { diff --git a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Ancient.cs b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Ancient.cs index 1c75669d2..e49949e3f 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Ancient.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Ancient.cs @@ -44,7 +44,7 @@ protected override Character CreateDarkLord() character.Inventory.Items.Add(this.CreateFullAncient(InventoryConstants.PendantSlot, ItemGroups.Misc1, 25, 0, "Broy")); // Broy Pendant of Ice character.Inventory.Items.Add(this.CreateFullAncient(InventoryConstants.Ring1Slot, ItemGroups.Misc1, 9, 0, "Agnis")); // Agnis Ring of Poison character.Inventory.Items.Add(this.CreateWings(InventoryConstants.WingsSlot, 30, 13, 13)); // Cape +13 - character.Inventory.Items.Add(this.CreatePet(InventoryConstants.PetSlot, 4)); // Horse + character.Inventory.Items.Add(this.CreateHorse(InventoryConstants.PetSlot)); this.AddDarkLordItems(character.Inventory); this.AddTestJewelsAndPotions(character.Inventory); diff --git a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/GameMaster.cs b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/GameMaster.cs index 8f6524d59..d9583b04f 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/GameMaster.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/GameMaster.cs @@ -53,7 +53,7 @@ protected override Character CreateDarkLord() character.LevelUpPoints = 2000; character.MasterLevelUpPoints = 100; // To test master skill tree - character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 2, 13, 15, 4, true, true, Stats.ExcellentDamageChance)); // Exc AA Scepter+15+16+L+ExcDmg + character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 2, 13, 15, 4, true, true)); // AA Scepter+15+16+L character.Inventory.Items.Add(this.CreateFullAncient(InventoryConstants.ArmorSlot, ItemGroups.Armor, 26, 15, "Agnis")); // Agnis Armor+13+16+L character.Inventory.Items.Add(this.CreateFullAncient(InventoryConstants.HelmSlot, ItemGroups.Helm, 26, 15, "Agnis")); // Agnis Helm+13+16+L character.Inventory.Items.Add(this.CreateFullAncient(InventoryConstants.PantsSlot, ItemGroups.Pants, 26, 15, "Broy")); // Broy Pants+13+16+L @@ -63,8 +63,7 @@ protected override Character CreateDarkLord() character.Inventory.Items.Add(this.CreateFullAncient(InventoryConstants.Ring1Slot, ItemGroups.Misc1, 9, 0, "Agnis")); // Agnis Ring of Poison character.Inventory.Items.Add(this.CreateFullOptionJewellery(InventoryConstants.Ring2Slot, 9)); // Ring of Poison character.Inventory.Items.Add(this.CreateWings(InventoryConstants.WingsSlot, 40, 15)); // Cape of Emperor +15 - - character.Inventory.Items.Add(this.CreatePet(InventoryConstants.PetSlot, 4)); // Horse + character.Inventory.Items.Add(this.CreateHorse(InventoryConstants.PetSlot)); this.AddDarkLordItems(character.Inventory); diff --git a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/GameMaster2.cs b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/GameMaster2.cs index ec5edc4b5..bcb4135e5 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/GameMaster2.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/GameMaster2.cs @@ -55,7 +55,7 @@ protected Character CreateSummoner() character.LevelUpPoints = 2000; character.MasterLevelUpPoints = 100; // To test master skill tree - character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 5, 36, 15, 4, true, true, Stats.ExcellentDamageChance)); // Exc AA Stick+15+16+L+ExcDmg + character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 5, 36, 15, 4, true, true)); // AA Stick+15+16+L character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.RightHandSlot, 5, 23, 15, 4, true, true, Stats.ExcellentDamageChance)); // Exc Book of Lagle+15+16+L+ExcDmg character.Inventory.Items.Add(this.CreateFullAncient(InventoryConstants.ArmorSlot, ItemGroups.Armor, 40, 15, "Semeden")); // Sememden Armor+16+L character.Inventory.Items.Add(this.CreateFullAncient(InventoryConstants.HelmSlot, ItemGroups.Helm, 40, 15, "Semeden")); // Sememden Helm+15+16+L diff --git a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Level300.cs b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Level300.cs index 6bf0e5bc6..ea90d572d 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Level300.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Level300.cs @@ -38,12 +38,12 @@ protected override Character CreateDarkLord() character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 2, 12, 13, 4, true, true, Stats.ExcellentDamageChance)); // Exc Great Lord Scepter+13+16+L+ExcDmg character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.HelmSlot, 26, 7, Stats.MaximumHealth, 13, 4, true)); // Exc Ada Helm+13+16+L - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 26, 8, Stats.DamageReceiveDecrement, 13, 4, true)); // Exc Ada Armor+13+16+L + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 26, 8, Stats.ArmorDamageDecrease, 13, 4, true)); // Exc Ada Armor+13+16+L character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.PantsSlot, 26, 9, Stats.MoneyAmountRate, 13, 4, true)); // Exc Ada Pants+13+16+L character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.GlovesSlot, 26, 10, Stats.MaximumMana, 13, 4, true)); // Exc Ada Gloves+13+16+L character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.BootsSlot, 26, 11, Stats.DamageReflection, 13, 4, true)); // Exc Ada Boots+13+16+L character.Inventory.Items.Add(this.CreateWings(InventoryConstants.WingsSlot, 30, 13, 13)); // Cape +13 - character.Inventory.Items.Add(this.CreatePet(InventoryConstants.PetSlot, 4)); // Horse + character.Inventory.Items.Add(this.CreateHorse(InventoryConstants.PetSlot)); this.AddDarkLordItems(character.Inventory); this.AddTestJewelsAndPotions(character.Inventory); @@ -63,7 +63,7 @@ protected override Character CreateKnight() character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 0, 0, 13, 4, true, false, Stats.ExcellentDamageChance)); // Exc Kris+13+16+L+ExcDmg character.Inventory.Items.Add(this.CreateWeapon(InventoryConstants.RightHandSlot, 0, 5, 13, 4, true, true, Stats.ExcellentDamageChance)); // Exc Blade+13+16+L+ExcDmg - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 6, 8, Stats.DamageReceiveDecrement, 13, 4, true)); // Exc Scale Armor+13+16+L + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 6, 8, Stats.ArmorDamageDecrease, 13, 4, true)); // Exc Scale Armor+13+16+L character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.HelmSlot, 6, 7, Stats.MaximumHealth, 13, 4, true)); // Exc Scale Helm+13+16+L character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.PantsSlot, 6, 9, Stats.MoneyAmountRate, 13, 4, true)); // Exc Scale Pants+13+16+L character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.GlovesSlot, 6, 10, Stats.MaximumMana, 13, 4, true)); // Exc Scale Gloves+13+16+L diff --git a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Level400.cs b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Level400.cs index 9c8fff79a..ee92bba16 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Level400.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/Level400.cs @@ -50,7 +50,7 @@ protected override Character CreateDarkLord() character.LevelUpPoints -= 2000; // for the added strength and agility character.MasterLevelUpPoints = 100; // To test master skill tree - character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 2, 13, 15, 4, true, true, Stats.ExcellentDamageChance)); // Exc AA Scepter+15+16+L+ExcDmg + character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 2, 13, 15, 4, true, true)); // AA Scepter+15+16+L // Sunlight Set+15+16+L: character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 33, 8, null, 15, 4, true)); @@ -59,8 +59,7 @@ protected override Character CreateDarkLord() character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.GlovesSlot, 33, 10, null, 15, 4, true)); character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.BootsSlot, 33, 11, null, 15, 4, true)); character.Inventory.Items.Add(this.CreateWings(InventoryConstants.WingsSlot, 40, 15)); // Cape of Emperor +15 - - character.Inventory.Items.Add(this.CreatePet(InventoryConstants.PetSlot, 4)); // Horse + character.Inventory.Items.Add(this.CreateHorse(InventoryConstants.PetSlot)); this.AddDarkLordItems(character.Inventory); this.AddTestJewelsAndPotions(character.Inventory); @@ -78,7 +77,7 @@ protected override Character CreateKnight() character.LevelUpPoints += 180; // after level 220, one point more character.MasterLevelUpPoints = 100; // To test master skill tree - character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 0, 19, 15, 4, true, true, Stats.ExcellentDamageChance)); // Exc AA Sword+15+16+L+ExcDmg + character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 0, 19, 15, 4, true, true)); // AA Sword+15+16+L character.Inventory.Items.Add(this.CreateWeapon(InventoryConstants.RightHandSlot, 0, 22, 15, 4, true, true)); // Bone Blade+15+16+L // Dragon Knight Set+15+16+L: diff --git a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/QuestBase.cs b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/QuestBase.cs index 52f26323b..20d5a9057 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/QuestBase.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/TestAccounts/QuestBase.cs @@ -50,11 +50,11 @@ protected override Character CreateDarkLord() character.Attributes.First(a => a.Definition == Stats.BaseEnergy).Value += 100; character.LevelUpPoints -= 700; character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 0, 0, 13, 4, true, false, Stats.ExcellentDamageChance)); // Exc Kris+13+16+L+ExcDmg - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 5, 8, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Armor - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.HelmSlot, 5, 7, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Helm - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.PantsSlot, 5, 9, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Pants - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.GlovesSlot, 5, 10, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Gloves - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.BootsSlot, 5, 11, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Boots + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 5, 8, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Armor + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.HelmSlot, 5, 7, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Helm + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.PantsSlot, 5, 9, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Pants + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.GlovesSlot, 5, 10, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Gloves + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.BootsSlot, 5, 11, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Boots this.AddDarkLordItems(character.Inventory); this.AddTestJewelsAndPotions(character.Inventory); @@ -73,11 +73,11 @@ protected override Character CreateKnight() character.LevelUpPoints -= 700; character.Inventory!.Items.Add(this.CreateWeapon(InventoryConstants.LeftHandSlot, 0, 0, 13, 4, true, false, Stats.ExcellentDamageChance)); // Exc Kris+13+16+L+ExcDmg character.Inventory.Items.Add(this.CreateWeapon(InventoryConstants.RightHandSlot, 1, 3, 13, 4, true, true, Stats.ExcellentDamageChance)); // Exc Tomahawk+13+16+L+ExcDmg - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 5, 8, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Armor - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.HelmSlot, 5, 7, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Helm - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.PantsSlot, 5, 9, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Pants - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.GlovesSlot, 5, 10, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Gloves - character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.BootsSlot, 5, 11, Stats.DamageReceiveDecrement, 13, 4, true)); // Leather Boots + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.ArmorSlot, 5, 8, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Armor + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.HelmSlot, 5, 7, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Helm + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.PantsSlot, 5, 9, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Pants + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.GlovesSlot, 5, 10, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Gloves + character.Inventory.Items.Add(this.CreateArmorItem(InventoryConstants.BootsSlot, 5, 11, Stats.ArmorDamageDecrease, 13, 4, true)); // Leather Boots character.Inventory.Items.Add(this.CreateJewel(47, Items.Quest.ScrollOfEmperorNumber)); character.Inventory.Items.Add(this.CreateJewel(48, Items.Quest.BrokenSwordNumber)); this.AddTestJewelsAndPotions(character.Inventory); diff --git a/src/Persistence/Initialization/WingsInitializerBase.cs b/src/Persistence/Initialization/WingsInitializerBase.cs index 09de38071..f5d9f0f25 100644 --- a/src/Persistence/Initialization/WingsInitializerBase.cs +++ b/src/Persistence/Initialization/WingsInitializerBase.cs @@ -57,7 +57,7 @@ protected IEnumerable BuildOptions(params (int, OptionTyp switch (tuple.Item2) { case OptionType.CurseDamage: - yield return this.CreateItemOption(tuple.Item1, Stats.MaximumCurseBaseDmg, 0, AggregateType.AddRaw, 4f, ItemOptionDefinitionNumbers.WingCurse); + yield return this.CreateItemOption(tuple.Item1, Stats.CurseBaseDmg, 0, AggregateType.AddRaw, 4f, ItemOptionDefinitionNumbers.WingCurse); break; case OptionType.Defense: yield return this.CreateItemOption(tuple.Item1, Stats.DefenseBase, 0, AggregateType.AddRaw, 4f, ItemOptionDefinitionNumbers.WingDefense); @@ -66,10 +66,10 @@ protected IEnumerable BuildOptions(params (int, OptionTyp yield return this.CreateItemOption(tuple.Item1, Stats.HealthRecoveryMultiplier, 0, AggregateType.AddRaw, 0.01f, ItemOptionDefinitionNumbers.WingHealthRecover); break; case OptionType.PhysDamage: - yield return this.CreateItemOption(tuple.Item1, Stats.MaximumPhysBaseDmg, 0, AggregateType.AddRaw, 4f, ItemOptionDefinitionNumbers.WingPhysical); + yield return this.CreateItemOption(tuple.Item1, Stats.PhysicalBaseDmg, 0, AggregateType.AddRaw, 4f, ItemOptionDefinitionNumbers.WingPhysical); break; case OptionType.WizDamage: - yield return this.CreateItemOption(tuple.Item1, Stats.MaximumWizBaseDmg, 0, AggregateType.AddRaw, 4f, ItemOptionDefinitionNumbers.WingWizardry); + yield return this.CreateItemOption(tuple.Item1, Stats.WizardryBaseDmg, 0, AggregateType.AddRaw, 4f, ItemOptionDefinitionNumbers.WingWizardry); break; default: throw new ArgumentException("unknown OptionType"); diff --git a/tests/MUnique.OpenMU.Tests/ItemConsumptionTest.cs b/tests/MUnique.OpenMU.Tests/ItemConsumptionTest.cs index 9c90fd2df..69b623648 100644 --- a/tests/MUnique.OpenMU.Tests/ItemConsumptionTest.cs +++ b/tests/MUnique.OpenMU.Tests/ItemConsumptionTest.cs @@ -306,7 +306,7 @@ public async ValueTask DrinkAlcoholSuccessAsync() { new Persistence.BasicModel.PowerUpDefinition { - TargetAttribute = Stats.AttackSpeed, + TargetAttribute = Stats.AttackSpeedAny, Boost = new Persistence.BasicModel.PowerUpDefinitionValue { ConstantValue = { Value = 20 } diff --git a/tests/MUnique.OpenMU.Tests/ItemSerializerTests.cs b/tests/MUnique.OpenMU.Tests/ItemSerializerTests.cs index 675b0383d..a343a4fa7 100644 --- a/tests/MUnique.OpenMU.Tests/ItemSerializerTests.cs +++ b/tests/MUnique.OpenMU.Tests/ItemSerializerTests.cs @@ -303,7 +303,7 @@ private Tuple SerializeAndDeserializeBlade(bool hasSkill = true) item.ItemOptions.Add(excellent1); var excellent2 = context.CreateNew(); excellent2.ItemOption = item.Definition.PossibleItemOptions.SelectMany(def => - def.PossibleOptions.Where(p => p.OptionType == ItemOptionTypes.Excellent && p.PowerUpDefinition!.TargetAttribute == Stats.AttackSpeed)).First(); + def.PossibleOptions.Where(p => p.OptionType == ItemOptionTypes.Excellent && p.PowerUpDefinition!.TargetAttribute == Stats.AttackSpeedAny)).First(); item.ItemOptions.Add(excellent2); var array = new byte[this._itemSerializer.NeededSpace];