// // SkillResponder.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using NosSmooth.Core.Packets; using NosSmooth.Game.Data.Characters; using NosSmooth.Game.Events.Characters; using NosSmooth.Game.Events.Core; using NosSmooth.Packets.Packets.Server.Skills; using Remora.Results; namespace NosSmooth.Game.PacketHandlers.Characters; /// /// Responds to SkiPacket to add skill to the character. /// public class SkillResponder : IPacketResponder { private readonly Game _game; private readonly EventDispatcher _eventDispatcher; /// /// Initializes a new instance of the class. /// /// The nostale game. /// The event dispatcher. public SkillResponder(Game game, EventDispatcher eventDispatcher) { _game = game; _eventDispatcher = eventDispatcher; } /// public async Task Respond(PacketEventArgs packetArgs, CancellationToken ct = default) { var packet = packetArgs.Packet; Skill primarySkill, secondarySkill; var character = _game.Character; if (character is not null && packet.PrimarySkillId == character.Skills?.PrimarySkill.SkillVNum) { primarySkill = character.Skills.PrimarySkill; } else { primarySkill = new Skill(packet.PrimarySkillId); } if (character is not null && packet.PrimarySkillId == packet.SecondarySkillId) { secondarySkill = primarySkill; } else if (character is not null && packet.SecondarySkillId == character.Skills?.SecondarySkill.SkillVNum) { secondarySkill = character.Skills.SecondarySkill; } else { secondarySkill = new Skill(packet.SecondarySkillId); } var skillsFromPacket = packet.SkillSubPackets?.Select(x => x.SkillId).ToList() ?? new List(); var skillsFromCharacter = character?.Skills is null ? new List() : character.Skills.OtherSkills.Select(x => x.SkillVNum).ToList(); var newSkills = skillsFromPacket.Except(skillsFromCharacter); var oldSkills = skillsFromCharacter.Except(skillsFromPacket); var otherSkillsFromCharacter = new List(character?.Skills?.OtherSkills ?? new Skill[] { }); otherSkillsFromCharacter.RemoveAll(x => oldSkills.Contains(x.SkillVNum)); foreach (var newSkill in newSkills) { otherSkillsFromCharacter.Add(new Skill(newSkill)); } var skills = new Skills(primarySkill, secondarySkill, otherSkillsFromCharacter); await _game.CreateOrUpdateCharacterAsync ( () => new Character(Skills: skills), c => c with { Skills = skills }, ct: ct ); await _eventDispatcher.DispatchEvent(new SkillsReceivedEvent(skills), ct); return Result.FromSuccess(); } }