feat(CS-P3): throne registration via Sinior/Crown talk (223/216) after defenses down + both switches held; reachable defense positions
Some checks failed
.NET Core / build (push) Has been cancelled

This commit is contained in:
Acentech Dev
2026-07-15 02:49:27 +03:00
parent db8bdd394f
commit 72ebc96e28
4 changed files with 122 additions and 30 deletions

View File

@@ -0,0 +1,83 @@
// <copyright file="CastleSiegeThroneCaptureTalkPlugIn.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.GameLogic.CastleSiege;
using System.Linq;
using System.Runtime.InteropServices;
using MUnique.OpenMU.GameLogic.NPC;
using MUnique.OpenMU.GameLogic.PlugIns;
using MUnique.OpenMU.GameLogic.PlugIns.PeriodicTasks;
using MUnique.OpenMU.GameLogic.Views;
using MUnique.OpenMU.Interfaces;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// Handles registering on the throne at the Sinior (223) / Crown (216) NPCs on Valley of Loren.
/// A registered guild takes the throne only when it has destroyed all castle defenses (gates + statues)
/// AND is holding both Crown Switches (a member standing on each). The guild on the throne when the siege
/// ends becomes the castle owner. Capturing broadcasts a server-wide golden message.
/// </summary>
[Guid("CA5710A0-7A1B-4C2D-8E3F-000000000223")]
[PlugIn]
[Display(Name = "Castle Siege Throne (Sinior/Crown)", Description = "Registers a guild on the throne (Sinior 223 / Crown 216) once defenses are down and both switches held.")]
public class CastleSiegeThroneCaptureTalkPlugIn : IPlayerTalkToNpcPlugIn
{
private static readonly short[] ThroneNpcNumbers = { 223, 216 };
/// <inheritdoc />
public async ValueTask PlayerTalksToNpcAsync(Player player, NonPlayerCharacter npc, NpcTalkEventArgs eventArgs)
{
if (!ThroneNpcNumbers.Contains(npc.Definition.Number))
{
return;
}
eventArgs.HasBeenHandled = true;
var context = CastleSiegeEventPlugIn.TryGetContext(player.GameContext);
if (context is null)
{
await ShowAsync(player, "Castle Siege is not active on this server.").ConfigureAwait(false);
return;
}
if (player.GuildStatus is not { } guildStatus)
{
await ShowAsync(player, "Only members of a registered guild can take the throne.").ConfigureAwait(false);
return;
}
var guildName = guildStatus.GuildId.ToString();
if (player.GameContext is IGameServerContext serverContext)
{
var guild = await serverContext.GuildServer.GetGuildAsync(guildStatus.GuildId).ConfigureAwait(false);
if (guild?.Name is { Length: > 0 } name)
{
guildName = name;
}
}
if (!context.RegisteredGuilds.Contains(guildName))
{
await ShowAsync(player, "Your guild is not registered for this Castle Siege.").ConfigureAwait(false);
return;
}
var (success, reason) = context.TryCaptureThrone(guildName);
if (success)
{
await player.GameContext.ForEachPlayerAsync(p =>
p.InvokeViewPlugInAsync<IShowMessagePlugIn>(v =>
v.ShowMessageAsync($"Guild '{guildName}' has CAPTURED THE THRONE! They will win the castle if they hold it until the siege ends.", MessageType.GoldenCenter)).AsTask()).ConfigureAwait(false);
}
else
{
await ShowAsync(player, reason).ConfigureAwait(false);
}
}
private static ValueTask ShowAsync(Player player, string text)
=> player.InvokeViewPlugInAsync<IShowMessagePlugIn>(p => p.ShowMessageAsync(text, MessageType.BlueNormal));
}