-
Notifications
You must be signed in to change notification settings - Fork 461
Description
Understanding Where to Plug This into OpenMU
OpenMU today basically has:
GameLogic: game rules, player actions, etc. (MUnique.OpenMU.GameLogic) munique.github.io
GameMap + AreaOfInterestManager: controls objects on the map, player/NPC observation, etc. munique.github.io
Packet/Network: package structs and handlers (MUnique.OpenMU.Network, GameServer.MessageHandler). munique.github.io
GuildServer and DataModel: guilds, characters, game configuration, persistence (EF Core + PostgreSQL).
GitHub
A concept of plugin points in GameLogic (player entered/exited, object added/removed from the map, etc.).
GitHub
Castle Siege needs to communicate with all of this.
- Castle Siege Domain Modeling
The first step is to create the Siege "business model" in the DataModel:
New (or extended) entities
In the MUnique.OpenMU.DataModel project:
Castle
Id
Name (e.g., "Valley of Loren")
OwnerGuild (reference to Guild)
TaxRate (float / int)
LastSiegeEnd (DateTime)
CastleSiegeSchedule
Castle
RegistrationStart, RegistrationEnd
SiegeStart, SiegeEnd
CastleSiegeRegistration
CastleSiegeSchedule
Guild
IsAttacker, IsDefender
SignupOrder / Score (depending on the logic)
CastleSiegeState
Castle
CurrentPhase (enum: None, Registration, Preparation, Siege, Finished)
CurrentOwnerGuild
ControllingGuild (who is currently holding the crown)
ControlTimeSeconds
It may also be worthwhile to extend:
Guild
IsCastleOwner (bool)
OwnedCastle (optional FK)
After that, adjust the Persistence project (EF Core) to map these new entities and include them in the DbContext.
- Event Orchestration (Siege State Machine)
Create a service of type “CastleSiegeManager” in the GameLogic/GameServer layer:
public class CastleSiegeManager
{
private readonly IGameContext _gameContext;
private readonly Castle _castle;
private CastleSiegeState _state;
public CastleSiegeManager(IGameContext gameContext, Castle castle) { ... }
public Task TickAsync(CancellationToken ct) { ... } // called periodically
Responsibilities:
Read the schedule (CastleSiegeSchedule) and change the state:
Out of schedule → None
Registration period → Registration
Pre-siege (NPC spawn, gates, announcements) → Preparation
Event time → Siege
Post-event (set owner, apply tax, prizes) → Finished
Interact with the Castle Siege map:
Use the GameMap/AreaOfInterestManager to:
Spawn gates, statues, crown switch, registration NPCs.
Control PVP (map flags/PK allowed).
Register callbacks in plugin points, for example:
ObjectGotKilled → when a gate or statue dies.
GitHub
Control the "crown":
When an attacking guild player uses the crown/switch object:
Validate if they are in the correct area.
Start the "casting" countdown (X seconds).
At the end, mark ControllingGuild = that player's guild.
While ControllingGuild holds, increment ControlTimeSeconds.
If another guild takes the crown, reset or reset according to your desired rule.
End of Siege:
Decide winnerGuild:
Emulating GMO: guild with the most control time / or whoever controls at the end.
Update Castle.OwnerGuild = winnerGuild and save to the DB.
Apply default TaxRate and notify the GuildServer.
- Registration Rules and Economy
Registration
Via NPC registration + commands:
Create a PlayerAction of type RegisterCastleSiegeAction in MUnique.OpenMU.GameLogic.PlayerActions.
Create the corresponding PacketHandler for the client's registration request.
Validations:
Guild master only.
Minimum guild level.
Active registration period (CurrentPhase == Registration).
Registrations are persisted in CastleSiegeRegistration.
Castle Fees and Benefits
Economy Integration:
At any point where the server calculates NPC shop prices, you adjust:
FinalPrice = BasePrice * (1 + castle.TaxRate) if it's a city under the castle's influence.
The extra money goes to the GuildBank (if any) or to a guild's "castle funds" field.
This will likely be plugged into some "item sold to NPC" or "buy from NPC" plugin point.
GitHub
- Integration with the protocol (packets)
The original client has several Castle Siege-specific packages. In OpenMU you have:
Documentation / package generator at MUnique.OpenMU.Network.Packets.
munique.github.io
Steps:
Map the Castle Siege packages from public documentation (without copying code):
Siege status (owner, time, phase).
Guild registration.
Broadcasts (start/end announcements, gates destroyed, crown taken).
Siege minimap/icon updates.
Create the packet XML structs in the Network.Packets project and regenerate the doc/code according to the standard OpenMU flow.
Create the IPacketHandlerPlugIn for:
CS_REGISTER (guild registration).
CS_COMMAND (enter map, warp, siege teleport).
CS_CROWN_USE (packet when the player uses the crown/switch).
On the GameServer, send the following packets:
Start of phase.
Guild change controlling the crown.
End of Siege and announcement of the winner.