diff --git a/src/GameLogic/PlugIns/SelfDefensePlugIn.cs b/src/GameLogic/PlugIns/SelfDefensePlugIn.cs index 347b93621..b143eebd5 100644 --- a/src/GameLogic/PlugIns/SelfDefensePlugIn.cs +++ b/src/GameLogic/PlugIns/SelfDefensePlugIn.cs @@ -2,12 +2,11 @@ // Licensed under the MIT License. See LICENSE file in the project root for full license information. // -using MUnique.OpenMU.GameLogic.NPC; - namespace MUnique.OpenMU.GameLogic.PlugIns; using System; using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic.NPC; using MUnique.OpenMU.GameLogic.Views; using MUnique.OpenMU.Interfaces; using MUnique.OpenMU.PlugIns; @@ -17,14 +16,16 @@ namespace MUnique.OpenMU.GameLogic.PlugIns; /// [PlugIn(nameof(SelfDefensePlugIn), "Updates the state of the self defense system.")] [Guid("3E702A15-653A-48EF-899C-4CDB2239A90C")] -public class SelfDefensePlugIn : IPeriodicTaskPlugIn, IAttackableGotHitPlugIn +public class SelfDefensePlugIn : IPeriodicTaskPlugIn, IAttackableGotHitPlugIn, ISupportCustomConfiguration, ISupportDefaultCustomConfiguration { - private readonly TimeSpan _selfDefenseTime = TimeSpan.FromSeconds(60); + /// + public SelfDefensePlugInConfiguration? Configuration { get; set; } /// public async ValueTask ExecuteTaskAsync(GameContext gameContext) { - var timedOut = gameContext.SelfDefenseState.Where(s => DateTime.UtcNow.Subtract(s.Value) >= _selfDefenseTime).ToList(); + var configuration = this.Configuration ??= CreateDefaultConfiguration(); + var timedOut = gameContext.SelfDefenseState.Where(s => DateTime.UtcNow.Subtract(s.Value) >= configuration.SelfDefenseTimeOut).ToList(); foreach (var (pair, lastAttack) in timedOut) { if (gameContext.SelfDefenseState.Remove(pair, out _)) @@ -50,6 +51,12 @@ public void AttackableGotHit(IAttackable attackable, IAttacker attacker, HitInfo return; } + if (attackerPlayer.CurrentMiniGame?.AllowPlayerKilling is true) + { + // e.g. during chaos castle + return; + } + if (attackerPlayer.IsSelfDefenseActive(defender)) { // Attacking during self defense period does not initiate another self defense. @@ -70,11 +77,22 @@ public void AttackableGotHit(IAttackable attackable, IAttacker attacker, HitInfo }, (tuple, time) => now); } + /// + public object CreateDefaultConfig() + { + return CreateDefaultConfiguration(); + } + + private static SelfDefensePlugInConfiguration CreateDefaultConfiguration() + { + return new SelfDefensePlugInConfiguration(); + } + private async ValueTask BeginSelfDefenseAsync(Player attacker, Player defender) { var message = $"Self defense is initiated by {attacker.Name}'s attack to {defender.Name}!"; - await defender.InvokeViewPlugInAsync(p => p.ShowMessageAsync(message, MessageType.BlueNormal)); - await attacker.InvokeViewPlugInAsync(p => p.ShowMessageAsync(message, MessageType.BlueNormal)); + await defender.InvokeViewPlugInAsync(p => p.ShowMessageAsync(message, MessageType.BlueNormal)).ConfigureAwait(false); + await attacker.InvokeViewPlugInAsync(p => p.ShowMessageAsync(message, MessageType.BlueNormal)).ConfigureAwait(false); } private async ValueTask EndSelfDefenseAsync(Player attacker, Player defender) diff --git a/src/GameLogic/PlugIns/SelfDefensePlugInConfiguration.cs b/src/GameLogic/PlugIns/SelfDefensePlugInConfiguration.cs new file mode 100644 index 000000000..e9db8d77d --- /dev/null +++ b/src/GameLogic/PlugIns/SelfDefensePlugInConfiguration.cs @@ -0,0 +1,16 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.GameLogic.PlugIns; + +/// +/// Configuration for the . +/// +public class SelfDefensePlugInConfiguration +{ + /// + /// Gets or sets the self defense timeout. + /// + public TimeSpan SelfDefenseTimeOut { get; set; } = TimeSpan.FromMinutes(1); +} \ No newline at end of file