Skip to content

Commit

Permalink
Merge branch 'master' into bugfix/joh_upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
sven-n authored Oct 26, 2024
2 parents ea86208 + 19768c2 commit 85fbb7d
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 20 deletions.
14 changes: 11 additions & 3 deletions src/GameLogic/CharacterExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,17 @@ public static bool HasFullAncientSetEquipped(this Character character)
i.ItemSlot <= InventoryConstants.LastEquippableItemSlotIndex
&& i.ItemSlot >= InventoryConstants.FirstEquippableItemSlotIndex
&& i.ItemSetGroups.Any(group => group.AncientSetDiscriminator > 0))
.Select(i => new { Item = i.Definition, Set = i.ItemSetGroups.First(s => s.AncientSetDiscriminator > 0) });
var ancientSets = equippedAncientSetItems.Select(i => i.Set).Distinct();
return ancientSets.Any(set => set.ItemSetGroup?.Items.All(setItem => equippedAncientSetItems.Any(i => i.Item == setItem.ItemDefinition && i.Set == set)) ?? false);
.Select(i =>
new
{
Item = i.Definition,
Set = i.ItemSetGroups.First(s => s.AncientSetDiscriminator > 0),
});
var ancientSets = equippedAncientSetItems.Select(i => i.Set.ItemSetGroup).WhereNotNull().Distinct();
return ancientSets.Any(set =>
set.Items.All(setItem => equippedAncientSetItems.Any(i =>
object.Equals(i.Item, setItem.ItemDefinition)
&& object.Equals(i.Set.ItemSetGroup, set))));
}

/// <summary>
Expand Down
11 changes: 6 additions & 5 deletions src/GameLogic/InventoryStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public InventoryStorage(Player player, IGameContext context)
new ItemStorageAdapter(player.SelectedCharacter?.Inventory ?? throw Error.NotInitializedProperty(player, "SelectedCharacter.Inventory"), FirstEquippableItemSlotIndex, player.GetInventorySize()))
{
this._player = player;
this.EquippedItemsChanged += async eventArgs => await this.UpdateItemsOnChangeAsync(eventArgs.Item).ConfigureAwait(false);
this.EquippedItemsChanged += async eventArgs => await this.UpdateItemsOnChangeAsync(eventArgs.Item, eventArgs.IsEquipped).ConfigureAwait(false);
this._gameContext = context;

if (player.SelectedCharacter.InventoryExtensions > 0)
Expand Down Expand Up @@ -110,7 +110,7 @@ public override async ValueTask<bool> AddItemAsync(byte slot, Item item)
var isEquippedItem = this.IsWearingSlot(slot);
if (isEquippedItem && this.EquippedItemsChanged is { } eventHandler)
{
await eventHandler(new ItemEventArgs(convertedItem ?? item)).ConfigureAwait(false);
await eventHandler(new ItemEventArgs(convertedItem ?? item, true)).ConfigureAwait(false);
}
}

Expand All @@ -124,7 +124,7 @@ public override async ValueTask RemoveItemAsync(Item item)
await base.RemoveItemAsync(item).ConfigureAwait(false);
if (isEquippedItem && this.EquippedItemsChanged is { } eventHandler)
{
await eventHandler(new ItemEventArgs(item)).ConfigureAwait(false);
await eventHandler(new ItemEventArgs(item, false)).ConfigureAwait(false);
}
}

Expand All @@ -133,11 +133,12 @@ private bool IsWearingSlot(int slot)
return slot >= FirstEquippableItemSlotIndex && slot <= LastEquippableItemSlotIndex;
}

private async ValueTask UpdateItemsOnChangeAsync(Item item)
private async ValueTask UpdateItemsOnChangeAsync(Item item, bool isEquipped)
{
this._player.OnAppearanceChanged();

await this._player.ForEachWorldObserverAsync<IAppearanceChangedPlugIn>(
p => p.AppearanceChangedAsync(this._player, item),
p => p.AppearanceChangedAsync(this._player, item, isEquipped),
false).ConfigureAwait(false); // in my tests it was not needed to send the appearance to the own players client.

if (this._player.Attributes is null)
Expand Down
15 changes: 11 additions & 4 deletions src/GameLogic/ItemEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,25 @@ namespace MUnique.OpenMU.GameLogic;
/// </summary>
/// <seealso cref="System.EventArgs" />
public class ItemEventArgs : EventArgs
{
{
/// <summary>
/// Initializes a new instance of the <see cref="ItemEventArgs"/> class.
/// </summary>
/// <param name="item">The item.</param>
public ItemEventArgs(Item item)
/// <param name="item">The item.</param>
/// <param name="isEquipped">Whether equipped or not</param>
public ItemEventArgs(Item item, bool isEquipped)
{
this.Item = item;
this.IsEquipped = isEquipped;
}

/// <summary>
/// Gets the item which is involved at the event.
/// </summary>
public Item Item { get; }
public Item Item { get; }

/// <summary>
/// Gets a value indicating whether the item is equipped at the event.
/// </summary>
public bool IsEquipped { get; }
}
9 changes: 8 additions & 1 deletion src/GameLogic/ItemExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public static byte GetMaximumDurabilityOfOnePiece(this Item item)
/// </returns>
public static bool IsAncient(this Item item)
{
return item.ItemOptions.Any(link => link.ItemOption?.OptionType == ItemOptionTypes.AncientBonus);
return item.ItemSetGroups.Any(itemSet => itemSet.AncientSetDiscriminator > 0);
}

/// <summary>
Expand Down Expand Up @@ -305,6 +305,13 @@ public static ItemAppearance GetAppearance(this Item item)
.Select(option => option.ItemOption!.OptionType!)
.Distinct()
.ForEach(appearance.VisibleOptions.Add);
if (item.IsAncient())
{
// 1. The ancient option is not included in the item.ItemOptions.
// 2. The bonus option is not always existing for ancient items. And it's not marked as visible.
// -> we check it based on the item set group.
appearance.VisibleOptions.Add(ItemOptionTypes.AncientOption);
}
return appearance;
}

Expand Down
7 changes: 4 additions & 3 deletions src/GameLogic/Views/World/IAppearanceChangedPlugIn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ namespace MUnique.OpenMU.GameLogic.Views.World;
/// Interface of a view whose implementation informs about the changed appearance of a player.
/// </summary>
public interface IAppearanceChangedPlugIn : IViewPlugIn
{
{
/// <summary>
/// The appearance of a player changed.
/// </summary>
/// <param name="changedPlayer">The changed player.</param>
/// <param name="changedItem">The changed item.</param>
ValueTask AppearanceChangedAsync(Player changedPlayer, Item changedItem);
/// <param name="changedItem">The changed item.</param>
/// <param name="isEquipped"></param>
ValueTask AppearanceChangedAsync(Player changedPlayer, Item changedItem, bool isEquipped);
}
4 changes: 3 additions & 1 deletion src/GameServer/RemoteView/ItemSerializerExtended.cs
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,9 @@ public int Length
}
}

private int ExcellentIndex => this.Options.HasFlag(OptionFlags.HasOption) ? 6 : 5;
private int AdditionalOptionIndex => this.Options.HasFlag(OptionFlags.HasOption) ? 5 : 4;

private int ExcellentIndex => this.Options.HasFlag(OptionFlags.HasExcellent) ? this.AdditionalOptionIndex + 1 : this.AdditionalOptionIndex;

private int AncientIndex => this.Options.HasFlag(OptionFlags.HasAncient) ? this.ExcellentIndex + 1 : this.ExcellentIndex;

Expand Down
6 changes: 3 additions & 3 deletions src/GameServer/RemoteView/World/AppearanceChangedPlugIn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class AppearanceChangedPlugIn : IAppearanceChangedPlugIn
public AppearanceChangedPlugIn(RemotePlayer player) => this._player = player;

/// <inheritdoc/>
public async ValueTask AppearanceChangedAsync(Player changedPlayer, Item item)
public async ValueTask AppearanceChangedAsync(Player changedPlayer, Item item, bool isEquipped)
{
var connection = this._player.Connection;
if (connection is null || changedPlayer.Inventory is not { } inventory)
Expand Down Expand Up @@ -94,7 +94,7 @@ public class AppearanceChangedExtendedPlugIn : IAppearanceChangedPlugIn
public AppearanceChangedExtendedPlugIn(RemotePlayer player) => this._player = player;

/// <inheritdoc/>
public async ValueTask AppearanceChangedAsync(Player changedPlayer, Item item)
public async ValueTask AppearanceChangedAsync(Player changedPlayer, Item item, bool isEquipped)
{
var connection = this._player.Connection;
if (connection is null || changedPlayer.Inventory is null)
Expand All @@ -105,7 +105,7 @@ public async ValueTask AppearanceChangedAsync(Player changedPlayer, Item item)
await connection.SendAppearanceChangedExtendedAsync(
changedPlayer.GetId(this._player),
item.ItemSlot,
(byte)(item.Definition?.Group ?? 0xFF),
(byte)((isEquipped? item.Definition?.Group : 0xFF) ?? 0xFF),
(ushort)(item.Definition?.Number ?? 0xFFFF),
item.Level,
(byte)(ItemSerializerHelper.GetExcellentByte(item) | ItemSerializerHelper.GetFenrirByte(item)),
Expand Down

0 comments on commit 85fbb7d

Please sign in to comment.