-
Notifications
You must be signed in to change notification settings - Fork 486
Castle Siege Crown & Switch Win-Condition Mechanics #726
Copy link
Copy link
Open
Labels
Description
Summary
Implement the core Castle Siege win condition: the crown capture system. Three players from the same attacking side must simultaneously occupy the crown and both switches for a configured duration to capture the castle.
Prerequisites
- Castle Siege NPCs (Gates, Statues, Crown, Switches, Levers) #725 (NPCs) — for
CastleSiegeCrown,CastleSiegeSwitchNPC classes and their intelligence. - Castle Siege Guild Selection & Participant Tracking #724 (Guild Selection) — for join side assignments and
SetPlayerJoinSideAsync. - Castle Siege State Machine #722 (State Machine) — for
CastleSiegeContextandStartstate tick handlers.
Requirements
1. CheckMiddleWinner() — In GameLogic/CastleSiege/CastleSiegeCrownMechanics.cs (new file)
Called every tick (every second) during Start state.
Logic:
- Get
CrownUser,SwitchUsers[0],SwitchUsers[1]fromCastleSiegeContext. - All three must be:
- Non-null.
- Alive (
IsAlive). - In a guild (
GuildStatus != null). - On an attacking side (not
None, notDefense). - On the same attacking side.
- If conditions are not met:
- If the crown user changed or left, send
CrownAccessState.Failto the previous user. - Do not reset accumulated time (capped at
CrownHoldTimeSeconds - 1on fail). - Return.
- If the crown user changed or left, send
- Increment
CrownAccumulatedTimeby the tick interval (1 second). - Send
CrownAccessState.Attemptto the crown user with the current accumulated time. - If
CrownAccumulatedTime >= Configuration.CrownHoldTimeSeconds:- Send
CrownAccessState.Successto the crown user. - Call
ChangeWinnerGuild().
- Send
2. ChangeWinnerGuild() — In the same file
Called when a capture succeeds.
Logic:
- Set
MiddleOwnerGuildIdto the crown user's guild ID. - Swap sides:
- The capturing guild's side becomes
Defense. - The previous
Defenseside becomes the capturing guild's old attack side.
- The capturing guild's side becomes
- Call
SetPlayerJoinSideAsync(killLifeStones: true)to:- Re-assign all players to their new sides.
- Kill all Life Stones.
- Respawn all non-defense players to the attack respawn area.
- Lock the crown (
IsCrownAvailable = false). - Reset
CrownAccumulatedTimeto zero. - Clear
CrownUserand bothSwitchUsers. - Broadcast
CastleSiegeOwnershipChangeNotificationto all players on the CS map.
3. SendSwitchInfo() — In GameLogic/CastleSiege/CastleSiegeSwitchMechanics.cs (new file)
Called every second during Start state.
Logic:
- For each switch (0 and 1):
- Send
CastleSiegeSwitchInfopacket to all players on the CS map with:- Switch ID, state (empty/occupied), occupant's join side, guild name, character name.
- Send
- Determine crown availability:
- If both switch users are non-null and on the same attacking side →
IsCrownAvailable = true. - Otherwise →
IsCrownAvailable = false.
- If both switch users are non-null and on the same attacking side →
- Send
CastleSiegeCrownStateUpdateto all players with the current lock/unlock state.
4. Crown Access State Broadcasting
When the crown user's state changes, send CrownAccessState packet:
| Value | Name | When |
|---|---|---|
| 0 | Attempt |
Player is actively pressing, accumulating time |
| 1 | Success |
Capture completed |
| 2 | Fail |
Player was interrupted (killed, left, switch broken) |
The packet includes the accumulated time in milliseconds.
5. CheckResult() — Called when Start timer expires
In CastleSiegePlugIn.OnEnterStateAsync(End):
- If
MiddleOwnerGuildIdhas a value → that guild is the new castle owner. - If
MiddleOwnerGuildIdis null → the existing castle owner retains ownership. - If ownership changed:
- Update
CastleSiegeData.OwnerGuildId,IsOccupied = true. - Reset tax rates to 0, tribute money to 0 (Phase 10).
- Update
- Save to database.
- Broadcast ownership result.
6. View Interfaces & Remote Views
ICastleSiegeCrownStatePlugIn— sends crown lock/unlock state.ICastleSiegeCrownAccessStatePlugIn— sends crown access state (attempt/success/fail) to the crown user.ICastleSiegeSwitchInfoPlugIn— sends switch occupant info.ICastleSiegeOwnershipChangePlugIn— sends ownership change notification.
Files to Create
| File | Description |
|---|---|
GameLogic/CastleSiege/CastleSiegeCrownMechanics.cs |
CheckMiddleWinner, ChangeWinnerGuild, CheckResult |
GameLogic/CastleSiege/CastleSiegeSwitchMechanics.cs |
SendSwitchInfo, crown availability |
GameLogic/Views/CastleSiege/ICastleSiegeCrownStatePlugIn.cs |
View interface |
GameLogic/Views/CastleSiege/ICastleSiegeCrownAccessStatePlugIn.cs |
View interface |
GameLogic/Views/CastleSiege/ICastleSiegeSwitchInfoPlugIn.cs |
View interface |
GameLogic/Views/CastleSiege/ICastleSiegeOwnershipChangePlugIn.cs |
View interface |
GameServer/RemoteView/CastleSiege/CastleSiegeCrownStatePlugIn.cs |
Remote view |
GameServer/RemoteView/CastleSiege/CastleSiegeCrownAccessStatePlugIn.cs |
Remote view |
GameServer/RemoteView/CastleSiege/CastleSiegeSwitchInfoPlugIn.cs |
Remote view |
GameServer/RemoteView/CastleSiege/CastleSiegeOwnershipChangePlugIn.cs |
Remote view |
Acceptance Criteria
- Crown capture requires all 3 positions (crown + 2 switches) held by the same attacking side.
- Accumulated time increments only when all 3 conditions are met.
- Capture occurs when accumulated time reaches
CrownHoldTimeSeconds. - On capture: sides are swapped, all players re-assigned, Life Stones killed, crown locked.
- Accumulated time is capped at
CrownHoldTimeSeconds - 1on failure (not reset to 0). - Switch info is broadcast every second showing occupant details.
- Crown lock/unlock state is broadcast based on switch occupancy.
- At battle end, the final winner is correctly determined.
- Ownership change triggers tax reset.
Reactions are currently unavailable