feat(CS): authentic Crown-hold throne capture (S6 protocol) replacing Sinior-talk
Some checks failed
.NET Core / build (push) Has been cancelled
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>
This commit is contained in:
@@ -101,4 +101,82 @@ public class CastleSiegeStatusViewPlugIn : ICastleSiegeStatusViewPlugIn
|
||||
|
||||
await connection.SendAsync(WritePacket).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask SetCrownShieldAsync(bool down)
|
||||
{
|
||||
var connection = this._player.Connection;
|
||||
if (connection is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int WritePacket()
|
||||
{
|
||||
// C1 0C B2 16 <state> <pad> <dword=0> ; state 0 = shield down, 1 = shield up
|
||||
var span = connection.Output.GetSpan(12)[..12];
|
||||
span.Clear();
|
||||
span[0] = 0xC1;
|
||||
span[1] = 0x0C;
|
||||
span[2] = 0xB2;
|
||||
span[3] = 0x16;
|
||||
span[4] = (byte)(down ? 0 : 1);
|
||||
return span.Length;
|
||||
}
|
||||
|
||||
await connection.SendAsync(WritePacket).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask SetCrownRegistAsync(byte state, uint accessMilliseconds)
|
||||
{
|
||||
var connection = this._player.Connection;
|
||||
if (connection is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int WritePacket()
|
||||
{
|
||||
// C1 0C B2 15 <state> <pad3> <accessMs:4 LE @offset 8>
|
||||
var span = connection.Output.GetSpan(12)[..12];
|
||||
span.Clear();
|
||||
span[0] = 0xC1;
|
||||
span[1] = 0x0C;
|
||||
span[2] = 0xB2;
|
||||
span[3] = 0x15;
|
||||
span[4] = state;
|
||||
System.Buffers.Binary.BinaryPrimitives.WriteUInt32LittleEndian(span.Slice(8, 4), accessMilliseconds);
|
||||
return span.Length;
|
||||
}
|
||||
|
||||
await connection.SendAsync(WritePacket).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask AnnounceSealCapturedAsync(string guildName)
|
||||
{
|
||||
var connection = this._player.Connection;
|
||||
if (connection is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int WritePacket()
|
||||
{
|
||||
// C1 0D B2 18 <state=1> <guildName[8] utf8>
|
||||
var span = connection.Output.GetSpan(13)[..13];
|
||||
span.Clear();
|
||||
span[0] = 0xC1;
|
||||
span[1] = 0x0D;
|
||||
span[2] = 0xB2;
|
||||
span[3] = 0x18;
|
||||
span[4] = 1;
|
||||
var bytes = System.Text.Encoding.UTF8.GetBytes(guildName);
|
||||
bytes.AsSpan(0, Math.Min(8, bytes.Length)).CopyTo(span.Slice(5, 8));
|
||||
return span.Length;
|
||||
}
|
||||
|
||||
await connection.SendAsync(WritePacket).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user