feat(ADAMU-CUSTOM): port remote-NPC (open NPC window from anywhere via 0x8000 marker)
This commit is contained in:
@@ -103,6 +103,23 @@ public class GameMap
|
||||
return result;
|
||||
}
|
||||
|
||||
// ADAMU-CUSTOM: remote NPC ("NPC list" mobile feature) — spawn olmuş NPC'yi definition number ile bul.
|
||||
/// <summary>
|
||||
/// Gets a spawned non-player-character on this map by its definition number.
|
||||
/// Used to open an NPC's window remotely (mobile "NPC list" feature), independent
|
||||
/// of the player's position.
|
||||
/// </summary>
|
||||
/// <param name="number">The <see cref="MUnique.OpenMU.DataModel.Configuration.MonsterDefinition.Number"/>.</param>
|
||||
/// <returns>The first matching non-player-character, or <c>null</c>.</returns>
|
||||
public NonPlayerCharacter? GetNpcByNumber(short number)
|
||||
{
|
||||
return this._objectsInMap.Values
|
||||
.OfType<NonPlayerCharacter>()
|
||||
.FirstOrDefault(npc => npc.Definition.Number == number);
|
||||
}
|
||||
|
||||
// ADAMU-CUSTOM end
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attackables in range of the specified coordinates.
|
||||
/// </summary>
|
||||
|
||||
@@ -57,6 +57,39 @@ public class TalkNpcAction
|
||||
}
|
||||
}
|
||||
|
||||
// ADAMU-CUSTOM: remote NPC — NPC'ye definition number ile her yerden konuş (mobile "NPC list").
|
||||
/// <summary>
|
||||
/// Talks to an NPC identified by its definition <paramref name="npcNumber"/>, regardless of the
|
||||
/// player's current position or map (no proximity required). Used by the mobile "NPC list" to
|
||||
/// open a merchant store / chaos machine / vault from anywhere. Loads the NPC's home map if it
|
||||
/// isn't loaded yet, then reuses the normal <see cref="TalkToNpcAsync"/> flow.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <param name="npcNumber">The NPC definition number.</param>
|
||||
public async ValueTask TalkToNpcByNumberAsync(Player player, short npcNumber)
|
||||
{
|
||||
var gameContext = player.GameContext;
|
||||
|
||||
// NPC'nin spawn olduğu haritayı bul, (gerekiyorsa) yükle ve instance'ı al.
|
||||
foreach (var mapDef in gameContext.Configuration.Maps)
|
||||
{
|
||||
if (mapDef.MonsterSpawns is null
|
||||
|| !mapDef.MonsterSpawns.Any(s => s.MonsterDefinition?.Number == npcNumber))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var map = await gameContext.GetMapAsync((ushort)mapDef.Number).ConfigureAwait(false);
|
||||
if (map?.GetNpcByNumber(npcNumber) is { } npc)
|
||||
{
|
||||
await this.TalkToNpcAsync(player, npc).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ADAMU-CUSTOM end
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this action advances the player state to <see cref="PlayerState.NpcDialogOpened" />.
|
||||
/// </summary>
|
||||
|
||||
@@ -29,6 +29,17 @@ internal abstract class TalkNpcHandlerPlugInBase : IPacketHandlerPlugIn
|
||||
public async ValueTask HandlePacketAsync(Player player, Memory<byte> packet)
|
||||
{
|
||||
TalkToNpcRequest message = packet;
|
||||
|
||||
// ADAMU-CUSTOM: remote NPC ("NPC list" mobile feature). Object id'leri her zaman <= 0x7FFF
|
||||
// (GameMap IdGenerator), o yüzden yüksek bit serbest marker. Set edilmişse alt 15 bit bir
|
||||
// NPC *definition number*'dır — o NPC'nin penceresini konum/harita bağımsız aç.
|
||||
if ((message.NpcId & 0x8000) != 0)
|
||||
{
|
||||
await this.TalkNpcAction.TalkToNpcByNumberAsync(player, (short)(message.NpcId & 0x7FFF)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
// ADAMU-CUSTOM end
|
||||
|
||||
if (player.CurrentMap?.GetObject(message.NpcId) is NonPlayerCharacter npc)
|
||||
{
|
||||
await this.TalkNpcAction.TalkToNpcAsync(player, npc).ConfigureAwait(false);
|
||||
|
||||
Reference in New Issue
Block a user