feat(castle-siege): adopt the upstream Castle Siege data model and persistence
Brings in the database layer of upstream OpenMU PRs #754 and #860 without touching AdaMu's working Castle Siege gameplay. This is purely additive: the existing 5-phase implementation still runs exactly as before. What is included: - DataModel: CastleSiegeState (the original Season 6 values 0-9, which are exactly what the game client's CASTLESIEGE_STATE enum expects), CastleSiegeJoinSide, and the zone/NPC/upgrade definition types. - Entities: CastleSiegeData, CastleSiegeGuildRegistration, CastleSiegeNpcState. These identify a guild by its persistent Guid rather than by name. - Generated persistence: 8 BasicModel + 8 EntityFramework model classes, CastleSiegeExtensions, and the regenerated ExtendedTypeContext, MapsterConfigurator and GameConfiguration partials. - Migrations: 20260730194321_AddCastleSiege and 20260801162427_ConfigureCastleSiegePersistence, plus the model snapshot. - EntityDataContext gains the two DbSets and the five model registrations. - EntityFrameworkContextBase only publishes configuration changes for entities in the configuration schema, so siege state writes are no longer broadcast as configuration changes. AdaMu-specific adaptations: - UpdateVersion.AddCastleSiegeData is 105, not upstream's 100. AdaMu already ships 95-104, and the applied-update bookkeeping is keyed on this value, so a collision would skip or re-run updates on live databases. - CastleSiegeInitializer does not seed a weekly StateSchedule. Upstream drives the cycle from a fixed Saturday schedule; AdaMu drives it manually from CastleSiegeEventPlugIn and the AdminPanel, so the schedule is left empty and nothing reads it. The seeded NPC definitions match AdaMu's existing hard-coded coordinates exactly (6 gates, the two crown switches and the crown), and additionally provide 4 guardian statues, 6 guardsmen and real gate/statue hit point tables that the current implementation does not have yet. Two pre-existing migrations were restyled by upstream (copyright header, using placement, trailing comma). No functional change. Verified: full server build succeeds with 0 errors.
This commit is contained in:
152
src/DataModel/Configuration/CastleSiegeConfiguration.cs
Normal file
152
src/DataModel/Configuration/CastleSiegeConfiguration.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
// <copyright file="CastleSiegeConfiguration.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Configuration;
|
||||
|
||||
using MUnique.OpenMU.Annotations;
|
||||
using MUnique.OpenMU.DataModel.Configuration.Items;
|
||||
|
||||
/// <summary>
|
||||
/// Main configuration for the castle siege event.
|
||||
/// </summary>
|
||||
[Cloneable]
|
||||
public partial class CastleSiegeConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the castle siege feature is enabled.
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of seconds a guild must hold the crown to capture the castle.
|
||||
/// </summary>
|
||||
public int CrownHoldTimeSeconds { get; set; } = 30;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum combined level of a guild master required to register for the siege.
|
||||
/// </summary>
|
||||
public int RegisterMinLevel { get; set; } = 200;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum number of guild members required to register for the siege.
|
||||
/// </summary>
|
||||
public int RegisterMinMembers { get; set; } = 20;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum number of seconds a participant must be present in the battle to be eligible for a reward.
|
||||
/// </summary>
|
||||
public int ParticipantRewardMinSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of attacking alliance slots.
|
||||
/// </summary>
|
||||
public int MaxAttackingGuilds { get; set; } = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the guild score awarded to the guild that wins the siege.
|
||||
/// </summary>
|
||||
public int GuildScoreCastleSiege { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the guild score awarded to alliance member guilds of the winning side.
|
||||
/// </summary>
|
||||
public int GuildScoreCastleSiegeMembers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Zen cost for the castle owner to re-purchase a destroyed gate.
|
||||
/// </summary>
|
||||
public int GateBuyPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Zen cost for the castle owner to re-purchase a destroyed statue.
|
||||
/// </summary>
|
||||
public int StatueBuyPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the map definition for the Valley of Loren (map 30), where the siege takes place.
|
||||
/// </summary>
|
||||
public virtual GameMapDefinition? CastleSiegeMapDefinition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the map definition for the Land of Trials (map 31), the castle-owner's exclusive zone.
|
||||
/// </summary>
|
||||
public virtual GameMapDefinition? LandOfTrialsMapDefinition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item definition for the participation reward item.
|
||||
/// </summary>
|
||||
public virtual ItemDefinition? RewardItemDefinition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the schedule entries that define when each siege state begins.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeStateScheduleEntry> StateSchedule { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the definitions for all castle siege NPCs (gates, statues, etc.).
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeNpcDefinition> NpcDefinitions { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the upgrade levels for gate defense.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeUpgradeDefinition> GateDefenseUpgrades { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the upgrade levels for gate maximum HP.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeUpgradeDefinition> GateLifeUpgrades { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the upgrade levels for statue defense.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeUpgradeDefinition> StatueDefenseUpgrades { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the upgrade levels for statue maximum HP.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeUpgradeDefinition> StatueLifeUpgrades { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the upgrade levels for statue HP regeneration.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeUpgradeDefinition> StatueRegenUpgrades { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the zones on the siege map where attacking siege machines may be placed.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeZoneDefinition> AttackMachineZones { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the zones on the siege map where defensive siege machines may be placed.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeZoneDefinition> DefenseMachineZones { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the zone where defending players respawn during the siege.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual CastleSiegeZoneDefinition? DefenseRespawnArea { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the zone where attacking players respawn during the siege.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual CastleSiegeZoneDefinition? AttackRespawnArea { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return "Castle Siege Configuration";
|
||||
}
|
||||
}
|
||||
36
src/DataModel/Configuration/CastleSiegeJoinSide.cs
Normal file
36
src/DataModel/Configuration/CastleSiegeJoinSide.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
// <copyright file="CastleSiegeJoinSide.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the side (defending or attacking) a guild or NPC belongs to in the castle siege.
|
||||
/// </summary>
|
||||
public enum CastleSiegeJoinSide : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// No side assigned.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The defending guild side.
|
||||
/// </summary>
|
||||
Defense = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The first attacking alliance slot.
|
||||
/// </summary>
|
||||
Attack1 = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The second attacking alliance slot.
|
||||
/// </summary>
|
||||
Attack2 = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The third attacking alliance slot.
|
||||
/// </summary>
|
||||
Attack3 = 4,
|
||||
}
|
||||
55
src/DataModel/Configuration/CastleSiegeNpcDefinition.cs
Normal file
55
src/DataModel/Configuration/CastleSiegeNpcDefinition.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// <copyright file="CastleSiegeNpcDefinition.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Configuration;
|
||||
|
||||
using MUnique.OpenMU.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a castle siege NPC instance, including its spawn location, side, and persistence settings.
|
||||
/// </summary>
|
||||
[Cloneable]
|
||||
public partial class CastleSiegeNpcDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the monster definition template for this NPC.
|
||||
/// </summary>
|
||||
public virtual MonsterDefinition? MonsterDefinition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the unique instance identifier within its NPC type.
|
||||
/// </summary>
|
||||
public byte InstanceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this NPC's state is persisted to the database between sieges.
|
||||
/// </summary>
|
||||
public bool IsPersistedToDatabase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default join side this NPC belongs to.
|
||||
/// </summary>
|
||||
public CastleSiegeJoinSide DefaultSide { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the X coordinate of the NPC's spawn position.
|
||||
/// </summary>
|
||||
public byte SpawnX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Y coordinate of the NPC's spawn position.
|
||||
/// </summary>
|
||||
public byte SpawnY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the facing direction of the NPC at spawn.
|
||||
/// </summary>
|
||||
public Direction Direction { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{this.MonsterDefinition} #{this.InstanceId} at ({this.SpawnX},{this.SpawnY})";
|
||||
}
|
||||
}
|
||||
61
src/DataModel/Configuration/CastleSiegeState.cs
Normal file
61
src/DataModel/Configuration/CastleSiegeState.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
// <copyright file="CastleSiegeState.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// The state of the castle siege event cycle.
|
||||
/// </summary>
|
||||
public enum CastleSiegeState : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Idle state before guild registration opens.
|
||||
/// </summary>
|
||||
Idle1 = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Guilds may register for the siege.
|
||||
/// </summary>
|
||||
RegisterGuild = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Idle state after guild registration.
|
||||
/// </summary>
|
||||
Idle2 = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Guilds may register emblems (Marks of Lord) to determine the attacking guilds.
|
||||
/// </summary>
|
||||
RegisterMark = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Idle state after mark registration.
|
||||
/// </summary>
|
||||
Idle3 = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Players are notified that the siege is about to start.
|
||||
/// </summary>
|
||||
Notify = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The siege map is prepared and entry is allowed.
|
||||
/// </summary>
|
||||
Ready = 6,
|
||||
|
||||
/// <summary>
|
||||
/// The siege battle is in progress.
|
||||
/// </summary>
|
||||
Start = 7,
|
||||
|
||||
/// <summary>
|
||||
/// The siege battle has ended and results are being processed.
|
||||
/// </summary>
|
||||
End = 8,
|
||||
|
||||
/// <summary>
|
||||
/// The full siege cycle has completed.
|
||||
/// </summary>
|
||||
EndCycle = 9,
|
||||
}
|
||||
40
src/DataModel/Configuration/CastleSiegeStateScheduleEntry.cs
Normal file
40
src/DataModel/Configuration/CastleSiegeStateScheduleEntry.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
// <copyright file="CastleSiegeStateScheduleEntry.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Configuration;
|
||||
|
||||
using MUnique.OpenMU.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a scheduled transition to a specific <see cref="CastleSiegeState"/> at a given day and time.
|
||||
/// </summary>
|
||||
[Cloneable]
|
||||
public partial class CastleSiegeStateScheduleEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the siege state that becomes active at the scheduled time.
|
||||
/// </summary>
|
||||
public CastleSiegeState State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the day of the week on which this state transition occurs.
|
||||
/// </summary>
|
||||
public DayOfWeek DayOfWeek { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the hour (0–23) at which this state transition occurs.
|
||||
/// </summary>
|
||||
public byte Hour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minute (0–59) at which this state transition occurs.
|
||||
/// </summary>
|
||||
public byte Minute { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{this.State} on {this.DayOfWeek} at {this.Hour:D2}:{this.Minute:D2}";
|
||||
}
|
||||
}
|
||||
40
src/DataModel/Configuration/CastleSiegeUpgradeDefinition.cs
Normal file
40
src/DataModel/Configuration/CastleSiegeUpgradeDefinition.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
// <copyright file="CastleSiegeUpgradeDefinition.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Configuration;
|
||||
|
||||
using MUnique.OpenMU.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Defines one level of an upgrade that the castle owner can apply to a gate or statue NPC.
|
||||
/// </summary>
|
||||
[Cloneable]
|
||||
public partial class CastleSiegeUpgradeDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the upgrade level (0–3), where 0 represents the base/unupgraded state.
|
||||
/// </summary>
|
||||
public byte Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of Jewels of Guardian required to perform this upgrade.
|
||||
/// </summary>
|
||||
public int RequiredJewelOfGuardianCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount of Zen required to perform this upgrade.
|
||||
/// </summary>
|
||||
public int RequiredZen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the resulting stat value granted by this upgrade level (defense or max HP).
|
||||
/// </summary>
|
||||
public int Value { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Level {this.Level}: Value={this.Value}, Jewels={this.RequiredJewelOfGuardianCount}, Zen={this.RequiredZen}";
|
||||
}
|
||||
}
|
||||
31
src/DataModel/Configuration/CastleSiegeUpgradeType.cs
Normal file
31
src/DataModel/Configuration/CastleSiegeUpgradeType.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
// <copyright file="CastleSiegeUpgradeType.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// The type of upgrade applied to a castle siege NPC (gate or statue).
|
||||
/// </summary>
|
||||
public enum CastleSiegeUpgradeType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// No upgrade type assigned.
|
||||
/// </summary>
|
||||
Undefined = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Increases the defense stat of the NPC.
|
||||
/// </summary>
|
||||
Defense = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Increases the HP regeneration rate of the NPC.
|
||||
/// </summary>
|
||||
Regen = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Increases the maximum HP of the NPC.
|
||||
/// </summary>
|
||||
Life = 3,
|
||||
}
|
||||
40
src/DataModel/Configuration/CastleSiegeZoneDefinition.cs
Normal file
40
src/DataModel/Configuration/CastleSiegeZoneDefinition.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
// <copyright file="CastleSiegeZoneDefinition.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Configuration;
|
||||
|
||||
using MUnique.OpenMU.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a rectangular zone on the castle siege map, used for spawn areas and machine zones.
|
||||
/// </summary>
|
||||
[Cloneable]
|
||||
public partial class CastleSiegeZoneDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the top-left X coordinate of the zone.
|
||||
/// </summary>
|
||||
public byte X1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the top-left Y coordinate of the zone.
|
||||
/// </summary>
|
||||
public byte Y1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom-right X coordinate of the zone.
|
||||
/// </summary>
|
||||
public byte X2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bottom-right Y coordinate of the zone.
|
||||
/// </summary>
|
||||
public byte Y2 { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{this.X1} / {this.Y1} to {this.X2} / {this.Y2}";
|
||||
}
|
||||
}
|
||||
@@ -300,6 +300,12 @@ public partial class GameConfiguration
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<MiniGameDefinition> MiniGameDefinitions { get; protected set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the castle siege configuration.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual CastleSiegeConfiguration? CastleSiegeConfiguration { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
67
src/DataModel/Entities/CastleSiegeData.cs
Normal file
67
src/DataModel/Entities/CastleSiegeData.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
// <copyright file="CastleSiegeData.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Persistent state of the castle siege, stored as a single row across siege cycles.
|
||||
/// </summary>
|
||||
[AggregateRoot]
|
||||
public class CastleSiegeData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the unique identifier of this record.
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the persistent identifier of the guild that currently owns the castle.
|
||||
/// <see langword="null"/> when no guild owns the castle.
|
||||
/// </summary>
|
||||
public Guid? OwnerGuildId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether any guild currently occupies the castle.
|
||||
/// </summary>
|
||||
public bool IsOccupied { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Chaos Machine tax rate applied by the castle owner (0–3).
|
||||
/// </summary>
|
||||
public byte TaxChaos { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the personal store tax rate applied by the castle owner (0–3).
|
||||
/// </summary>
|
||||
public byte TaxStore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the entry fee (in Zen) for the castle owner's hunt zone (0–300000).
|
||||
/// </summary>
|
||||
public int TaxHunt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the hunt zone (Land of Trials) is currently open to the public.
|
||||
/// </summary>
|
||||
public bool IsHuntZoneEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the accumulated tribute money collected from the hunt zone and taxes.
|
||||
/// </summary>
|
||||
public long TributeMoney { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the persisted states of all castle NPCs.
|
||||
/// </summary>
|
||||
[MemberOfAggregate]
|
||||
public virtual ICollection<CastleSiegeNpcState> NpcStates { get; protected set; } = null!;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return this.IsOccupied
|
||||
? $"Castle owned by guild {this.OwnerGuildId}"
|
||||
: "Castle unoccupied";
|
||||
}
|
||||
}
|
||||
44
src/DataModel/Entities/CastleSiegeGuildRegistration.cs
Normal file
44
src/DataModel/Entities/CastleSiegeGuildRegistration.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
// <copyright file="CastleSiegeGuildRegistration.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Stores a guild's registration data for the current castle siege cycle,
|
||||
/// including the number of emblems submitted to determine attacking guilds.
|
||||
/// </summary>
|
||||
[AggregateRoot]
|
||||
public class CastleSiegeGuildRegistration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the unique identifier of this registration record.
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the persistent identifier of the registered guild.
|
||||
/// </summary>
|
||||
public Guid GuildId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the guild name, denormalized for convenience to avoid extra lookups during siege processing.
|
||||
/// </summary>
|
||||
public string GuildName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of Emblems of Lord registered by this guild.
|
||||
/// </summary>
|
||||
public int Marks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the insertion order of this registration, used for tie-breaking when guilds have equal marks.
|
||||
/// </summary>
|
||||
public int RegistrationOrder { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{this.GuildName} (Marks={this.Marks}, Order={this.RegistrationOrder})";
|
||||
}
|
||||
}
|
||||
52
src/DataModel/Entities/CastleSiegeNpcState.cs
Normal file
52
src/DataModel/Entities/CastleSiegeNpcState.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
// <copyright file="CastleSiegeNpcState.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.DataModel.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Persistent state of a single castle siege NPC between siege cycles.
|
||||
/// </summary>
|
||||
public class CastleSiegeNpcState
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the unique identifier of this NPC state.
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the monster definition number that identifies the NPC template.
|
||||
/// </summary>
|
||||
public short MonsterNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the instance identifier matching <see cref="MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition.InstanceId"/>.
|
||||
/// </summary>
|
||||
public byte InstanceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current defense upgrade level (0–3).
|
||||
/// </summary>
|
||||
public byte DefenseLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current HP regeneration upgrade level (0–3).
|
||||
/// </summary>
|
||||
public byte RegenLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current maximum HP upgrade level (0–3).
|
||||
/// </summary>
|
||||
public byte LifeLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current HP of the NPC. A value of 0 means the NPC is destroyed.
|
||||
/// </summary>
|
||||
public int CurrentHp { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"NPC {this.MonsterNumber} #{this.InstanceId} (HP={this.CurrentHp})";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user