~ruther/NosSmooth

829e95c9afae2ffe37ed710f4a45e080f0e196c0 — Rutherther 2 years ago e940380
feat(game): make sure skill cooldown reset is interpreted correctly when sent before "su"
M Core/NosSmooth.Game/Data/Characters/Skill.cs => Core/NosSmooth.Game/Data/Characters/Skill.cs +11 -1
@@ 17,11 17,16 @@ namespace NosSmooth.Game.Data.Characters;
public record Skill(int SkillVNum, int? Level = default, ISkillInfo? Info = default)
{
    /// <summary>
    /// Gets the last time this skill was used.
    /// Gets the last time this skill was used. (su received).
    /// </summary>
    public DateTimeOffset LastUseTime { get; internal set; }

    /// <summary>
    /// Gets the last time this skill was requested to be used. (u_s sent).
    /// </summary>
    public DateTimeOffset? LastUseRequestTime { get; internal set; }

    /// <summary>
    /// Gets whether the skill is on cooldown.
    /// </summary>
    /// <remarks>


@@ 29,4 34,9 @@ public record Skill(int SkillVNum, int? Level = default, ISkillInfo? Info = defa
    /// prefer to use this instead of checking the LastUseTime and Cooldown.
    /// </remarks>
    public bool IsOnCooldown { get; internal set; }

    /// <summary>
    /// Gets the last time the cooldown was reset.
    /// </summary>
    public DateTimeOffset? LastCooldownReset { get; internal set; }
}
\ No newline at end of file

M Core/NosSmooth.Game/PacketHandlers/Entities/SkillUsedResponder.cs => Core/NosSmooth.Game/PacketHandlers/Entities/SkillUsedResponder.cs +48 -3
@@ 17,6 17,7 @@ using NosSmooth.Game.Events.Core;
using NosSmooth.Game.Events.Entities;
using NosSmooth.Game.Extensions;
using NosSmooth.Game.Helpers;
using NosSmooth.Packets.Client.Battle;
using NosSmooth.Packets.Enums.Entities;
using NosSmooth.Packets.Server.Battle;
using NosSmooth.Packets.Server.Skills;


@@ 27,7 28,7 @@ namespace NosSmooth.Game.PacketHandlers.Entities;
/// <summary>
/// Responds to skill used packet.
/// </summary>
public class SkillUsedResponder : IPacketResponder<SuPacket>, IPacketResponder<SrPacket>
public class SkillUsedResponder : IPacketResponder<SuPacket>, IPacketResponder<SrPacket>, IPacketResponder<UseAOESkillPacket>, IPacketResponder<UseSkillPacket>
{
    private readonly Game _game;
    private readonly EventDispatcher _eventDispatcher;


@@ 93,14 94,19 @@ public class SkillUsedResponder : IPacketResponder<SuPacket>, IPacketResponder<S

        Skill? skillEntity;
        var skills = _game.Skills;
        if (packet.SkillVNum is not null && caster is Character character && skills is not null)
        if (packet.SkillVNum is not null && caster is Character && skills is not null)
        {
            var skillResult = skills.TryGetSkillByVNum(packet.SkillVNum.Value);

            if (skillResult.IsDefined(out skillEntity))
            {
                skillEntity.LastUseTime = DateTimeOffset.Now;
                skillEntity.IsOnCooldown = true;

                if (skillEntity.LastUseRequestTime is null || skillEntity.LastCooldownReset is null
                    || skillEntity.LastUseRequestTime > skillEntity.LastCooldownReset)
                {
                    skillEntity.IsOnCooldown = true;
                }
            }
            else
            {


@@ 179,6 185,7 @@ public class SkillUsedResponder : IPacketResponder<SuPacket>, IPacketResponder<S
            if (skillResult.IsDefined(out var skillEntity))
            {
                skillEntity.IsOnCooldown = false;
                skillEntity.LastCooldownReset = DateTime.Now;
            }

            await _eventDispatcher.DispatchEvent


@@ 191,4 198,42 @@ public class SkillUsedResponder : IPacketResponder<SuPacket>, IPacketResponder<S

        return Result.FromSuccess();
    }

    /// <inheritdoc />
    public Task<Result> Respond(PacketEventArgs<UseAOESkillPacket> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;

        var skills = _game.Skills;
        if (skills is not null)
        {
            var skillResult = skills.TryGetSkillByCastId((short)packet.SkillId);

            if (skillResult.IsDefined(out var skillEntity))
            {
                skillEntity.LastUseRequestTime = DateTime.Now;
            }
        }

        return Task.FromResult(Result.FromSuccess());
    }

    /// <inheritdoc />
    public Task<Result> Respond(PacketEventArgs<UseSkillPacket> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;

        var skills = _game.Skills;
        if (skills is not null)
        {
            var skillResult = skills.TryGetSkillByCastId(packet.CastId);

            if (skillResult.IsDefined(out var skillEntity))
            {
                skillEntity.LastUseRequestTime = DateTime.Now;
            }
        }

        return Task.FromResult(Result.FromSuccess());
    }
}
\ No newline at end of file

Do not follow this link