Some checks failed
.NET Core / build (push) Has been cancelled
Break all gates + hold both switches (defenses down) -> the Crown shield drops (C1 B2 16=0). The guild master then stands on the Crown (176,212) and holds for CrownHoldDuration (default 60s, client shows a 60s countdown via C1 B2 15) to capture; capture broadcasts C1 B2 18 + golden text and sets the occupier. Losing a switch or leaving the crown resets the hold (contestable until the siege timer ends). Sinior (223) is now informational guidance. +2 tests (14 total). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
101 lines
3.9 KiB
C#
101 lines
3.9 KiB
C#
// <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;
|
|
}
|
|
|
|
// The throne is taken by holding the Crown, not by talking here — give guidance based on the state.
|
|
await ShowAsync(player, DescribeThroneStep(context, guildName)).ConfigureAwait(false);
|
|
}
|
|
|
|
private static string DescribeThroneStep(CastleSiegeContext context, string guildName)
|
|
{
|
|
if (context.Phase != CastleSiegePhase.Siege)
|
|
{
|
|
return "The siege is not running yet.";
|
|
}
|
|
|
|
if (context.DefensesRemaining > 0)
|
|
{
|
|
return $"Destroy all castle gates first ({context.DefensesRemaining} remaining), then hold both Crown Switches.";
|
|
}
|
|
|
|
var eligible = context.GetShieldEligibleGuild();
|
|
if (eligible is null)
|
|
{
|
|
return "All gates are down! Hold BOTH Crown Switches with your guild — the Crown's shield will drop.";
|
|
}
|
|
|
|
if (eligible == guildName)
|
|
{
|
|
return "Your guild holds both switches and the shield is down — send your GUILD MASTER to hold the Crown to take the throne!";
|
|
}
|
|
|
|
return $"Guild '{eligible}' is holding both switches. Take a switch back to raise their shield.";
|
|
}
|
|
|
|
private static ValueTask ShowAsync(Player player, string text)
|
|
=> player.InvokeViewPlugInAsync<IShowMessagePlugIn>(p => p.ShowMessageAsync(text, MessageType.BlueNormal));
|
|
}
|