Skip to content

Commit

Permalink
Merge pull request #505 from ze-dom/bugfix/joh_upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
sven-n authored Oct 28, 2024
2 parents 19768c2 + 85fbb7d commit d5cc8ce
Show file tree
Hide file tree
Showing 19 changed files with 5,457 additions and 83 deletions.
7 changes: 7 additions & 0 deletions src/DataModel/Configuration/Items/IncreasableItemOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ public partial class IncreasableItemOption : ItemOption
/// </value>
public LevelType LevelType { get; set; }

/// <summary>
/// Gets or sets a value which is considered when randomizing the option to an item.
/// </summary>
/// <remarks>This is used for Jewel of Harmony options rollout.</remarks>
/// <value>The statistical weight.</value>
public byte Weight { get; set; }

/// <summary>
/// Gets or sets the level dependent options for option levels over 1.
/// </summary>
Expand Down
10 changes: 5 additions & 5 deletions src/GameLogic/AttackableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static async ValueTask<HitInfo> CalculateDamageAsync(this IAttacker attac
}
else if (isCriticalHit)
{
dmg = baseMaxDamage;
dmg = baseMaxDamage + (int)attacker.Attributes[Stats.CriticalDamageBonus];
attributes |= DamageAttributes.Critical;
}
else if (baseMaxDamage <= baseMinDamage)
Expand Down Expand Up @@ -144,10 +144,10 @@ public static HitInfo GetHitInfo(this IAttackable defender, uint damage, DamageA
}

/// <summary>
/// Applies the magic effect of the players skill to the target.
/// Applies the magic effect of the player's skill to the target.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="player">The player.</param>
/// <param name="attacker">The attacker.</param>
/// <param name="skillEntry">The skill entry.</param>
public static async ValueTask ApplyMagicEffectAsync(this IAttackable target, IAttacker attacker, SkillEntry skillEntry)
{
Expand All @@ -160,7 +160,7 @@ public static async ValueTask ApplyMagicEffectAsync(this IAttackable target, IAt
}

/// <summary>
/// Applies the regeneration of the players skill to the target.
/// Applies the regeneration of the player's skill to the target.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="player">The player.</param>
Expand Down Expand Up @@ -467,7 +467,7 @@ private static int GetDamage(this SkillEntry skill)
}

/// <summary>
/// Returns the base damage if the attacker, using a specific skill.
/// Returns the base damage of the attacker, using a specific skill.
/// </summary>
/// <param name="attacker">The attacker.</param>
/// <param name="skill">Skill which is used.</param>
Expand Down
40 changes: 40 additions & 0 deletions src/GameLogic/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,44 @@ public static IList<T> AsList<T>(this IEnumerable<T> enumerable)
/// <param name="enumerable">The enumerable.</param>
/// <returns>The randomly selected element.</returns>
public static T? SelectRandom<T>(this IEnumerable<T> enumerable) => SelectRandom(enumerable, Rand.GetRandomizer());

/// <summary>
/// Selects a random weighted element of an enumerable.
/// </summary>
/// <typeparam name="T">The generic type of the enumerable.</typeparam>
/// <param name="enumerable">The enumerable.</param>
/// <param name="weights">The weights associated with <paramref name="enumerable" />, respectively.</param>
/// <param name="randomizer">The randomizer.</param>
/// <returns>The randomly selected weighted element.</returns>
public static T? SelectWeightedRandom<T>(this IEnumerable<T> enumerable, IEnumerable<int> weights, IRandomizer randomizer)
{
var list = enumerable as IList<T> ?? enumerable.ToList();
var weightList = weights as IList<int> ?? weights.ToList();
if (list.Count > 0 && weightList.Count == list.Count)
{
var roll = randomizer.NextInt(0, weights.Sum());
int inc = 0;
for (int i = 0; i < weightList.Count; i++)
{
inc += weightList[i];
if (roll < inc)
{
return list[i];
}
}

return SelectRandom(enumerable, randomizer); // Fallback in case there are no weights assigned (>0)
}

return default;
}

/// <summary>
/// Selects a random weighted element of an enumerable.
/// </summary>
/// <typeparam name="T">The generic type of the enumerable.</typeparam>
/// <param name="enumerable">The enumerable.</param>
/// <param name="weights">The weights associated with <paramref name="enumerable" />, respectively.</param>
/// <returns>The randomly selected weighted element.</returns>
public static T? SelectWeightedRandom<T>(this IEnumerable<T> enumerable, IEnumerable<int> weights) => SelectWeightedRandom(enumerable, weights, Rand.GetRandomizer());
}
6 changes: 6 additions & 0 deletions src/GameLogic/ItemPowerUpFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@ private IEnumerable<PowerUpWrapper> GetPowerUpsOfItemOptions(Item item, Attribut
continue;
}

if (optionOfLevel?.RequiredItemLevel > item.Level)
{
// Some options (like harmony) although on the item can be inactive.
continue;
}

var powerUp = optionOfLevel?.PowerUpDefinition ?? option.PowerUpDefinition;

if (powerUp?.Boost is null)
Expand Down
35 changes: 26 additions & 9 deletions src/GameLogic/PlayerActions/Craftings/RefineStoneCrafting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,43 @@
namespace MUnique.OpenMU.GameLogic.PlayerActions.Craftings;

using MUnique.OpenMU.DataModel.Configuration.ItemCrafting;
using MUnique.OpenMU.DataModel.Configuration.Items;
using MUnique.OpenMU.GameLogic.PlayerActions.Items;

/// <summary>
/// Crafting which creates refine stones.
/// </summary>
public class RefineStoneCrafting : SimpleItemCraftingHandler
{
#region List of excluded Items
#region List of excluded Items (if item level < 4)

private readonly ISet<(byte Group, short Number)> _excludedItems = new HashSet<(byte, short)>
{
(0, 0), // Kris
(0, 1), // Short Sword
(0, 2), // Rapier
(0, 4), // Sword of Assassin
(1, 0), // Small Axe
(1, 1), // Hand Axe
(1, 2), // Double Axe
(2, 0), // Mace
(2, 1), // Morning Star
(2, 2), // Flail
(3, 1), // Spear
(3, 2), // Dragon Lance
(3, 3), // Giant Trident
(3, 5), // Double Poleaxe
(4, 0), // Short Bow
(4, 1), // Bow
(4, 2), // Elven Bow
(4, 3), // Battle Bow
(4, 8), // Crossbow
(4, 9), // Golden Crossbow
(4, 10), // Arquebus
(5, 1), // Skull Staff
(5, 2), // Angelic Staff
(5, 3), // Serpent Staff
(4, 11), // Light Crossbow
(5, 0), // Skull Staff
(5, 1), // Angelic Staff
(5, 2), // Serpent Staff
(6, 0), // Small Shield
(6, 1), // Horn Shield
(6, 2), // Kite Shield
Expand All @@ -41,13 +50,14 @@ public class RefineStoneCrafting : SimpleItemCraftingHandler
(6, 6), // Skull Shield
(6, 7), // Spiked Shield
(6, 9), // Plate Shield
(6, 10), // Large Round Shield
(6, 10), // Big Round Shield
(7, 0), // Bronze Helm
(7, 2), // Pad Helm
(7, 4), // Bone Helm
(7, 5), // Leather Helm
(7, 6), // Scale Helm
(7, 7), // Sphinx Helm
(7, 7), // Sphinx Mask
(7, 8), // Brass Helm
(7, 10), // Vine Helm
(7, 11), // Silk Helm
(7, 12), // Wind Helm
Expand All @@ -57,6 +67,7 @@ public class RefineStoneCrafting : SimpleItemCraftingHandler
(8, 5), // Leather Armor
(8, 6), // Scale Armor
(8, 7), // Sphinx Armor
(8, 8), // Brass Armor
(8, 10), // Vine Armor
(8, 11), // Silk Armor
(8, 12), // Wind Armor
Expand All @@ -66,6 +77,7 @@ public class RefineStoneCrafting : SimpleItemCraftingHandler
(9, 5), // Leather Pants
(9, 6), // Scale Pants
(9, 7), // Sphinx Pants
(9, 8), // Brass Pants
(9, 10), // Vine Pants
(9, 11), // Silk Pants
(9, 12), // Wind Pants
Expand All @@ -75,6 +87,7 @@ public class RefineStoneCrafting : SimpleItemCraftingHandler
(10, 5), // Leather Gloves
(10, 6), // Scale Gloves
(10, 7), // Sphinx Gloves
(10, 8), // Brass Gloves
(10, 10), // Vine Gloves
(10, 11), // Silk Gloves
(10, 12), // Wind Gloves
Expand All @@ -84,6 +97,7 @@ public class RefineStoneCrafting : SimpleItemCraftingHandler
(11, 5), // Leather Boots
(11, 6), // Scale Boots
(11, 7), // Sphinx Boots
(11, 8), // Brass Boots
(11, 10), // Vine Boots
(11, 11), // Silk Boots
(11, 12), // Wind Boots
Expand Down Expand Up @@ -114,7 +128,10 @@ public RefineStoneCrafting(SimpleCraftingSettings settings)
protected override bool RequiredItemMatches(Item item, ItemCraftingRequiredItem requiredItem)
{
return base.RequiredItemMatches(item, requiredItem)
&& (item.IsWearable() && !this._excludedItems.Contains((item.Definition!.Group, item.Definition.Number)));
&& item.IsWearable()
&& !item.IsAncient()
&& !item.ItemOptions.Any(o => o.ItemOption?.OptionType == ItemOptionTypes.HarmonyOption)
&& (!this._excludedItems.Contains((item.Definition!.Group, item.Definition.Number)) || item.Level > 3);
}

/// <inheritdoc />
Expand All @@ -129,12 +146,12 @@ protected override async ValueTask<List<Item>> CreateOrModifyResultItemsAsync(IL
var result = new List<Item>();
if (higherRefineStoneItems > 0)
{
result.AddRange(await this.CreateRefineStonesAsync(higherRefineStoneItems, 20, 44, player).ConfigureAwait(false));
result.AddRange(await this.CreateRefineStonesAsync(higherRefineStoneItems, 50, 44, player).ConfigureAwait(false));
}

if (lowerRefineStoneItems > 0)
{
result.AddRange(await this.CreateRefineStonesAsync(lowerRefineStoneItems, 50, 43, player).ConfigureAwait(false));
result.AddRange(await this.CreateRefineStonesAsync(lowerRefineStoneItems, 20, 43, player).ConfigureAwait(false));
}

return result;
Expand Down
11 changes: 11 additions & 0 deletions src/GameLogic/PlayerActions/Craftings/RestoreItemCrafting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ public RestoreItemCrafting(SimpleCraftingSettings settings)
{
}

private static int[] PricePerOptLvl => [100_000, 110_000, 120_000, 130_000, 140_000, 150_000, 200_000, 220_000, 240_000, 280_000, 320_000, 360_000, 400_000, 500_000];

/// <inheritdoc />
protected override int GetPrice(byte successRate, IList<CraftingRequiredItemLink> requiredItems)
{
return PricePerOptLvl[requiredItems.FirstOrDefault()?
.Items.FirstOrDefault()?
.ItemOptions.FirstOrDefault(io => io.ItemOption?.OptionType == ItemOptionTypes.HarmonyOption)?
.Level ?? 0];
}

/// <inheritdoc />
protected override async ValueTask<List<Item>> CreateOrModifyResultItemsAsync(IList<CraftingRequiredItemLink> requiredItems, Player player, byte socketSlot)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,22 @@ public class HarmonyJewelConsumeHandlerPlugIn : ItemUpgradeConsumeHandlerPlugIn
/// Initializes a new instance of the <see cref="HarmonyJewelConsumeHandlerPlugIn" /> class.
/// </summary>
public HarmonyJewelConsumeHandlerPlugIn()
: base(new ItemUpgradeConfiguration(ItemOptionTypes.HarmonyOption, true, false, 0.5, ItemFailResult.None))
: base(new ItemUpgradeConfiguration(ItemOptionTypes.HarmonyOption, true, false, 0.6, ItemFailResult.None))
{
}

/// <inheritdoc />
public override ItemIdentifier Key => ItemConstants.JewelOfHarmony;

/// <inheritdoc />
protected override bool ItemCanHaveOption(Item item)
{
if (item.IsAncient())
{
// Until S16E2 ancient and socket items couldn't have harmony options: https://muonline.webzen.com/en/gameinfo/guide/detail/117
return false;
}

return base.ItemCanHaveOption(item);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ namespace MUnique.OpenMU.GameLogic.PlayerActions.ItemConsumeActions;
using MUnique.OpenMU.PlugIns;

/// <summary>
/// Consume handler for the Lower Refine Stone which increases the item option of <see cref="ItemOptionTypes.HarmonyOption"/>.
/// Consume handler for the Higher Refine Stone which increases the item option of <see cref="ItemOptionTypes.HarmonyOption"/>.
/// </summary>
[Guid("A9F58DF6-06DB-4187-B386-9F00382333EE")]
[PlugIn(nameof(HigherRefineStoneConsumeHandlerPlugIn), "Plugin which handles the higher refine stone consumption.")]
public class HigherRefineStoneConsumeHandlerPlugIn : ItemUpgradeConsumeHandlerPlugIn
public class HigherRefineStoneConsumeHandlerPlugIn : RefineStoneUpgradeConsumeHandlerPlugIn
{
/// <summary>
/// Initializes a new instance of the <see cref="HigherRefineStoneConsumeHandlerPlugIn" /> class.
/// </summary>
public HigherRefineStoneConsumeHandlerPlugIn()
: base(new ItemUpgradeConfiguration(ItemOptionTypes.HarmonyOption, false, true, 0.5, ItemFailResult.SetOptionToLevelOne))
: base(new ItemUpgradeConfiguration(ItemOptionTypes.HarmonyOption, false, true, 0.8, ItemFailResult.SetOptionToBaseLevel))
{
}

Expand Down
Loading

0 comments on commit d5cc8ce

Please sign in to comment.