Some checks failed
.NET Core / build (push) Has been cancelled
The switches used to be held by simply standing near them, and the crown captured by standing near it - clicking a switch only produced the client's "not implemented yet" message. This drives both from the original interaction instead: - Clicking a Crown Switch starts an operation which completes after CastleSiegeSettings.SwitchPushSeconds (15) and keeps the switch for the guild until its operator leaves the switch's area. One player per switch; anybody else clicking it is told another team is on it (C1 B2 14 state 2). - While one guild holds both switches the crown's shield drops for it, and its guild master captures the throne by CLICKING the crown and holding it for CrownHoldTimeSeconds - seeded to 60 now, to match the countdown the client's registration panel hardcodes. The throne stays contestable until the siege ends. - The shield now depends on the switches alone, as in the original; the gates and statues remain what they always were, the obstacle in the way. The switch info packet (C1 B2 20) is broadcast before any switch-state packet because the client's "switch released" handler reads its switch table without checking that it exists - that table is only allocated when the info packet arrives, so the wrong order crashes the client. Also fixed while in here: - The crown registration panel could never be closed: the cancel was only sent while the master still stood on the crown, which is precisely when the hold does NOT break. The panel is now closed for the player it was opened for. - A contested switch was decided by enumeration order. - Panels opened by the siege are closed when it ends. - TryCaptureThrone was dead code carrying a second, diverged rule set. - /csphase advertised the pre-refactor phase names to the client. - The periodic broadcasts keyed off "UtcNow.Second % n", which silently skips when a tick runs late; they count ticks now. The unit tests never compiled against the refactored model - they are migrated to the state machine and guild ids, and cover the new switch and crown rules. A new test proves update 105 writes the configuration into an existing database. ApplyPendingUpdatesTool applies pending configuration updates without the admin panel; it is [Explicit], so it never runs in a normal test pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
56 lines
2.5 KiB
C#
56 lines
2.5 KiB
C#
// <copyright file="CastleSiegeSwitchOperation.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;
|
|
|
|
/// <summary>
|
|
/// One player operating one Crown Switch. The player starts it by clicking the switch and keeps it by
|
|
/// staying in its area; the switch counts as held for the guild once the operation has run its time.
|
|
/// </summary>
|
|
public class CastleSiegeSwitchOperation
|
|
{
|
|
/// <summary>Initializes a new instance of the <see cref="CastleSiegeSwitchOperation"/> class.</summary>
|
|
/// <param name="guildId">The operating player's guild identifier.</param>
|
|
/// <param name="guildName">The operating player's guild name, for display.</param>
|
|
/// <param name="playerId">The operating player's object identifier on the map.</param>
|
|
/// <param name="playerName">The operating player's name, for display.</param>
|
|
/// <param name="switchObjectId">The switch NPC's object identifier on the map.</param>
|
|
/// <param name="startedUtc">When the operation started (UTC).</param>
|
|
public CastleSiegeSwitchOperation(Guid guildId, string guildName, ushort playerId, string playerName, ushort switchObjectId, DateTime startedUtc)
|
|
{
|
|
this.GuildId = guildId;
|
|
this.GuildName = guildName;
|
|
this.PlayerId = playerId;
|
|
this.PlayerName = playerName;
|
|
this.SwitchObjectId = switchObjectId;
|
|
this.StartedUtc = startedUtc;
|
|
}
|
|
|
|
/// <summary>Gets the operating player's guild identifier.</summary>
|
|
public Guid GuildId { get; }
|
|
|
|
/// <summary>Gets the operating player's guild name.</summary>
|
|
public string GuildName { get; }
|
|
|
|
/// <summary>Gets the operating player's object identifier on the map.</summary>
|
|
public ushort PlayerId { get; }
|
|
|
|
/// <summary>Gets the operating player's name.</summary>
|
|
public string PlayerName { get; }
|
|
|
|
/// <summary>Gets the switch NPC's object identifier on the map, which the client's packets refer to.</summary>
|
|
public ushort SwitchObjectId { get; }
|
|
|
|
/// <summary>Gets the point in time (UTC) when the operation started.</summary>
|
|
public DateTime StartedUtc { get; }
|
|
|
|
/// <summary>
|
|
/// Gets a value indicating whether the operation ran its time, so the switch counts for the guild.
|
|
/// </summary>
|
|
public bool IsHeld { get; private set; }
|
|
|
|
/// <summary>Marks the operation as completed, which makes the switch count for the guild.</summary>
|
|
internal void MarkHeld() => this.IsHeld = true;
|
|
}
|