diff --git a/src/GameServer/MessageHandler/MagicEffectCancelHandlerPlugIn.cs b/src/GameServer/MessageHandler/MagicEffectCancelHandlerPlugIn.cs
new file mode 100644
index 0000000..ca5cd1d
--- /dev/null
+++ b/src/GameServer/MessageHandler/MagicEffectCancelHandlerPlugIn.cs
@@ -0,0 +1,61 @@
+//
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+//
+
+namespace MUnique.OpenMU.GameServer.MessageHandler;
+
+using System.Runtime.InteropServices;
+using MUnique.OpenMU.GameLogic;
+using MUnique.OpenMU.Network.Packets.ClientToServer;
+using MUnique.OpenMU.Network.PlugIns;
+using MUnique.OpenMU.PlugIns;
+
+///
+/// Handler for magic effect cancel packets.
+///
+[PlugIn]
+[Display(Name = nameof(PlugInResources.MagicEffectCancelHandlerPlugIn_Name), Description = nameof(PlugInResources.MagicEffectCancelHandlerPlugIn_Description), ResourceType = typeof(PlugInResources))]
+[Guid("3f25c9a1-4b8d-4e7f-9a2b-1c3d4e5f6a7b")]
+[MinimumClient(1, 0, ClientLanguage.Invariant)]
+internal class MagicEffectCancelHandlerPlugIn : IPacketHandlerPlugIn
+{
+ private const int InfinityArrowSkillId = 77;
+ private const int ExpansionOfWizardrySkillId = 233;
+ private const int ExpansionOfWizardryStrengSkillId = 380;
+ private const int ExpansionOfWizardryMasterySkillId = 383;
+ private const int InfinityArrowStrengSkillId = 441;
+
+ ///
+ public bool IsEncryptionExpected => true;
+
+ ///
+ public byte Key => MagicEffectCancelRequest.Code;
+
+ ///
+ public async ValueTask HandlePacketAsync(Player player, Memory packet)
+ {
+ MagicEffectCancelRequest message = packet;
+ if (!IsCancellableSkill(message.SkillId) || player.SkillList is null || !player.SkillList.ContainsSkill(message.SkillId))
+ {
+ return;
+ }
+
+ var magicEffect = player.SkillList.GetSkill(message.SkillId)?.Skill?.MagicEffectDef;
+ if (magicEffect is null || !player.MagicEffectList.ActiveEffects.TryGetValue(magicEffect.Number, out var effect))
+ {
+ return;
+ }
+
+ await effect.DisposeAsync().ConfigureAwait(false);
+ }
+
+ private static bool IsCancellableSkill(ushort skillId) => skillId switch
+ {
+ ExpansionOfWizardrySkillId => true,
+ ExpansionOfWizardryStrengSkillId => true,
+ ExpansionOfWizardryMasterySkillId => true,
+ InfinityArrowSkillId => true,
+ InfinityArrowStrengSkillId => true,
+ _ => false,
+ };
+}
\ No newline at end of file
diff --git a/src/GameServer/Properties/PlugInResources.Designer.cs b/src/GameServer/Properties/PlugInResources.Designer.cs
index 910d8c1..a924d4f 100644
--- a/src/GameServer/Properties/PlugInResources.Designer.cs
+++ b/src/GameServer/Properties/PlugInResources.Designer.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
@@ -2580,6 +2580,24 @@ namespace MUnique.OpenMU.GameServer.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to Handler for magic effect cancel packets..
+ ///
+ public static string MagicEffectCancelHandlerPlugIn_Description {
+ get {
+ return ResourceManager.GetString("MagicEffectCancelHandlerPlugIn_Description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Magic Effect Cancel Handler.
+ ///
+ public static string MagicEffectCancelHandlerPlugIn_Name {
+ get {
+ return ResourceManager.GetString("MagicEffectCancelHandlerPlugIn_Name", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The default implementation of the IMapChangePlugIn which is forwarding everything to the game client with specific data packets..
///
diff --git a/src/GameServer/Properties/PlugInResources.resx b/src/GameServer/Properties/PlugInResources.resx
index a2945ce..dcf7494 100644
--- a/src/GameServer/Properties/PlugInResources.resx
+++ b/src/GameServer/Properties/PlugInResources.resx
@@ -218,6 +218,12 @@
Handler for hit packets.
+
+
+ Magic Effect Cancel Handler
+
+
+ Handler for magic effect cancel packets.
Talk Npc Handler
diff --git a/src/Network/Packets/ClientToServer/ClientToServerPackets.cs b/src/Network/Packets/ClientToServer/ClientToServerPackets.cs
index 314a492..9eaeee2 100644
--- a/src/Network/Packets/ClientToServer/ClientToServerPackets.cs
+++ b/src/Network/Packets/ClientToServer/ClientToServerPackets.cs
@@ -9425,7 +9425,7 @@ public readonly struct TargetedSkill095
///
-/// Is sent by the client when: A player cancels a specific magic effect of a skill, usually 'Infinity Arrow' and 'Wizardy Enhance'.
+/// Is sent by the client when: A player cancels a specific magic effect of a skill, usually 'Infinity Arrow' and 'Wizardry Enhance'.
/// Causes reaction on server side: The effect is cancelled and an update is sent to the player and all surrounding players.
///
public readonly struct MagicEffectCancelRequest
diff --git a/src/Network/Packets/ClientToServer/ClientToServerPackets.xml b/src/Network/Packets/ClientToServer/ClientToServerPackets.xml
index 89e8bfb..6d4ca95 100644
--- a/src/Network/Packets/ClientToServer/ClientToServerPackets.xml
+++ b/src/Network/Packets/ClientToServer/ClientToServerPackets.xml
@@ -2317,7 +2317,7 @@
MagicEffectCancelRequest
7
ClientToServer
- A player cancels a specific magic effect of a skill, usually 'Infinity Arrow' and 'Wizardy Enhance'.
+ A player cancels a specific magic effect of a skill, usually 'Infinity Arrow' and 'Wizardry Enhance'.
The effect is cancelled and an update is sent to the player and all surrounding players.
diff --git a/src/Network/Packets/ClientToServer/ClientToServerPacketsRef.cs b/src/Network/Packets/ClientToServer/ClientToServerPacketsRef.cs
index d76f8e8..94a9a49 100644
--- a/src/Network/Packets/ClientToServer/ClientToServerPacketsRef.cs
+++ b/src/Network/Packets/ClientToServer/ClientToServerPacketsRef.cs
@@ -9300,7 +9300,7 @@ public readonly ref struct TargetedSkill095Ref
///
-/// Is sent by the client when: A player cancels a specific magic effect of a skill, usually 'Infinity Arrow' and 'Wizardy Enhance'.
+/// Is sent by the client when: A player cancels a specific magic effect of a skill, usually 'Infinity Arrow' and 'Wizardry Enhance'.
/// Causes reaction on server side: The effect is cancelled and an update is sent to the player and all surrounding players.
///
public readonly ref struct MagicEffectCancelRequestRef
diff --git a/src/Network/Packets/ClientToServer/ConnectionExtensions.cs b/src/Network/Packets/ClientToServer/ConnectionExtensions.cs
index 5cbdc21..6f3f0d5 100644
--- a/src/Network/Packets/ClientToServer/ConnectionExtensions.cs
+++ b/src/Network/Packets/ClientToServer/ConnectionExtensions.cs
@@ -3037,7 +3037,7 @@ public static class ConnectionExtensions
/// The skill id.
/// The player id.
///
- /// Is sent by the client when: A player cancels a specific magic effect of a skill, usually 'Infinity Arrow' and 'Wizardy Enhance'.
+ /// Is sent by the client when: A player cancels a specific magic effect of a skill, usually 'Infinity Arrow' and 'Wizardry Enhance'.
/// Causes reaction on server side: The effect is cancelled and an update is sent to the player and all surrounding players.
///
public static async ValueTask SendMagicEffectCancelRequestAsync(this IConnection? connection, ushort @skillId, ushort @playerId)
diff --git a/src/Persistence/Initialization/Skills/MagicEffectNumber.cs b/src/Persistence/Initialization/Skills/MagicEffectNumber.cs
index 71dea63..1af6dc3 100644
--- a/src/Persistence/Initialization/Skills/MagicEffectNumber.cs
+++ b/src/Persistence/Initialization/Skills/MagicEffectNumber.cs
@@ -330,12 +330,12 @@ internal enum MagicEffectNumber : short
///
/// The wiz enhance strengthener effect.
///
- WizEnhance2 = 138,
+ WizEnhanceStrengthener = 138,
///
/// The wiz enhance mastery effect.
///
- WizEnhance3 = 139,
+ WizEnhanceMastery = 139,
///
/// The critical damage increase mastery effect.
diff --git a/src/Persistence/Initialization/Skills/WizardryEnhanceEffectInitializer.cs b/src/Persistence/Initialization/Skills/WizardryEnhanceEffectInitializer.cs
index 24208ad..2dad7bd 100644
--- a/src/Persistence/Initialization/Skills/WizardryEnhanceEffectInitializer.cs
+++ b/src/Persistence/Initialization/Skills/WizardryEnhanceEffectInitializer.cs
@@ -12,9 +12,6 @@ using MUnique.OpenMU.GameLogic.Attributes;
///
/// Initializer which initializes the wizardry enhance effect.
///
-///
-/// It includes all attributes which are enhanced by the wizardry skill and its master skills.
-///
public class WizardryEnhanceEffectInitializer : InitializerBase
{
///
@@ -39,30 +36,18 @@ public class WizardryEnhanceEffectInitializer : InitializerBase
magicEffect.SendDuration = false;
magicEffect.StopByDeath = true;
magicEffect.Duration = this.Context.CreateNew();
- magicEffect.Duration.ConstantValue.Value = 1200f; // 20 minutes
+ magicEffect.Duration.ConstantValue.Value = 1800f; // 30 minutes
- var powerUpDefinition = this.Context.CreateNew();
- magicEffect.PowerUpDefinitions.Add(powerUpDefinition);
- powerUpDefinition.TargetAttribute = Stats.MinimumWizBaseDmg.GetPersistent(this.GameConfiguration);
+ var minWizDmgPowerUp = this.Context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(minWizDmgPowerUp);
+ minWizDmgPowerUp.TargetAttribute = Stats.MinimumWizBaseDmg.GetPersistent(this.GameConfiguration);
+ minWizDmgPowerUp.Boost = this.Context.CreateNew();
+ minWizDmgPowerUp.Boost.MaximumValue = 100f; // 100 dmg
- powerUpDefinition.Boost = this.Context.CreateNew();
- powerUpDefinition.Boost.ConstantValue.Value = 1.2f;
- powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate;
-
- var powerUpDefinition2 = this.Context.CreateNew();
- magicEffect.PowerUpDefinitions.Add(powerUpDefinition2);
- powerUpDefinition2.TargetAttribute = Stats.MaximumWizBaseDmg.GetPersistent(this.GameConfiguration);
-
- powerUpDefinition2.Boost = this.Context.CreateNew();
- powerUpDefinition2.Boost.ConstantValue.Value = 1f;
- powerUpDefinition2.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate;
-
- var powerUpDefinition3 = this.Context.CreateNew();
- magicEffect.PowerUpDefinitions.Add(powerUpDefinition3);
- powerUpDefinition3.TargetAttribute = Stats.CriticalDamageChance.GetPersistent(this.GameConfiguration);
-
- powerUpDefinition3.Boost = this.Context.CreateNew();
- powerUpDefinition3.Boost.ConstantValue.Value = 1f;
- powerUpDefinition3.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate;
+ var minWizDmgPerEnergy = this.Context.CreateNew();
+ minWizDmgPerEnergy.InputAttribute = Stats.TotalEnergy.GetPersistent(this.GameConfiguration);
+ minWizDmgPerEnergy.InputOperator = InputOperator.Multiply;
+ minWizDmgPerEnergy.InputOperand = 0.2f / 9; // 45 energy adds 1 min wiz damage
+ minWizDmgPowerUp.Boost.RelatedValues.Add(minWizDmgPerEnergy);
}
}
\ No newline at end of file
diff --git a/src/Persistence/Initialization/Skills/WizardryEnhanceMasteryEffectInitializer.cs b/src/Persistence/Initialization/Skills/WizardryEnhanceMasteryEffectInitializer.cs
new file mode 100644
index 0000000..cbf6dd9
--- /dev/null
+++ b/src/Persistence/Initialization/Skills/WizardryEnhanceMasteryEffectInitializer.cs
@@ -0,0 +1,70 @@
+//
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+//
+
+namespace MUnique.OpenMU.Persistence.Initialization.Skills;
+
+using MUnique.OpenMU.AttributeSystem;
+using MUnique.OpenMU.DataModel.Attributes;
+using MUnique.OpenMU.DataModel.Configuration;
+using MUnique.OpenMU.GameLogic.Attributes;
+
+///
+/// Initializer which initializes the wizardry enhance mastery effect.
+///
+public class WizardryEnhanceMasteryEffectInitializer : InitializerBase
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The context.
+ /// The game configuration.
+ public WizardryEnhanceMasteryEffectInitializer(IContext context, GameConfiguration gameConfiguration)
+ : base(context, gameConfiguration)
+ {
+ }
+
+ ///
+ public override void Initialize()
+ {
+ var magicEffect = this.Context.CreateNew();
+ this.GameConfiguration.MagicEffects.Add(magicEffect);
+ magicEffect.Number = (byte)MagicEffectNumber.WizEnhanceMastery;
+ magicEffect.Name = "Wizardry Enhance Mastery Skill Effect";
+
+ var wizardryEnhanceEffect = this.GameConfiguration.MagicEffects.First(e => e.Number == (short)MagicEffectNumber.WizEnhanceStrengthener);
+ magicEffect.InformObservers = wizardryEnhanceEffect.InformObservers;
+ magicEffect.SubType = wizardryEnhanceEffect.SubType;
+ magicEffect.SendDuration = wizardryEnhanceEffect.SendDuration;
+ magicEffect.StopByDeath = wizardryEnhanceEffect.StopByDeath;
+ magicEffect.Duration = this.Context.CreateNew();
+ magicEffect.Duration.ConstantValue.Value = wizardryEnhanceEffect.Duration!.ConstantValue.Value;
+ magicEffect.Duration.MaximumValue = wizardryEnhanceEffect.Duration.MaximumValue;
+
+ foreach (var powerUp in wizardryEnhanceEffect.PowerUpDefinitions)
+ {
+ var powerUpCopy = this.Context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(powerUpCopy);
+ powerUpCopy.TargetAttribute = powerUp.TargetAttribute!.GetPersistent(this.GameConfiguration);
+ powerUpCopy.Boost = this.Context.CreateNew();
+ powerUpCopy.Boost.ConstantValue.Value = powerUp.Boost!.ConstantValue.Value;
+ powerUpCopy.Boost.ConstantValue.AggregateType = powerUp.Boost.ConstantValue.AggregateType;
+ powerUpCopy.Boost.MaximumValue = powerUp.Boost.MaximumValue;
+
+ foreach (var boostRelatedValue in powerUp.Boost.RelatedValues)
+ {
+ var boostRelatedValueCopy = this.Context.CreateNew();
+ boostRelatedValueCopy.InputAttribute = boostRelatedValue.InputAttribute!.GetPersistent(this.GameConfiguration);
+ boostRelatedValueCopy.InputOperator = boostRelatedValue.InputOperator;
+ boostRelatedValueCopy.InputOperand = boostRelatedValue.InputOperand;
+ boostRelatedValueCopy.AggregateType = boostRelatedValue.AggregateType;
+ powerUpCopy.Boost.RelatedValues.Add(boostRelatedValueCopy);
+ }
+ }
+
+ var critChancePowerUp = this.Context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(critChancePowerUp);
+ critChancePowerUp.TargetAttribute = Stats.CriticalDamageChance.GetPersistent(this.GameConfiguration);
+ critChancePowerUp.Boost = this.Context.CreateNew();
+ }
+}
\ No newline at end of file
diff --git a/src/Persistence/Initialization/Skills/WizardryEnhanceStrengthenerEffectInitializer.cs b/src/Persistence/Initialization/Skills/WizardryEnhanceStrengthenerEffectInitializer.cs
new file mode 100644
index 0000000..ecbff2d
--- /dev/null
+++ b/src/Persistence/Initialization/Skills/WizardryEnhanceStrengthenerEffectInitializer.cs
@@ -0,0 +1,72 @@
+//
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+//
+
+namespace MUnique.OpenMU.Persistence.Initialization.Skills;
+
+using MUnique.OpenMU.AttributeSystem;
+using MUnique.OpenMU.DataModel.Attributes;
+using MUnique.OpenMU.DataModel.Configuration;
+using MUnique.OpenMU.GameLogic.Attributes;
+
+///
+/// Initializer which initializes the wizardry enhance strengthener effect.
+///
+public class WizardryEnhanceStrengthenerEffectInitializer : InitializerBase
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The context.
+ /// The game configuration.
+ public WizardryEnhanceStrengthenerEffectInitializer(IContext context, GameConfiguration gameConfiguration)
+ : base(context, gameConfiguration)
+ {
+ }
+
+ ///
+ public override void Initialize()
+ {
+ var magicEffect = this.Context.CreateNew();
+ this.GameConfiguration.MagicEffects.Add(magicEffect);
+ magicEffect.Number = (byte)MagicEffectNumber.WizEnhanceStrengthener;
+ magicEffect.Name = "Wizardry Enhance Strengthener Skill Effect";
+
+ var wizardryEnhanceEffect = this.GameConfiguration.MagicEffects.First(e => e.Number == (short)MagicEffectNumber.WizEnhance);
+ magicEffect.InformObservers = wizardryEnhanceEffect.InformObservers;
+ magicEffect.SubType = wizardryEnhanceEffect.SubType;
+ magicEffect.SendDuration = wizardryEnhanceEffect.SendDuration;
+ magicEffect.StopByDeath = wizardryEnhanceEffect.StopByDeath;
+ magicEffect.Duration = this.Context.CreateNew();
+ magicEffect.Duration.ConstantValue.Value = wizardryEnhanceEffect.Duration!.ConstantValue.Value;
+ magicEffect.Duration.MaximumValue = wizardryEnhanceEffect.Duration.MaximumValue;
+
+ foreach (var powerUp in wizardryEnhanceEffect.PowerUpDefinitions)
+ {
+ var powerUpCopy = this.Context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(powerUpCopy);
+ powerUpCopy.TargetAttribute = powerUp.TargetAttribute!.GetPersistent(this.GameConfiguration);
+ powerUpCopy.Boost = this.Context.CreateNew();
+ powerUpCopy.Boost.ConstantValue.Value = powerUp.Boost!.ConstantValue.Value;
+ powerUpCopy.Boost.ConstantValue.AggregateType = powerUp.Boost.ConstantValue.AggregateType;
+ powerUpCopy.Boost.MaximumValue = powerUp.Boost.MaximumValue;
+
+ foreach (var boostRelatedValue in powerUp.Boost.RelatedValues)
+ {
+ var boostRelatedValueCopy = this.Context.CreateNew();
+ boostRelatedValueCopy.InputAttribute = boostRelatedValue.InputAttribute!.GetPersistent(this.GameConfiguration);
+ boostRelatedValueCopy.InputOperator = boostRelatedValue.InputOperator;
+ boostRelatedValueCopy.InputOperand = boostRelatedValue.InputOperand;
+ boostRelatedValueCopy.AggregateType = boostRelatedValue.AggregateType;
+ powerUpCopy.Boost.RelatedValues.Add(boostRelatedValueCopy);
+ }
+ }
+
+ var maxDmgPowerUp = this.Context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(maxDmgPowerUp);
+ maxDmgPowerUp.TargetAttribute = Stats.MaximumWizBaseDmg.GetPersistent(this.GameConfiguration);
+ maxDmgPowerUp.Boost = this.Context.CreateNew();
+ maxDmgPowerUp.Boost.ConstantValue.Value = 1f;
+ maxDmgPowerUp.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate;
+ }
+}
\ No newline at end of file
diff --git a/src/Persistence/Initialization/Updates/FinishDarkWizardMasterTreePlugIn.cs b/src/Persistence/Initialization/Updates/FinishDarkWizardMasterTreePlugIn.cs
new file mode 100644
index 0000000..b3f8cb7
--- /dev/null
+++ b/src/Persistence/Initialization/Updates/FinishDarkWizardMasterTreePlugIn.cs
@@ -0,0 +1,185 @@
+//
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+//
+
+namespace MUnique.OpenMU.Persistence.Initialization.Updates;
+
+using System.Runtime.InteropServices;
+using MUnique.OpenMU.AttributeSystem;
+using MUnique.OpenMU.DataModel.Attributes;
+using MUnique.OpenMU.DataModel.Configuration;
+using MUnique.OpenMU.GameLogic.Attributes;
+using MUnique.OpenMU.Persistence.Initialization.Skills;
+using MUnique.OpenMU.PlugIns;
+
+///
+/// This update completes the dark wizard master tree expansion of wizardry effects.
+///
+[PlugIn]
+[Display(Name = PlugInName, Description = PlugInDescription)]
+[Guid("C1D2E3F4-5A6B-7C8D-9E0F-1A2B3C4D5E6F")]
+public class FinishDarkWizardMasterTreePlugIn : UpdatePlugInBase
+{
+ ///
+ /// The plug in name.
+ ///
+ internal const string PlugInName = "Finish Dark Wizard Master Tree PlugIn";
+
+ ///
+ /// The plug in description.
+ ///
+ internal const string PlugInDescription = "This update completes the dark wizard master tree expansion of wizardry effects.";
+
+ ///
+ public override UpdateVersion Version => UpdateVersion.FinishDarkWizardMasterTree;
+
+ ///
+ public override string DataInitializationKey => VersionSeasonSix.DataInitialization.Id;
+
+ ///
+ public override string Name => PlugInName;
+
+ ///
+ public override string Description => PlugInDescription;
+
+ ///
+ public override bool IsMandatory => true;
+
+ ///
+ public override DateTime CreatedAt => new(2026, 7, 7, 16, 0, 0, DateTimeKind.Utc);
+
+ ///
+ protected override async ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration)
+ {
+ // Update Wizardry Enhance effect
+ var wizardryEnhanceEffect = gameConfiguration.MagicEffects.First(e => e.Number == (short)MagicEffectNumber.WizEnhance);
+ wizardryEnhanceEffect.Duration = context.CreateNew();
+ wizardryEnhanceEffect.Duration.ConstantValue.Value = 1800f; // 30 minutes
+ wizardryEnhanceEffect.PowerUpDefinitions.Clear();
+
+ var minWizDmgPowerUp = context.CreateNew();
+ wizardryEnhanceEffect.PowerUpDefinitions.Add(minWizDmgPowerUp);
+ minWizDmgPowerUp.TargetAttribute = Stats.MinimumWizBaseDmg.GetPersistent(gameConfiguration);
+ minWizDmgPowerUp.Boost = context.CreateNew();
+ minWizDmgPowerUp.Boost.MaximumValue = 100f; // 100 dmg
+
+ var minWizDmgPerEnergy = context.CreateNew();
+ minWizDmgPerEnergy.InputAttribute = Stats.TotalEnergy.GetPersistent(gameConfiguration);
+ minWizDmgPerEnergy.InputOperator = InputOperator.Multiply;
+ minWizDmgPerEnergy.InputOperand = 0.2f / 9; // 45 energy adds 1 min wiz damage
+ minWizDmgPowerUp.Boost.RelatedValues.Add(minWizDmgPerEnergy);
+
+ // Create Wiz Enhance Strengthener & Mastery Skill Effects
+ var wizEnhanceStrengthenerEffect = this.CreateWizEnhanceStrengthenerEffect(context, gameConfiguration);
+ var wizEnhanceMasteryEffect = this.CreateWizEnhanceMasteryEffect(context, gameConfiguration);
+
+ // Update master skills
+ if (gameConfiguration.Skills.FirstOrDefault(s => s.Number == (short)SkillNumber.ExpansionofWizStreng) is { } expansionOfWizStreng)
+ {
+ expansionOfWizStreng.MagicEffectDef = wizEnhanceStrengthenerEffect;
+ }
+
+ if (gameConfiguration.Skills.FirstOrDefault(s => s.Number == (short)SkillNumber.ExpansionofWizMas) is { } expansionOfWizMastery)
+ {
+ expansionOfWizMastery.MagicEffectDef = wizEnhanceMasteryEffect;
+
+ if (expansionOfWizMastery.MasterDefinition is { } masterDefinition)
+ {
+ masterDefinition.ReplacedSkill = gameConfiguration.Skills.First(s => s.Number == (short)SkillNumber.ExpansionofWizStreng);
+ masterDefinition.Aggregation = AggregateType.AddRaw;
+ }
+ }
+ }
+
+ private MagicEffectDefinition CreateWizEnhanceStrengthenerEffect(IContext context, GameConfiguration gameConfiguration)
+ {
+ var magicEffect = context.CreateNew();
+ gameConfiguration.MagicEffects.Add(magicEffect);
+ magicEffect.Number = (byte)MagicEffectNumber.WizEnhanceStrengthener;
+ magicEffect.Name = "Wizardry Enhance Strengthener Skill Effect";
+
+ var wizardryEnhanceEffect = gameConfiguration.MagicEffects.First(e => e.Number == (short)MagicEffectNumber.WizEnhance);
+ magicEffect.InformObservers = wizardryEnhanceEffect.InformObservers;
+ magicEffect.SubType = wizardryEnhanceEffect.SubType;
+ magicEffect.SendDuration = wizardryEnhanceEffect.SendDuration;
+ magicEffect.StopByDeath = wizardryEnhanceEffect.StopByDeath;
+ magicEffect.Duration = context.CreateNew();
+ magicEffect.Duration.ConstantValue.Value = wizardryEnhanceEffect.Duration!.ConstantValue.Value;
+ magicEffect.Duration.MaximumValue = wizardryEnhanceEffect.Duration.MaximumValue;
+
+ foreach (var powerUp in wizardryEnhanceEffect.PowerUpDefinitions)
+ {
+ var powerUpCopy = context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(powerUpCopy);
+ powerUpCopy.TargetAttribute = powerUp.TargetAttribute!.GetPersistent(gameConfiguration);
+ powerUpCopy.Boost = context.CreateNew();
+ powerUpCopy.Boost.ConstantValue.Value = powerUp.Boost!.ConstantValue.Value;
+ powerUpCopy.Boost.ConstantValue.AggregateType = powerUp.Boost.ConstantValue.AggregateType;
+ powerUpCopy.Boost.MaximumValue = powerUp.Boost.MaximumValue;
+
+ foreach (var boostRelatedValue in powerUp.Boost.RelatedValues)
+ {
+ var boostRelatedValueCopy = context.CreateNew();
+ boostRelatedValueCopy.InputAttribute = boostRelatedValue.InputAttribute!.GetPersistent(gameConfiguration);
+ boostRelatedValueCopy.InputOperator = boostRelatedValue.InputOperator;
+ boostRelatedValueCopy.InputOperand = boostRelatedValue.InputOperand;
+ boostRelatedValueCopy.AggregateType = boostRelatedValue.AggregateType;
+ powerUpCopy.Boost.RelatedValues.Add(boostRelatedValueCopy);
+ }
+ }
+
+ var maxDmgPowerUp = context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(maxDmgPowerUp);
+ maxDmgPowerUp.TargetAttribute = Stats.MaximumWizBaseDmg.GetPersistent(gameConfiguration);
+ maxDmgPowerUp.Boost = context.CreateNew();
+ maxDmgPowerUp.Boost.ConstantValue.Value = 1f;
+ maxDmgPowerUp.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate;
+
+ return magicEffect;
+ }
+
+ private MagicEffectDefinition CreateWizEnhanceMasteryEffect(IContext context, GameConfiguration gameConfiguration)
+ {
+ var magicEffect = context.CreateNew();
+ gameConfiguration.MagicEffects.Add(magicEffect);
+ magicEffect.Number = (byte)MagicEffectNumber.WizEnhanceMastery;
+ magicEffect.Name = "Wizardry Enhance Mastery Skill Effect";
+
+ var wizardryEnhanceEffect = gameConfiguration.MagicEffects.First(e => e.Number == (short)MagicEffectNumber.WizEnhanceStrengthener);
+ magicEffect.InformObservers = wizardryEnhanceEffect.InformObservers;
+ magicEffect.SubType = wizardryEnhanceEffect.SubType;
+ magicEffect.SendDuration = wizardryEnhanceEffect.SendDuration;
+ magicEffect.StopByDeath = wizardryEnhanceEffect.StopByDeath;
+ magicEffect.Duration = context.CreateNew();
+ magicEffect.Duration.ConstantValue.Value = wizardryEnhanceEffect.Duration!.ConstantValue.Value;
+ magicEffect.Duration.MaximumValue = wizardryEnhanceEffect.Duration.MaximumValue;
+
+ foreach (var powerUp in wizardryEnhanceEffect.PowerUpDefinitions)
+ {
+ var powerUpCopy = context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(powerUpCopy);
+ powerUpCopy.TargetAttribute = powerUp.TargetAttribute!.GetPersistent(gameConfiguration);
+ powerUpCopy.Boost = context.CreateNew();
+ powerUpCopy.Boost.ConstantValue.Value = powerUp.Boost!.ConstantValue.Value;
+ powerUpCopy.Boost.ConstantValue.AggregateType = powerUp.Boost.ConstantValue.AggregateType;
+ powerUpCopy.Boost.MaximumValue = powerUp.Boost.MaximumValue;
+
+ foreach (var boostRelatedValue in powerUp.Boost.RelatedValues)
+ {
+ var boostRelatedValueCopy = context.CreateNew();
+ boostRelatedValueCopy.InputAttribute = boostRelatedValue.InputAttribute!.GetPersistent(gameConfiguration);
+ boostRelatedValueCopy.InputOperator = boostRelatedValue.InputOperator;
+ boostRelatedValueCopy.InputOperand = boostRelatedValue.InputOperand;
+ boostRelatedValueCopy.AggregateType = boostRelatedValue.AggregateType;
+ powerUpCopy.Boost.RelatedValues.Add(boostRelatedValueCopy);
+ }
+ }
+
+ var critChancePowerUp = context.CreateNew();
+ magicEffect.PowerUpDefinitions.Add(critChancePowerUp);
+ critChancePowerUp.TargetAttribute = Stats.CriticalDamageChance.GetPersistent(gameConfiguration);
+ critChancePowerUp.Boost = context.CreateNew();
+
+ return magicEffect;
+ }
+}
diff --git a/src/Persistence/Initialization/Updates/UpdateVersion.cs b/src/Persistence/Initialization/Updates/UpdateVersion.cs
index 8ee91d1..81e5e7b 100644
--- a/src/Persistence/Initialization/Updates/UpdateVersion.cs
+++ b/src/Persistence/Initialization/Updates/UpdateVersion.cs
@@ -479,7 +479,7 @@ public enum UpdateVersion
/// The version of the .
///
AddIsQuestItemFlag = 94,
-
+
///
/// The version of the .
///
@@ -514,4 +514,9 @@ public enum UpdateVersion
/// The version of the .
///
AddElfSoldierBuff = 101,
+
+ ///
+ /// The version of the .
+ ///
+ FinishDarkWizardMasterTree = 102,
}
diff --git a/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs b/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs
index 40fcbc7..029d952 100644
--- a/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs
+++ b/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs
@@ -81,6 +81,8 @@ internal class SkillsInitializer : SkillsInitializerBase
{ SkillNumber.EarthshakeMastery, MagicEffectNumber.Stunned },
{ SkillNumber.CritDmgIncPowUp3, MagicEffectNumber.CriticalDamageIncreaseMastery },
{ SkillNumber.SwellLifeProficiency, MagicEffectNumber.GreaterFortitudeProficiency },
+ { SkillNumber.ExpansionofWizStreng, MagicEffectNumber.WizEnhanceStrengthener },
+ { SkillNumber.ExpansionofWizMas, MagicEffectNumber.WizEnhanceMastery },
};
private readonly IDictionary _masterSkillRoots;
@@ -701,6 +703,8 @@ internal class SkillsInitializer : SkillsInitializerBase
new StunEffectInitializer(this.Context, this.GameConfiguration).Initialize();
new CriticalDamageIncreaseMasteryEffectInitializer(this.Context, this.GameConfiguration).Initialize();
new LifeSwellProficiencyEffectInitializer(this.Context, this.GameConfiguration).Initialize();
+ new WizardryEnhanceStrengthenerEffectInitializer(this.Context, this.GameConfiguration).Initialize();
+ new WizardryEnhanceMasteryEffectInitializer(this.Context, this.GameConfiguration).Initialize();
}
private void MapSkillsToEffects()
@@ -800,7 +804,7 @@ internal class SkillsInitializer : SkillsInitializerBase
this.AddMasterSkillDefinition(SkillNumber.ExpansionofWizStreng, SkillNumber.ExpansionofWizardry, SkillNumber.Undefined, 2, 2, SkillNumber.ExpansionofWizardry, 20, Formula120Value, Formula120, Stats.MaximumWizBaseDmg, AggregateType.Multiplicate);
this.AddMasterSkillDefinition(SkillNumber.InfernoStrengthener, SkillNumber.Inferno, SkillNumber.FlameStrengthener, 2, 3, SkillNumber.Inferno, 20, Formula502);
this.AddMasterSkillDefinition(SkillNumber.BlastStrengthener, SkillNumber.Cometfall, SkillNumber.LightningStrengthener, 2, 3, SkillNumber.Cometfall, 20, Formula502);
- this.AddMasterSkillDefinition(SkillNumber.ExpansionofWizMas, SkillNumber.ExpansionofWizStreng, SkillNumber.Undefined, 2, 3, SkillNumber.ExpansionofWizardry, 20, Formula120Value, Formula120, targetAttribute: Stats.CriticalDamageChance, AggregateType.Multiplicate);
+ this.AddMasterSkillDefinition(SkillNumber.ExpansionofWizMas, SkillNumber.ExpansionofWizStreng, SkillNumber.Undefined, 2, 3, SkillNumber.ExpansionofWizStreng, 20, Formula120Value, Formula120, Stats.CriticalDamageChance, AggregateType.AddRaw);
this.AddMasterSkillDefinition(SkillNumber.PoisonStrengthener, SkillNumber.Poison, SkillNumber.Undefined, 2, 3, SkillNumber.Poison, 20, Formula632);
this.AddMasterSkillDefinition(SkillNumber.EvilSpiritStreng, SkillNumber.EvilSpirit, SkillNumber.Undefined, 2, 4, SkillNumber.EvilSpirit, 20, Formula502);
this.AddPassiveMasterSkillDefinition(SkillNumber.MagicMasteryGrandMaster, Stats.WizardryBaseDmg, AggregateType.AddRaw, Formula502, 4, 2, SkillNumber.EvilSpiritStreng);