baseline: OpenMU upstream b5a0961 (fresh source)

This commit is contained in:
Acentech Dev
2026-07-14 19:00:35 +03:00
parent 450402e47d
commit 36fc125d5c
11968 changed files with 748705 additions and 0 deletions

View File

@@ -0,0 +1,208 @@
// <copyright file="CharacterClassHelper.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
/// <summary>
/// Helper class related to <see cref="CharacterClass"/>.
/// </summary>
public static class CharacterClassHelper
{
private static readonly (CharacterClasses Classes, CharacterClassNumber Number)[] NumberMapping =
{
(CharacterClasses.GrandMaster, CharacterClassNumber.GrandMaster),
(CharacterClasses.SoulMaster, CharacterClassNumber.SoulMaster),
(CharacterClasses.DarkWizard, CharacterClassNumber.DarkWizard),
(CharacterClasses.BladeMaster, CharacterClassNumber.BladeMaster),
(CharacterClasses.BladeKnight, CharacterClassNumber.BladeKnight),
(CharacterClasses.DarkKnight, CharacterClassNumber.DarkKnight),
(CharacterClasses.HighElf, CharacterClassNumber.HighElf),
(CharacterClasses.MuseElf, CharacterClassNumber.MuseElf),
(CharacterClasses.FairyElf, CharacterClassNumber.FairyElf),
(CharacterClasses.DuelMaster, CharacterClassNumber.DuelMaster),
(CharacterClasses.MagicGladiator, CharacterClassNumber.MagicGladiator),
(CharacterClasses.LordEmperor, CharacterClassNumber.LordEmperor),
(CharacterClasses.DarkLord, CharacterClassNumber.DarkLord),
(CharacterClasses.DimensionMaster, CharacterClassNumber.DimensionMaster),
(CharacterClasses.BloodySummoner, CharacterClassNumber.BloodySummoner),
(CharacterClasses.Summoner, CharacterClassNumber.Summoner),
(CharacterClasses.FistMaster, CharacterClassNumber.FistMaster),
(CharacterClasses.RageFighter, CharacterClassNumber.RageFighter),
};
/// <summary>
/// Determines the <see cref="CharacterClass"/>es, depending on the given class ranks which are provided by original configuration files.
/// </summary>
/// <param name="gameConfiguration">The game configuration which contains the character classes.</param>
/// <param name="wizardClass">Class rank of the wizard class.</param>
/// <param name="knightClass">Class rank of the knight class.</param>
/// <param name="elfClass">Class rank of the elf class.</param>
/// <param name="magicGladiatorClass">Class rank of the magic gladiator class.</param>
/// <param name="darkLordClass">Class rank of the dark lord class.</param>
/// <param name="summonerClass">Class rank of the summoner class.</param>
/// <param name="ragefighterClass">Class rank of the ragefighter class.</param>
/// <returns>The corresponding <see cref="CharacterClass"/>es of the provided class ranks.</returns>
[Obsolete("Use the overload with the CharacterClasses enum instead.")]
public static IEnumerable<CharacterClass> DetermineCharacterClasses(this GameConfiguration gameConfiguration, int wizardClass, int knightClass, int elfClass, int magicGladiatorClass, int darkLordClass, int summonerClass, int ragefighterClass)
{
var characterClasses = gameConfiguration.CharacterClasses;
IEnumerable<CharacterClass> DetermineClass(int classValue, CharacterClassNumber masterClass, CharacterClassNumber? secondClass, CharacterClassNumber firstClass)
{
if (classValue > 0)
{
if (characterClasses.FirstOrDefault(c => c.Number == (int)masterClass) is { } master)
{
yield return master;
}
if (classValue < 3)
{
if (secondClass is { } && characterClasses.FirstOrDefault(c => c.Number == (int)secondClass) is { } second)
{
yield return second;
}
if (characterClasses.FirstOrDefault(c => c.Number == (int)firstClass) is { } first)
{
yield return first;
}
}
}
}
var result = new List<CharacterClass>();
result.AddRange(DetermineClass(wizardClass, CharacterClassNumber.GrandMaster, CharacterClassNumber.SoulMaster, CharacterClassNumber.DarkWizard));
result.AddRange(DetermineClass(knightClass, CharacterClassNumber.BladeMaster, CharacterClassNumber.BladeKnight, CharacterClassNumber.DarkKnight));
result.AddRange(DetermineClass(elfClass, CharacterClassNumber.HighElf, CharacterClassNumber.MuseElf, CharacterClassNumber.FairyElf));
result.AddRange(DetermineClass(magicGladiatorClass, CharacterClassNumber.DuelMaster, null, CharacterClassNumber.MagicGladiator));
result.AddRange(DetermineClass(darkLordClass, CharacterClassNumber.LordEmperor, null, CharacterClassNumber.DarkLord));
result.AddRange(DetermineClass(summonerClass, CharacterClassNumber.DimensionMaster, CharacterClassNumber.BloodySummoner, CharacterClassNumber.Summoner));
result.AddRange(DetermineClass(ragefighterClass, CharacterClassNumber.FistMaster, null, CharacterClassNumber.RageFighter));
return result;
}
/// <summary>
/// Determines the <see cref="CharacterClass" />es, depending on the given class ranks which are provided by original configuration files.
/// </summary>
/// <param name="gameConfiguration">The game configuration which contains the character classes.</param>
/// <param name="classes">The flags enum of character classes.</param>
/// <param name="ignoreMissing">If set to <c>true</c>, missing classes are ignored and throw no exception.</param>
/// <returns>
/// The corresponding <see cref="CharacterClass" />es of the provided class ranks.
/// </returns>
public static IEnumerable<CharacterClass> DetermineCharacterClasses(this GameConfiguration gameConfiguration, CharacterClasses classes, bool ignoreMissing = false)
{
var characterClasses = gameConfiguration.CharacterClasses;
foreach (var characterClassNumber in NumberMapping.Where(c => classes.HasFlag(c.Classes)).Select(c => c.Number))
{
yield return characterClasses.First(c => c.Number == (int)characterClassNumber);
}
}
/// <summary>
/// Determines the <see cref="CharacterClass"/>es, depending on the given classes which are provided by original configuration files.
/// </summary>
/// <param name="gameConfiguration">The game configuration which contains the character classes.</param>
/// <param name="wizardClass">Class of the wizard class.</param>
/// <param name="knightClass">Class of the knight class.</param>
/// <param name="elfClass">Class of the elf class.</param>
/// <returns>The corresponding <see cref="CharacterClass"/>es of the provided class ranks.</returns>
public static IEnumerable<CharacterClass> DetermineCharacterClasses(this GameConfiguration gameConfiguration, bool wizardClass, bool knightClass, bool elfClass)
{
var characterClasses = gameConfiguration.CharacterClasses;
if (wizardClass)
{
yield return characterClasses.First(c => c.Number == (int)CharacterClassNumber.DarkWizard);
}
if (knightClass)
{
yield return characterClasses.First(c => c.Number == (int)CharacterClassNumber.DarkKnight);
}
if (elfClass)
{
yield return characterClasses.First(c => c.Number == (int)CharacterClassNumber.FairyElf);
}
}
/// <summary>
/// Creates the attribute relationship.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="gameConfiguration">The game configuration.</param>
/// <param name="targetAttribute">The target attribute.</param>
/// <param name="multiplier">The multiplier.</param>
/// <param name="sourceAttribute">The source attribute.</param>
/// <param name="inputOperator">The input operator.</param>
/// <param name="aggregateType">The aggregate type with which the relationship will effect the <paramref name="targetAttribute"/>.</param>
/// <returns>The attribute relationship.</returns>
public static AttributeRelationship CreateAttributeRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, float multiplier, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply, AggregateType aggregateType = AggregateType.AddRaw)
{
return context.CreateNew<AttributeRelationship>(
targetAttribute.GetPersistent(gameConfiguration) ?? targetAttribute,
multiplier,
sourceAttribute.GetPersistent(gameConfiguration) ?? sourceAttribute,
inputOperator,
default(AttributeDefinition?),
aggregateType);
}
/// <summary>
/// Creates the attribute relationship.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="gameConfiguration">The game configuration.</param>
/// <param name="targetAttribute">The target attribute.</param>
/// <param name="multiplierAttribute">The multiplier attribute.</param>
/// <param name="sourceAttribute">The source attribute.</param>
/// <param name="inputOperator">The input operator.</param>
/// <param name="aggregateType">The aggregate type with which the relationship will effect the <paramref name="targetAttribute"/>.</param>
/// <returns>The attribute relationship.</returns>
public static AttributeRelationship CreateAttributeRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, AttributeDefinition multiplierAttribute, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply, AggregateType aggregateType = AggregateType.AddRaw)
{
return context.CreateNew<AttributeRelationship>(
targetAttribute.GetPersistent(gameConfiguration) ?? targetAttribute,
0f,
sourceAttribute.GetPersistent(gameConfiguration) ?? sourceAttribute,
inputOperator,
multiplierAttribute.GetPersistent(gameConfiguration) ?? multiplierAttribute,
aggregateType);
}
/// <summary>
/// Creates the conditional relationship between attributes.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="gameConfiguration">The game configuration.</param>
/// <param name="targetAttribute">The target attribute.</param>
/// <param name="conditionalAttribute">The conditional attribute.</param>
/// <param name="sourceAttribute">The source attribute.</param>
/// <param name="aggregateType">The aggregate type with which the relationship will effect the <paramref name="targetAttribute"/>.</param>
/// <returns>The attribute relationship.</returns>
public static AttributeRelationship CreateConditionalRelationship(IContext context, GameConfiguration gameConfiguration, AttributeDefinition targetAttribute, AttributeDefinition conditionalAttribute, AttributeDefinition sourceAttribute, AggregateType aggregateType = AggregateType.AddRaw)
{
return context.CreateNew<AttributeRelationship>(
targetAttribute.GetPersistent(gameConfiguration) ?? targetAttribute,
conditionalAttribute.GetPersistent(gameConfiguration) ?? conditionalAttribute,
sourceAttribute.GetPersistent(gameConfiguration) ?? sourceAttribute,
aggregateType);
}
/// <summary>
/// Creates the constant value attribute.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="gameConfiguration">The game configuration.</param>
/// <param name="value">The value.</param>
/// <param name="attribute">The attribute.</param>
/// <returns>The constant value attribute.</returns>
public static ConstValueAttribute CreateConstValueAttribute(IContext context, GameConfiguration gameConfiguration, float value, AttributeDefinition attribute)
{
return context.CreateNew<ConstValueAttribute>(value, attribute.GetPersistent(gameConfiguration));
}
}

View File

@@ -0,0 +1,207 @@
// <copyright file="CharacterClassInitialization.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Attributes;
/// <summary>
/// Initialization of character classes data.
/// </summary>
internal partial class CharacterClassInitialization : InitializerBase
{
private const int LorenciaMapId = 0;
private const int NoriaMapId = 3;
private const int ElvenlandMapId = 51;
/// <summary>
/// Initializes a new instance of the <see cref="CharacterClassInitialization" /> class.
/// </summary>
/// <param name="context">The persistence context.</param>
/// <param name="gameConfiguration">The game configuration.</param>
public CharacterClassInitialization(IContext context, GameConfiguration gameConfiguration)
: base(context, gameConfiguration)
{
}
/// <summary>
/// Gets a value indicating whether to use classic PVP, which uses no shield stats and the same attack/defense rate as PvM.
/// </summary>
protected virtual bool UseClassicPvp => false;
/// <summary>
/// Creates the character classes.
/// </summary>
public override void Initialize()
{
var bladeMaster = this.CreateBladeMaster();
var bladeKnight = this.CreateBladeKnight(bladeMaster);
this.CreateDarkKnight(CharacterClassNumber.DarkKnight, "Dark Knight", false, bladeKnight, true);
var grandMaster = this.CreateGrandMaster();
var soulMaster = this.CreateSoulMaster(grandMaster);
this.CreateDarkWizard(CharacterClassNumber.DarkWizard, "Dark Wizard", false, soulMaster, true);
var highElf = this.CreateHighElf();
var museElf = this.CreateMuseElf(highElf);
this.CreateFairyElf(CharacterClassNumber.FairyElf, "Fairy Elf", false, museElf, true);
var dimensionMaster = this.CreateDimensionMaster();
var bloodySummoner = this.CreateBloodySummoner(dimensionMaster);
this.CreateSummoner(CharacterClassNumber.Summoner, "Summoner", false, bloodySummoner, true);
var duelMaster = this.CreateDuelMaster();
this.CreateMagicGladiator(CharacterClassNumber.MagicGladiator, "Magic Gladiator", false, duelMaster, true);
var lordEmperor = this.CreateLordEmperor();
this.CreateDarkLord(CharacterClassNumber.DarkLord, "Dark Lord", false, lordEmperor, true);
var fistMaster = this.CreateFistMaster();
this.CreateRageFighter(CharacterClassNumber.RageFighter, "Rage Fighter", false, fistMaster, true);
}
private StatAttributeDefinition CreateStatAttributeDefinition(AttributeDefinition attribute, int value, bool increasableByPlayer)
{
var definition = this.Context.CreateNew<StatAttributeDefinition>(attribute.GetPersistent(this.GameConfiguration), value, increasableByPlayer);
return definition;
}
private AttributeRelationship CreateAttributeRelationship(AttributeDefinition targetAttribute, float multiplier, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply, AggregateType aggregateType = AggregateType.AddRaw)
{
return CharacterClassHelper.CreateAttributeRelationship(this.Context, this.GameConfiguration, targetAttribute, multiplier, sourceAttribute, inputOperator, aggregateType);
}
private AttributeRelationship CreateAttributeRelationship(AttributeDefinition targetAttribute, AttributeDefinition multiplierAttribute, AttributeDefinition sourceAttribute, InputOperator inputOperator = InputOperator.Multiply, AggregateType aggregateType = AggregateType.AddRaw)
{
return CharacterClassHelper.CreateAttributeRelationship(this.Context, this.GameConfiguration, targetAttribute, multiplierAttribute, sourceAttribute, inputOperator, aggregateType);
}
private AttributeRelationship CreateConditionalRelationship(AttributeDefinition targetAttribute, AttributeDefinition conditionalAttribute, AttributeDefinition sourceAttribute, AggregateType aggregateType = AggregateType.AddRaw)
{
return CharacterClassHelper.CreateConditionalRelationship(this.Context, this.GameConfiguration, targetAttribute, conditionalAttribute, sourceAttribute, aggregateType);
}
private ConstValueAttribute CreateConstValueAttribute(float value, AttributeDefinition attribute)
{
return CharacterClassHelper.CreateConstValueAttribute(this.Context, this.GameConfiguration, value, attribute);
}
private void AddCommonAttributeRelationships(ICollection<AttributeRelationship> 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));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.TotalEnergy, 1, Stats.BaseEnergy));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1, Stats.DefenseShield));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefenseFinal, 0.5f, Stats.DefenseBase));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefensePvm, 1, Stats.DefenseFinal));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefensePvp, 1, Stats.DefenseFinal));
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.MinimumPhysBaseDmg, 1, Stats.MinimumPhysBaseDmgByWeapon));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.MaximumPhysBaseDmgByWeapon));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmg, 1, Stats.BaseMinDamageBonus));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.BaseMaxDamageBonus));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.PhysicalBaseDmg, 1, Stats.BaseDamageBonus, aggregateType: AggregateType.AddFinal));
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.PhysicalBaseDmgIncrease, aggregateType: AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1, Stats.PhysicalBaseDmgIncrease, aggregateType: AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, Stats.SwellLifeHealthIncrease, aggregateType: AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1, Stats.SwellLifeManaIncrease, aggregateType: AggregateType.Multiplicate));
// 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<AttributeDefinition>(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.AttackSpeedAny, Stats.AreTwoWeaponsEquipped, tempSpeed));
var tempDefense = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "Temp Defense Bonus multiplier with Shield", string.Empty);
this.GameConfiguration.Attributes.Add(tempDefense);
attributeRelationships.Add(this.CreateConditionalRelationship(tempDefense, Stats.IsShieldEquipped, Stats.DefenseIncreaseWithEquippedShield));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefenseFinal, 1, tempDefense, InputOperator.Add, AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateConditionalRelationship(Stats.DefenseFinal, Stats.DefenseShield, Stats.ShieldItemDefenseIncrease));
attributeRelationships.Add(this.CreateConditionalRelationship(Stats.DefenseFinal, Stats.IsShieldEquipped, Stats.BonusDefenseWithShield, AggregateType.AddFinal));
attributeRelationships.Add(this.CreateConditionalRelationship(Stats.DefenseRatePvm, Stats.IsShieldEquipped, Stats.BonusDefenseRateWithShield, AggregateType.AddFinal));
var tempInnovDefDec = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "Temp Innovation defense decrement", string.Empty);
this.GameConfiguration.Attributes.Add(tempInnovDefDec);
attributeRelationships.Add(this.CreateAttributeRelationship(tempInnovDefDec, -1, Stats.InnovationDefDecrement));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefenseDecrement, 1, tempInnovDefDec, InputOperator.Add, AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.HealthRecoveryMultiplier, 0.01f, Stats.IsInSafezone));
if (this.UseClassicPvp)
{
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 1, Stats.DefenseRatePvm));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 1, Stats.AttackRatePvm));
}
else
{
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.ShieldRecoveryMultiplier, 0.01f, Stats.IsInSafezone));
}
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumGuildSize, 0.1f, Stats.Level));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.CanFly, 1, Stats.IsDinorantEquipped));
}
private void AddCommonBaseAttributeValues(ICollection<ConstValueAttribute> baseAttributeValues, bool isMaster)
{
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.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.PhysicalBaseDmgIncrease));
baseAttributeValues.Add(this.CreateConstValueAttribute(-1, Stats.AreTwoWeaponsEquipped));
baseAttributeValues.Add(this.CreateConstValueAttribute(-1, Stats.HasDoubleWield));
baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.DefenseDecrement));
baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.SwellLifeHealthIncrease));
baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.SwellLifeManaIncrease));
baseAttributeValues.Add(this.CreateConstValueAttribute(0.1f, Stats.DurabilityReductionFactor));
if (isMaster)
{
baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.MasterPointsPerLevelUp));
baseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.MasterExperienceRate));
}
if (!this.UseClassicPvp)
{
baseAttributeValues.Add(this.CreateConstValueAttribute(0.01f, Stats.ShieldRecoveryMultiplier));
}
}
/// <summary>
/// Adds double wield attribute relationships applicable to characters that can double wield (DK, MG, and RF).
/// A double wield grants 110% physical attack damage (55% base damage, later doubled on damage calculations).
/// </summary>
private void AddDoubleWieldAttributeRelationships(ICollection<AttributeRelationship> attributeRelationships)
{
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.HasDoubleWield, 1, Stats.DoubleWieldWeaponCount, InputOperator.Maximum));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.PhysicalBaseDmgIncrease, 0.55f, Stats.HasDoubleWield, InputOperator.ExponentiateByAttribute, AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateConditionalRelationship(Stats.MinimumPhysBaseDmgByWeapon, Stats.HasDoubleWield, Stats.MinPhysBaseDmgByRightWeapon));
attributeRelationships.Add(this.CreateConditionalRelationship(Stats.MaximumPhysBaseDmgByWeapon, Stats.HasDoubleWield, Stats.MaxPhysBaseDmgByRightWeapon));
// We need to average the base damage of the two weapons and their item option and excellent options.
// For PhysicalBaseDmgIncrease, to avoid using extra attributes, we use ad-hoc AggregateTypes (see ItemPowerUpFactory.GetPowerUpsOfItemOptions())
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MinimumPhysBaseDmgByWeapon, 0.5f, Stats.HasDoubleWield, InputOperator.ExponentiateByAttribute, AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmgByWeapon, 0.5f, Stats.HasDoubleWield, InputOperator.ExponentiateByAttribute, AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.PhysicalBaseDmg, 0.5f, Stats.HasDoubleWield, InputOperator.ExponentiateByAttribute, AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.PhysicalBaseDmgIncrease, 0.5f, Stats.HasDoubleWield, InputOperator.ExponentiateByAttribute, AggregateType.Multiplicate));
attributeRelationships.Add(this.CreateAttributeRelationship(Stats.PhysicalBaseDmgIncrease, 1, Stats.HasDoubleWield));
}
}

View File

@@ -0,0 +1,101 @@
// <copyright file="CharacterClassNumber.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
/// <summary>
/// The default character class numbers.
/// </summary>
public enum CharacterClassNumber : byte
{
/// <summary>
/// The dark wizard.
/// </summary>
DarkWizard = 0,
/// <summary>
/// The soul master.
/// </summary>
SoulMaster = 2,
/// <summary>
/// The grand master.
/// </summary>
GrandMaster = 3,
/// <summary>
/// The dark knight.
/// </summary>
DarkKnight = 4,
/// <summary>
/// The blade knight.
/// </summary>
BladeKnight = 6,
/// <summary>
/// The blade master.
/// </summary>
BladeMaster = 7,
/// <summary>
/// The fairy elf.
/// </summary>
FairyElf = 8,
/// <summary>
/// The muse elf.
/// </summary>
MuseElf = 10,
/// <summary>
/// The high elf.
/// </summary>
HighElf = 11,
/// <summary>
/// The magic gladiator.
/// </summary>
MagicGladiator = 12,
/// <summary>
/// The duel master.
/// </summary>
DuelMaster = 13,
/// <summary>
/// The dark lord.
/// </summary>
DarkLord = 16,
/// <summary>
/// The lord emperor.
/// </summary>
LordEmperor = 17,
/// <summary>
/// The summoner.
/// </summary>
Summoner = 20,
/// <summary>
/// The bloody summoner.
/// </summary>
BloodySummoner = 22,
/// <summary>
/// The dimension master.
/// </summary>
DimensionMaster = 23,
/// <summary>
/// The rage fighter.
/// </summary>
RageFighter = 24,
/// <summary>
/// The fist master.
/// </summary>
FistMaster = 25,
}

View File

@@ -0,0 +1,197 @@
// <copyright file="CharacterClasses.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
/// <summary>
/// Defines the character classes as flags enum.
/// </summary>
[Flags]
public enum CharacterClasses : long
{
/// <summary>
/// None of the classes.
/// </summary>
None = 0,
/// <summary>
/// All of the classes.
/// </summary>
All = 0xFFFFFFFF,
/// <summary>
/// The dark wizard.
/// </summary>
DarkWizard = 0b0000_0001,
/// <summary>
/// The soul master.
/// </summary>
SoulMaster = 0b0000_0010,
/// <summary>
/// The grand master.
/// </summary>
GrandMaster = 0b0000_0100,
/// <summary>
/// The dark knight.
/// </summary>
DarkKnight = 0b0001_0000,
/// <summary>
/// The blade knight.
/// </summary>
BladeKnight = 0b0010_0000,
/// <summary>
/// The blade master.
/// </summary>
BladeMaster = 0b0100_0000,
/// <summary>
/// The fairy elf.
/// </summary>
FairyElf = 0b0001_000_0000,
/// <summary>
/// The muse elf.
/// </summary>
MuseElf = 0b0010_0000_0000,
/// <summary>
/// The high elf.
/// </summary>
HighElf = 0b0100_0000_0000,
/// <summary>
/// The magic gladiator.
/// </summary>
MagicGladiator = 0b0001_0000_0000_0000,
/// <summary>
/// The duel master.
/// </summary>
DuelMaster = 0b0010_0000_0000_0000,
/// <summary>
/// The dark lord.
/// </summary>
DarkLord = 0b0001_0000_0000_0000_0000,
/// <summary>
/// The lord emperor.
/// </summary>
LordEmperor = 0b0010_0000_0000_0000_0000,
/// <summary>
/// The summoner.
/// </summary>
Summoner = 0b0001_0000_0000_0000_0000_0000,
/// <summary>
/// The bloody summoner.
/// </summary>
BloodySummoner = 0b0010_0000_0000_0000_0000_0000,
/// <summary>
/// The dimension master.
/// </summary>
DimensionMaster = 0b0100_0000_0000_0000_0000_0000,
/// <summary>
/// The rage fighter.
/// </summary>
RageFighter = 0b0001_0000_0000_0000_0000_0000_0000,
/// <summary>
/// The fist master.
/// </summary>
FistMaster = 0b0010_0000_0000_0000_0000_0000_0000,
/// <summary>
/// All wizards.
/// </summary>
AllWizards = DarkWizard | SoulMaster | GrandMaster,
/// <summary>
/// All knights.
/// </summary>
AllKnights = DarkKnight | BladeKnight | BladeMaster,
/// <summary>
/// All elfs.
/// </summary>
AllElfs = FairyElf | MuseElf | HighElf,
/// <summary>
/// All summoners.
/// </summary>
AllSummoners = Summoner | BloodySummoner | DimensionMaster,
/// <summary>
/// All magic gladiators.
/// </summary>
AllMGs = MagicGladiator | DuelMaster,
/// <summary>
/// All lords.
/// </summary>
AllLords = DarkLord | LordEmperor,
/// <summary>
/// All fighters.
/// </summary>
AllFighters = RageFighter | FistMaster,
/// <summary>
/// All magicians (wizards and magic gladiators).
/// </summary>
AllMagicians = AllWizards | AllMGs,
/// <summary>
/// All knights, lords and magic gladiators.
/// </summary>
AllKnightsLordsAndMGs = AllKnights | AllLords | AllMGs,
/// <summary>
/// The soul master and grand master.
/// </summary>
SoulMasterAndGrandMaster = SoulMaster | GrandMaster,
/// <summary>
/// The blade knight and blade master.
/// </summary>
BladeKnightAndBladeMaster = BladeKnight | BladeMaster,
/// <summary>
/// The muse elf and high elf.
/// </summary>
MuseElfAndHighElf = MuseElf | HighElf,
/// <summary>
/// The bloody summoner and dimension master.
/// </summary>
BloodySummonerAndDimensionMaster = BloodySummoner | DimensionMaster,
/// <summary>
/// All masters.
/// </summary>
AllMasters = GrandMaster | BladeMaster | HighElf | DimensionMaster | DuelMaster | LordEmperor | FistMaster,
/// <summary>
/// All masters except fist master.
/// </summary>
AllMastersExceptFistMaster = GrandMaster | BladeMaster | HighElf | DimensionMaster | DuelMaster | LordEmperor,
/// <summary>
/// All second classes.
/// </summary>
AllSecondClass = SoulMaster | BladeKnight | MuseElf | BloodySummoner | MagicGladiator | DarkLord | RageFighter,
/// <summary>
/// All masters and second classes.
/// </summary>
AllMastersAndSecondClass = AllMasters | AllSecondClass,
}

View File

@@ -0,0 +1,127 @@
// <copyright file="ClassDarkKnight.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Attributes;
/// <summary>
/// Initialization of character classes data.
/// </summary>
internal partial class CharacterClassInitialization
{
/// <summary>
/// Creates the dark knight.
/// </summary>
/// <param name="number">The number.</param>
/// <param name="name">The name.</param>
/// <param name="isMaster">if set to <c>true</c>, the class is a master class which has access to the master skill tree.</param>
/// <param name="nextGenerationClass">The next generation class.</param>
/// <param name="canGetCreated">If set to <c>true</c>, it can get created by the player.</param>
/// <returns>The created character class.</returns>
protected CharacterClass CreateDarkKnight(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated)
{
var result = this.Context.CreateNew<CharacterClass>();
result.SetGuid((byte)number);
this.GameConfiguration.CharacterClasses.Add(result);
result.CanGetCreated = canGetCreated;
result.HomeMap = this.GameConfiguration.Maps.FirstOrDefault(map => map.Number == LorenciaMapId);
result.Number = (byte)number;
result.Name = name;
result.IsMasterClass = isMaster;
result.NextGenerationClass = nextGenerationClass;
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Level, 1, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.PointsPerLevelUp, 5, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseStrength, 28, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseAgility, 20, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseVitality, 25, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 10, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 110, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 20, 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));
this.AddCommonAttributeRelationships(result.AttributeCombinations);
this.AddDoubleWieldAttributeRelationships(result.AttributeCombinations);
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.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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.15f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 0.5f, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, Stats.TotalLevel));
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.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.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.IsOneHandedSwordEquipped, Stats.WeaponMasteryAttackSpeed));
result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.MaceMasteryStunChance, Stats.IsMaceEquipped, Stats.MasteryStunChance));
result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.DoubleDamageChance, Stats.IsSpearEquipped, Stats.SpearMasteryDoubleDamageChance));
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));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f, Stats.DefenseFinal));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.TotalLevel, 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.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4.5f, Stats.TotalAgility));
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;
}
private CharacterClass CreateBladeMaster()
{
var result = this.CreateDarkKnight(CharacterClassNumber.BladeMaster, "Blade Master", true, null, false);
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.MasterLevel, 0, false));
return result;
}
private CharacterClass CreateBladeKnight(CharacterClass bladeMaster)
{
return this.CreateDarkKnight(CharacterClassNumber.BladeKnight, "Blade Knight", false, bladeMaster, false);
}
}

View File

@@ -0,0 +1,144 @@
// <copyright file="ClassDarkLord.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Attributes;
/// <summary>
/// Initialization of character classes data.
/// </summary>
internal partial class CharacterClassInitialization
{
private CharacterClass CreateLordEmperor()
{
var result = this.CreateDarkLord(CharacterClassNumber.LordEmperor, "Lord Emperor", true, null, false);
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.MasterLevel, 0, false));
return result;
}
private CharacterClass CreateDarkLord(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated)
{
var energyMinus15 = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "TotalEnergy minus 15", "TotalEnergy minus 15");
this.GameConfiguration.Attributes.Add(energyMinus15);
var result = this.Context.CreateNew<CharacterClass>();
result.SetGuid((byte)number);
this.GameConfiguration.CharacterClasses.Add(result);
result.CanGetCreated = canGetCreated;
result.CreationAllowedFlag = 2;
result.HomeMap = this.GameConfiguration.Maps.FirstOrDefault(map => map.Number == LorenciaMapId);
result.Number = (byte)number;
result.Name = name;
result.LevelRequirementByCreation = 250;
result.IsMasterClass = isMaster;
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, 20, true));
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, 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));
this.AddCommonAttributeRelationships(result.AttributeCombinations);
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.TotalLeadership, 1, Stats.BaseLeadership));
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.TotalLevel));
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, 1.0f / 10, Stats.TotalLeadership));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackSpeed, 1.0f / 10, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 10, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.15f, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.1f, Stats.TotalVitality));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.3f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.3f, Stats.TotalLeadership));
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, 1, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1.5f, Stats.TotalLevel));
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.SkillMultiplier, 0.0005f, Stats.TotalEnergy));
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, InputOperator.Add, 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.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.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, 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.DefenseFinal, Stats.IsHorseEquipped, Stats.BonusDefenseWithHorse, aggregateType: AggregateType.AddFinal));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalLeadership));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f, Stats.DefenseFinal));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.TotalLevel, 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.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4.0f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel));
}
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(38, Stats.MaximumMana));
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(48.5f, Stats.MaximumHealth));
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(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);
return result;
}
}

View File

@@ -0,0 +1,134 @@
// <copyright file="ClassDarkWizard.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Attributes;
/// <summary>
/// Initialization of character classes data.
/// </summary>
internal partial class CharacterClassInitialization
{
/// <summary>
/// Creates the dark wizard.
/// </summary>
/// <param name="number">The number.</param>
/// <param name="name">The name.</param>
/// <param name="isMaster">if set to <c>true</c>, the class is a master class which has access to the master skill tree.</param>
/// <param name="nextGenerationClass">The next generation class.</param>
/// <param name="canGetCreated">If set to <c>true</c>, it can get created by the player.</param>
/// <returns>The created character class.</returns>
protected CharacterClass CreateDarkWizard(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated)
{
var result = this.Context.CreateNew<CharacterClass>();
result.SetGuid((byte)number);
this.GameConfiguration.CharacterClasses.Add(result);
result.CanGetCreated = canGetCreated;
result.HomeMap = this.GameConfiguration.Maps.FirstOrDefault(map => map.Number == LorenciaMapId);
result.Number = (byte)number;
result.Name = name;
result.IsMasterClass = isMaster;
result.NextGenerationClass = nextGenerationClass;
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Level, 1, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.PointsPerLevelUp, 5, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseStrength, 18, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseAgility, 18, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseVitality, 15, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 30, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 60, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 60, 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));
this.AddCommonAttributeRelationships(result.AttributeCombinations);
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 0.25f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 1.0f / 3, Stats.TotalAgility));
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 / 20, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 10, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.3f, Stats.TotalVitality));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.4f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 2, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 2, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, Stats.TotalLevel));
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.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.BaseMinDamageBonus));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseMaxDamageBonus));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.WizardryBaseDmg, 1, Stats.BaseDamageBonus));
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.WizardryBaseDmgIncrease, aggregateType: AggregateType.Multiplicate));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.WizardryBaseDmgIncrease, aggregateType: AggregateType.Multiplicate));
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.AttackSpeedAny, Stats.IsOneHandedStaffEquipped, Stats.WeaponMasteryAttackSpeed));
result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.WizardryBaseDmg, Stats.IsTwoHandedStaffEquipped, Stats.TwoHandedStaffBonusBaseDamage));
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));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f, Stats.DefenseFinal));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.TotalLevel, 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.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 4, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel));
}
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));
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1, Stats.WizardryBaseDmgIncrease));
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.NovaStageDamage)); // placeholder value
this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster);
return result;
}
private CharacterClass CreateSoulMaster(CharacterClass grandMaster)
{
return this.CreateDarkWizard(CharacterClassNumber.SoulMaster, "Soul Master", false, grandMaster, false);
}
private CharacterClass CreateGrandMaster()
{
var result = this.CreateDarkWizard(CharacterClassNumber.GrandMaster, "Grand Master", true, null, false);
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.MasterLevel, 0, false));
return result;
}
}

View File

@@ -0,0 +1,139 @@
// <copyright file="ClassFairyElf.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Attributes;
/// <summary>
/// Initialization of character classes data.
/// </summary>
internal partial class CharacterClassInitialization
{
/// <summary>
/// Creates the fairy elf.
/// </summary>
/// <param name="number">The number.</param>
/// <param name="name">The name.</param>
/// <param name="isMaster">if set to <c>true</c>, the class is a master class which has access to the master skill tree.</param>
/// <param name="nextGenerationClass">The next generation class.</param>
/// <param name="canGetCreated">If set to <c>true</c>, it can get created by the player.</param>
/// <returns>The created character class.</returns>
protected CharacterClass CreateFairyElf(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated)
{
var ammunitionDmgIncrease = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "Ammunition damage increase", string.Empty);
this.GameConfiguration.Attributes.Add(ammunitionDmgIncrease);
var result = this.Context.CreateNew<CharacterClass>();
result.SetGuid((byte)number);
this.GameConfiguration.CharacterClasses.Add(result);
result.CanGetCreated = canGetCreated;
result.HomeMap = this.GameConfiguration.Maps.FirstOrDefault(map => map.Number == NoriaMapId);
result.Number = (byte)number;
result.Name = name;
result.IsMasterClass = isMaster;
result.NextGenerationClass = nextGenerationClass;
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Level, 1, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.PointsPerLevelUp, 5, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseStrength, 22, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseAgility, 25, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseVitality, 20, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 15, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 80, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentMana, 30, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentAbility, 1, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.AmmunitionAmount, 0, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.IsInSafezone, 1, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Resets, 0, false));
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.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 / 50, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MagicSpeed, 1.0f / 50, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.3f, Stats.TotalVitality));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.3f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1.5f, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1.5f, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, Stats.TotalVitality));
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.PhysicalBaseDmgIncrease, 1, ammunitionDmgIncrease, InputOperator.Add, AggregateType.Multiplicate));
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, 0, Stats.ArcheryAttackMode, InputOperator.ExponentiateByAttribute));
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.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));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f, Stats.DefenseFinal));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.TotalLevel, 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.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 0.6f, Stats.TotalAgility));
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(1, Stats.SkillMultiplier));
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(1.0f / 33f, Stats.AbilityRecoveryMultiplier));
this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster);
return result;
}
private CharacterClass CreateMuseElf(CharacterClass highElf)
{
return this.CreateFairyElf(CharacterClassNumber.MuseElf, "Muse Elf", false, highElf, false);
}
private CharacterClass CreateHighElf()
{
var result = this.CreateFairyElf(CharacterClassNumber.HighElf, "High Elf", true, null, false);
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.MasterLevel, 0, false));
return result;
}
}

View File

@@ -0,0 +1,140 @@
// <copyright file="ClassMagicGladiator.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Attributes;
/// <summary>
/// Initialization of character classes data.
/// </summary>
internal partial class CharacterClassInitialization
{
/// <summary>
/// Creates the magic gladiator.
/// </summary>
/// <param name="number">The number.</param>
/// <param name="name">The name.</param>
/// <param name="isMaster">if set to <c>true</c>, the class is a master class which has access to the master skill tree.</param>
/// <param name="nextGenerationClass">The next generation class.</param>
/// <param name="canGetCreated">If set to <c>true</c>, it can get created by the player.</param>
/// <returns>The created character class.</returns>
protected CharacterClass CreateMagicGladiator(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated)
{
var result = this.Context.CreateNew<CharacterClass>();
result.SetGuid((byte)number);
this.GameConfiguration.CharacterClasses.Add(result);
result.CanGetCreated = canGetCreated;
result.HomeMap = this.GameConfiguration.Maps.FirstOrDefault(map => map.Number == LorenciaMapId);
result.Number = (byte)number;
result.Name = name;
result.CreationAllowedFlag = 4;
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, 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));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.IsInSafezone, 1, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Resets, 0, false));
this.AddCommonAttributeRelationships(result.AttributeCombinations);
this.AddDoubleWieldAttributeRelationships(result.AttributeCombinations);
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1.0f / 5, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 1.0f / 3, Stats.TotalAgility));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 2, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, 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.0f / 12, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 8, Stats.TotalEnergy));
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.BaseMinDamageBonus));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseMaxDamageBonus));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.WizardryBaseDmg, 1, Stats.BaseDamageBonus));
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.WizardryBaseDmgIncrease, aggregateType: AggregateType.Multiplicate));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.WizardryBaseDmgIncrease, aggregateType: AggregateType.Multiplicate));
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));
// If a one-handed staff is equipped, we assume it's an energy MG and "switch off" the one-handed sword attribute,
// otherwise the mastery attack speed bonus would double in case of a staff-sword wield
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.IsOneHandedSwordEquipped, 0, Stats.IsOneHandedStaffEquipped, InputOperator.ExponentiateByAttribute, AggregateType.Multiplicate));
result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.IsOneHandedStaffEquipped, Stats.WeaponMasteryAttackSpeed));
result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.IsOneHandedSwordEquipped, Stats.WeaponMasteryAttackSpeed));
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));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f, Stats.DefenseFinal));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.TotalLevel, 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.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3.5f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3, Stats.TotalLevel));
}
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.WizardryBaseDmgIncrease));
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.IsOneHandedSwordEquipped));
this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster);
return result;
}
private CharacterClass CreateDuelMaster()
{
var result = this.CreateMagicGladiator(CharacterClassNumber.DuelMaster, "Duel Master", true, null, false);
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.MasterLevel, 0, false));
return result;
}
}

View File

@@ -0,0 +1,108 @@
// <copyright file="ClassRageFighter.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Attributes;
/// <summary>
/// Initialization of character classes data.
/// </summary>
internal partial class CharacterClassInitialization
{
private CharacterClass CreateFistMaster()
{
var result = this.CreateRageFighter(CharacterClassNumber.FistMaster, "Fist Master", true, null, false);
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.MasterLevel, 0, false));
return result;
}
private CharacterClass CreateRageFighter(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated)
{
var result = this.Context.CreateNew<CharacterClass>();
result.SetGuid((byte)number);
this.GameConfiguration.CharacterClasses.Add(result);
result.CanGetCreated = canGetCreated;
result.HomeMap = this.GameConfiguration.Maps.FirstOrDefault(map => map.Number == LorenciaMapId);
result.Number = (byte)number;
result.Name = name;
result.CreationAllowedFlag = 8;
result.IsMasterClass = isMaster;
result.LevelRequirementByCreation = 150;
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, 32, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseAgility, 27, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseVitality, 25, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseEnergy, 20, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.CurrentHealth, 100, 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));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Resets, 0, false));
this.AddCommonAttributeRelationships(result.AttributeCombinations);
this.AddDoubleWieldAttributeRelationships(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.2f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 1.5f, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 3, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.25f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvm, 1.0f / 6, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.AttackRatePvp, 3.6f, Stats.TotalAgility));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 1.0f, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.3f, Stats.TotalVitality));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.15f, Stats.TotalStrength));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f, Stats.DefenseFinal));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.TotalLevel, InputOperator.Exponentiate));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f / 30f, Stats.MaximumShieldTemp));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1.3f, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1.3f, Stats.TotalLevel));
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 / 15, Stats.TotalVitality));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumPhysBaseDmg, 1.0f / 12, Stats.TotalVitality));
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.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 5, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 3, Stats.TotalVitality));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.FenrirBaseDmg, 1.0f / 7, Stats.TotalEnergy));
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(57, Stats.MaximumHealth));
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(7, Stats.MaximumMana));
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;
}
}

View File

@@ -0,0 +1,164 @@
// <copyright file="ClassSummoner.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.CharacterClasses;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Attributes;
/// <summary>
/// Initialization of character classes data.
/// </summary>
internal partial class CharacterClassInitialization
{
private CharacterClass CreateBloodySummoner(CharacterClass dimensionMaster)
{
return this.CreateSummoner(CharacterClassNumber.BloodySummoner, "Bloody Summoner", false, dimensionMaster, false);
}
private CharacterClass CreateDimensionMaster()
{
var result = this.CreateSummoner(CharacterClassNumber.DimensionMaster, "Dimension Master", true, null, false);
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.MasterLevel, 0, false));
return result;
}
private CharacterClass CreateSummoner(CharacterClassNumber number, string name, bool isMaster, CharacterClass? nextGenerationClass, bool canGetCreated)
{
var statsDefense = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "Stats defense", string.Empty);
this.GameConfiguration.Attributes.Add(statsDefense);
var statsMinWizAndCurseBaseDmg = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "Stats min wiz and curse base dmg", string.Empty);
this.GameConfiguration.Attributes.Add(statsMinWizAndCurseBaseDmg);
var statsMaxWizAndCurseBaseDmg = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "Stats max wiz and curse base dmg", string.Empty);
this.GameConfiguration.Attributes.Add(statsMaxWizAndCurseBaseDmg);
var minBerserkerHealthDecrement = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "Min Berserker health decrement", string.Empty);
this.GameConfiguration.Attributes.Add(minBerserkerHealthDecrement);
var finalBerserkerHealthDecrement = this.Context.CreateNew<AttributeDefinition>(Guid.NewGuid(), "Final Berserker health decrement", string.Empty);
this.GameConfiguration.Attributes.Add(finalBerserkerHealthDecrement);
var result = this.Context.CreateNew<CharacterClass>();
result.SetGuid((byte)number);
this.GameConfiguration.CharacterClasses.Add(result);
result.CanGetCreated = canGetCreated;
result.HomeMap = this.GameConfiguration.Maps.FirstOrDefault(map => map.Number == ElvenlandMapId);
result.Number = (byte)number;
result.Name = name;
result.CreationAllowedFlag = 1;
result.IsMasterClass = isMaster;
result.NextGenerationClass = nextGenerationClass;
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Level, 1, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.PointsPerLevelUp, 5, false));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseStrength, 21, true));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.BaseAgility, 21, true));
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, 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));
result.StatAttributes.Add(this.CreateStatAttributeDefinition(Stats.Resets, 0, false));
this.AddCommonAttributeRelationships(result.AttributeCombinations);
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.TotalStrengthAndAgility, Stats.TotalAgility, Stats.TotalStrength, InputOperator.Add));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(statsDefense, 1.0f / 3, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseBase, 1, statsDefense));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvm, 0.25f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 0.5f, Stats.TotalAgility));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.DefenseRatePvp, 2, 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.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));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumAbility, 0.2f, Stats.TotalStrength));
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));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1.2f, Stats.TotalStrength));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f, Stats.DefenseFinal));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShieldTemp, 2f, Stats.TotalLevel, InputOperator.Exponentiate));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumShield, 1f / 30f, Stats.MaximumShieldTemp));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1.7f, Stats.TotalEnergy));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1.5f, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, Stats.TotalLevel));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 2, Stats.TotalVitality));
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.BaseMinDamageBonus));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.BaseMaxDamageBonus));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.WizardryBaseDmg, 1, Stats.BaseDamageBonus));
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.WizardryBaseDmgIncrease, aggregateType: AggregateType.Multiplicate));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumWizBaseDmg, 1, Stats.WizardryBaseDmgIncrease, aggregateType: AggregateType.Multiplicate));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.WizardryAttackDamageIncrease, 1.0f / 100, Stats.StaffRise));
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.CreateConditionalRelationship(Stats.CurseBaseDmg, Stats.IsBookEquipped, Stats.BookBonusBaseDamage));
result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.AttackSpeedAny, Stats.IsBookEquipped, Stats.WeaponMasteryAttackSpeed));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumMana, 1, Stats.BerserkerManaMultiplier, InputOperator.Add, AggregateType.Multiplicate));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(finalBerserkerHealthDecrement, -0.1f, Stats.BerserkerHealthDecrement, InputOperator.Minimum));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(finalBerserkerHealthDecrement, 1, Stats.BerserkerMinPhysDmgBonus, InputOperator.Minimum, AggregateType.Multiplicate));
result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumHealth, 1, finalBerserkerHealthDecrement, InputOperator.Add, AggregateType.Multiplicate));
result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.DefenseFinal, statsDefense, finalBerserkerHealthDecrement, AggregateType.AddFinal));
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.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.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(1, Stats.WizardryBaseDmgIncrease));
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.BerserkerManaMultiplier)); // placeholder value
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.BerserkerHealthDecrement)); // placeholder value
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0, Stats.BerserkerProficiencyMultiplier)); // placeholder value
result.BaseAttributeValues.Add(this.CreateConstValueAttribute(0.6f, Stats.BleedingDamageMultiplier));
this.AddCommonBaseAttributeValues(result.BaseAttributeValues, isMaster);
return result;
}
}