<commit_before>﻿using AutomaticTypeMapper;
using EOLib.Domain.Character;
using EOLib.Domain.Login;
using EOLib.Domain.Notifiers;
using EOLib.IO.Map;
using EOLib.Net;
using EOLib.Net.Handlers;
using System;
using System.Collections.Generic;

namespace EOLib.PacketHandlers.Effects
{
    [AutoMappedType]
    public class MapDebuffHandler : InGameOnlyPacketHandler
    {
        private const int EFFECT_DAMAGE_TPDRAIN = 1;
        private const int EFFECT_DAMAGE_SPIKE = 2;

        private readonly ICharacterRepository _characterRepository;
        private readonly IEnumerable<IMainCharacterEventNotifier> _mainCharacterEventNotifiers;
        private readonly IEnumerable<IEffectNotifier> _effectNotifiers;

        public override PacketFamily Family => PacketFamily.Effect;

        public override PacketAction Action => PacketAction.Spec;

        public MapDebuffHandler(IPlayerInfoProvider playerInfoProvider,
                                ICharacterRepository characterRepository,
                                IEnumerable<IMainCharacterEventNotifier> mainCharacterEventNotifiers,
                                IEnumerable<IEffectNotifier> effectNotifiers)
            : base(playerInfoProvider)
        {
            _characterRepository = characterRepository;
            _mainCharacterEventNotifiers = mainCharacterEventNotifiers;
            _effectNotifiers = effectNotifiers;
        }

        public override bool HandlePacket(IPacket packet)
        {
            var character = _characterRepository.MainCharacter;
            var originalStats = character.Stats;

            //1 in eoserv Map::TimedDrains - tp
            //2 in eoserv Character::SpikeDamage
            var damageType = packet.ReadChar();
            switch (damageType)
            {
                case EFFECT_DAMAGE_TPDRAIN:
                    {
                        // todo: show amount in damage counter
                        var amount = packet.ReadShort();
                        var tp = packet.ReadShort();
                        var maxTp = packet.ReadShort();
                        _characterRepository.MainCharacter = character.WithStats(
                            originalStats.WithNewStat(CharacterStat.TP, tp)
                                .WithNewStat(CharacterStat.MaxTP, maxTp));

                        foreach (var notifier in _effectNotifiers)
                            notifier.NotifyMapEffect(MapEffect.TPDrain);
                    }
                    break;
                case EFFECT_DAMAGE_SPIKE:
                    {
                        // todo: show amount in damage counter
                        var damage = packet.ReadShort();
                        var hp = packet.ReadShort();
                        var maxHp = packet.ReadShort();
                        character = character.WithStats(originalStats.WithNewStat(CharacterStat.HP, hp)
                                                                     .WithNewStat(CharacterStat.MaxHP, maxHp));

                        character = character.WithRenderProperties(character.RenderProperties.WithIsDead(hp <= 0));

                        _characterRepository.MainCharacter = character;

                        foreach (var notifier in _mainCharacterEventNotifiers)
                            notifier.NotifyTakeDamage(damage, (int)Math.Round((double)hp / maxHp) * 100, isHeal: false);
                    }
                    break;
                default:
                    return false;
            }

            return true;
        }
    }
}<commit_msg>Fix percent health display when taking spikes damage<commit_after>﻿using AutomaticTypeMapper;
using EOLib.Domain.Character;
using EOLib.Domain.Login;
using EOLib.Domain.Notifiers;
using EOLib.IO.Map;
using EOLib.Net;
using EOLib.Net.Handlers;
using System;
using System.Collections.Generic;

namespace EOLib.PacketHandlers.Effects
{
    [AutoMappedType]
    public class MapDebuffHandler : InGameOnlyPacketHandler
    {
        private const int EFFECT_DAMAGE_TPDRAIN = 1;
        private const int EFFECT_DAMAGE_SPIKE = 2;

        private readonly ICharacterRepository _characterRepository;
        private readonly IEnumerable<IMainCharacterEventNotifier> _mainCharacterEventNotifiers;
        private readonly IEnumerable<IEffectNotifier> _effectNotifiers;

        public override PacketFamily Family => PacketFamily.Effect;

        public override PacketAction Action => PacketAction.Spec;

        public MapDebuffHandler(IPlayerInfoProvider playerInfoProvider,
                                ICharacterRepository characterRepository,
                                IEnumerable<IMainCharacterEventNotifier> mainCharacterEventNotifiers,
                                IEnumerable<IEffectNotifier> effectNotifiers)
            : base(playerInfoProvider)
        {
            _characterRepository = characterRepository;
            _mainCharacterEventNotifiers = mainCharacterEventNotifiers;
            _effectNotifiers = effectNotifiers;
        }

        public override bool HandlePacket(IPacket packet)
        {
            var character = _characterRepository.MainCharacter;
            var originalStats = character.Stats;

            //1 in eoserv Map::TimedDrains - tp
            //2 in eoserv Character::SpikeDamage
            var damageType = packet.ReadChar();
            switch (damageType)
            {
                case EFFECT_DAMAGE_TPDRAIN:
                    {
                        // todo: show amount in damage counter
                        var amount = packet.ReadShort();
                        var tp = packet.ReadShort();
                        var maxTp = packet.ReadShort();
                        _characterRepository.MainCharacter = character.WithStats(
                            originalStats.WithNewStat(CharacterStat.TP, tp)
                                .WithNewStat(CharacterStat.MaxTP, maxTp));

                        foreach (var notifier in _effectNotifiers)
                            notifier.NotifyMapEffect(MapEffect.TPDrain);
                    }
                    break;
                case EFFECT_DAMAGE_SPIKE:
                    {
                        // todo: show amount in damage counter
                        var damage = packet.ReadShort();
                        var hp = packet.ReadShort();
                        var maxHp = packet.ReadShort();
                        character = character.WithStats(originalStats.WithNewStat(CharacterStat.HP, hp)
                                                                     .WithNewStat(CharacterStat.MaxHP, maxHp));

                        character = character.WithRenderProperties(character.RenderProperties.WithIsDead(hp <= 0));

                        _characterRepository.MainCharacter = character;

                        foreach (var notifier in _mainCharacterEventNotifiers)
                            notifier.NotifyTakeDamage(damage, (int)Math.Round((double)hp / maxHp * 100), isHeal: false);
                    }
                    break;
                default:
                    return false;
            }

            return true;
        }
    }
}
{'fraction_non_alphanumeric': 0.060892534408452666, 'fraction_numerical': 0.0022243848185736132, 'mean_word_length': 1.6351648351648351, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5443661', 'n_tokens_mistral': 1706, 'n_tokens_neox': 1607, 'n_words': 351}