diff --git a/EOBot/Program.cs b/EOBot/Program.cs index a4e4426a5..d9417cc92 100644 --- a/EOBot/Program.cs +++ b/EOBot/Program.cs @@ -143,7 +143,7 @@ public void JunkItem(int id, int amountRemoved) ConsoleHelper.WriteMessage(ConsoleHelper.Type.JunkItem, $"{weight,3}/{maxWeight,3} - weight - {inventoryCount?.Amount ?? 0} in inventory"); } - public void MakeDrunk() { } + public void NotifyFrozen() { } } [AutoMappedType] diff --git a/EOLib/Domain/Character/AttackValidationActions.cs b/EOLib/Domain/Character/AttackValidationActions.cs index cc3362ecd..ff26d9c2c 100644 --- a/EOLib/Domain/Character/AttackValidationActions.cs +++ b/EOLib/Domain/Character/AttackValidationActions.cs @@ -1,6 +1,7 @@ using System.Linq; using AutomaticTypeMapper; using EOLib.Domain.Extensions; +using EOLib.Domain.Login; using EOLib.Domain.Map; using EOLib.IO.Repositories; @@ -27,9 +28,13 @@ public AttackValidationActions(ICharacterProvider characterProvider, public AttackValidationError ValidateCharacterStateBeforeAttacking() { + if (_characterProvider.MainCharacter.Frozen) + return AttackValidationError.Frozen; + if (_characterProvider.MainCharacter.Stats[CharacterStat.Weight] > _characterProvider.MainCharacter.Stats[CharacterStat.MaxWeight]) return AttackValidationError.Overweight; + if (_characterProvider.MainCharacter.Stats[CharacterStat.SP] <= 0) return AttackValidationError.Exhausted; @@ -73,6 +78,7 @@ public enum AttackValidationError Overweight, Exhausted, NotYourBattle, - MissingArrows + MissingArrows, + Frozen, } } diff --git a/EOLib/Domain/Character/Character.cs b/EOLib/Domain/Character/Character.cs index afea8b702..da4b712c6 100644 --- a/EOLib/Domain/Character/Character.cs +++ b/EOLib/Domain/Character/Character.cs @@ -51,6 +51,8 @@ public sealed partial class Character : ISpellTargetable public bool NoWall { get; } + public bool Frozen { get; } + public static Character FromCharacterSelectionListEntry(CharacterSelectionListEntry selectionListEntry) { return new Builder diff --git a/EOLib/Domain/Character/WalkValidationActions.cs b/EOLib/Domain/Character/WalkValidationActions.cs index 5c167b869..f4eba99e9 100644 --- a/EOLib/Domain/Character/WalkValidationActions.cs +++ b/EOLib/Domain/Character/WalkValidationActions.cs @@ -13,7 +13,8 @@ public enum WalkValidationResult NotWalkable, Walkable, BlockedByCharacter, - GhostComplete + GhostComplete, + Frozen } [AutoMappedType] @@ -36,6 +37,7 @@ public WalkValidationActions(IMapCellStateProvider mapCellStateProvider, _currentMapStateProvider = currentMapStateProvider; _unlockDoorValidator = unlockDoorValidator; _ghostingRepository = ghostingRepository; + } public WalkValidationResult CanMoveToDestinationCoordinates() @@ -65,6 +67,9 @@ public WalkValidationResult IsCellStateWalkable(IMapCellState cellState) { ClearGhostCache(); + if (_characterProvider.MainCharacter.Frozen) + return WalkValidationResult.Frozen; + var mc = _characterProvider.MainCharacter; var cellChar = cellState.Character.FlatMap(c => c.SomeWhen(cc => cc != mc)); diff --git a/EOLib/Domain/Login/LoginActions.cs b/EOLib/Domain/Login/LoginActions.cs index 98f18c94a..88c2079e7 100644 --- a/EOLib/Domain/Login/LoginActions.cs +++ b/EOLib/Domain/Login/LoginActions.cs @@ -104,7 +104,7 @@ public async Task RequestCharacterLogin(Character.Character character) .WithAdminLevel(data.Admin) .WithStats(CharacterStats.FromSelectCharacterData(data)); - _playerInfoRepository.IsFirstTimePlayer = data.LoginMessageCode == LoginMessageCode.Yes; + _playerInfoRepository.IsFirstTimePlayer = data.LoginMessageCode != LoginMessageCode.No; _playerInfoRepository.PlayerHasAdminCharacter = _characterSelectorRepository.Characters.Any(x => x.AdminLevel > 0); _currentMapStateRepository.CurrentMapID = data.MapId; diff --git a/EOLib/Domain/Notifiers/IMainCharacterEventNotifier.cs b/EOLib/Domain/Notifiers/IMainCharacterEventNotifier.cs index b20867128..f63db4bb2 100644 --- a/EOLib/Domain/Notifiers/IMainCharacterEventNotifier.cs +++ b/EOLib/Domain/Notifiers/IMainCharacterEventNotifier.cs @@ -14,6 +14,8 @@ public interface IMainCharacterEventNotifier void DropItem(int id, int amountDropped); void JunkItem(int id, int amountRemoved); + + void NotifyFrozen(); } [AutoMappedType] @@ -28,5 +30,7 @@ public void TakeItemFromMap(int id, int amountTaken) { } public void DropItem(int id, int amountDropped) { } public void JunkItem(int id, int amountTaken) { } + + public void NotifyFrozen() { } } } diff --git a/EOLib/Domain/Spells/SpellCastValidationActions.cs b/EOLib/Domain/Spells/SpellCastValidationActions.cs index fb9a72acc..e6f805fbf 100644 --- a/EOLib/Domain/Spells/SpellCastValidationActions.cs +++ b/EOLib/Domain/Spells/SpellCastValidationActions.cs @@ -1,7 +1,10 @@ using System.Linq; + using AutomaticTypeMapper; + using EOLib.Domain.Character; using EOLib.Domain.Map; +using EOLib.Domain.Party; using EOLib.IO; using EOLib.IO.Repositories; @@ -13,18 +16,24 @@ public class SpellCastValidationActions : ISpellCastValidationActions private readonly IPubFileProvider _pubFileProvider; private readonly ICurrentMapProvider _currentMapProvider; private readonly ICharacterProvider _characterProvider; + private readonly IPartyDataProvider _partyDataProvider; public SpellCastValidationActions(IPubFileProvider pubFileProvider, ICurrentMapProvider currentMapProvider, - ICharacterProvider characterProvider) + ICharacterProvider characterProvider, + IPartyDataProvider partyDataProvider) { _pubFileProvider = pubFileProvider; _currentMapProvider = currentMapProvider; _characterProvider = characterProvider; + _partyDataProvider = partyDataProvider; } public SpellCastValidationResult ValidateSpellCast(int spellId) { + if (_characterProvider.MainCharacter.Frozen) + return SpellCastValidationResult.Frozen; + var spellData = _pubFileProvider.ESFFile[spellId]; var stats = _characterProvider.MainCharacter.Stats; @@ -32,12 +41,17 @@ public SpellCastValidationResult ValidateSpellCast(int spellId) return SpellCastValidationResult.ExhaustedNoSp; if (stats[CharacterStat.TP] - spellData.TP < 0) return SpellCastValidationResult.ExhaustedNoTp; + if (spellData.Target == SpellTarget.Group && !_partyDataProvider.Members.Any()) + return SpellCastValidationResult.NotMemberOfGroup; return SpellCastValidationResult.Ok; } public SpellCastValidationResult ValidateSpellCast(int spellId, ISpellTargetable spellTarget) { + if (_characterProvider.MainCharacter.Frozen) + return SpellCastValidationResult.Frozen; + var res = ValidateSpellCast(spellId); if (res != SpellCastValidationResult.Ok) return res; @@ -75,6 +89,9 @@ public SpellCastValidationResult ValidateSpellCast(int spellId, ISpellTargetable public bool ValidateBard() { + if (_characterProvider.MainCharacter.Frozen) + return false; + var weapon = _characterProvider.MainCharacter.RenderProperties.WeaponGraphic; return Constants.Instruments.Any(x => x == weapon); } diff --git a/EOLib/Domain/Spells/SpellCastValidationResult.cs b/EOLib/Domain/Spells/SpellCastValidationResult.cs index 0be33f540..95f381acd 100644 --- a/EOLib/Domain/Spells/SpellCastValidationResult.cs +++ b/EOLib/Domain/Spells/SpellCastValidationResult.cs @@ -7,5 +7,7 @@ public enum SpellCastValidationResult WrongTargetType, ExhaustedNoSp, ExhaustedNoTp, + NotMemberOfGroup, + Frozen, } } diff --git a/EOLib/PacketHandlers/Walk/WalkClosedHandler.cs b/EOLib/PacketHandlers/Walk/WalkClosedHandler.cs new file mode 100644 index 000000000..e2ec423bd --- /dev/null +++ b/EOLib/PacketHandlers/Walk/WalkClosedHandler.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; + +using AutomaticTypeMapper; + +using EOLib.Domain.Character; +using EOLib.Domain.Login; +using EOLib.Domain.Notifiers; +using EOLib.Net.Handlers; + +using Moffat.EndlessOnline.SDK.Protocol.Net; +using Moffat.EndlessOnline.SDK.Protocol.Net.Server; + +namespace EOLib.PacketHandlers.Walk +{ + [AutoMappedType] + public class WalkCloseHandler : InGameOnlyPacketHandler + { + private readonly ICharacterRepository _characterRepository; + private readonly IEnumerable _mainCharacterEventNotifiers; + + public override PacketFamily Family => PacketFamily.Walk; + + public override PacketAction Action => PacketAction.Close; + + public WalkCloseHandler(IPlayerInfoProvider playerInfoProvider, + ICharacterRepository characterRepository, + IEnumerable mainCharacterEventNotifiers) + : base(playerInfoProvider) + { + _characterRepository = characterRepository; + _mainCharacterEventNotifiers = mainCharacterEventNotifiers; + } + + public override bool HandlePacket(WalkCloseServerPacket packet) + { + _characterRepository.MainCharacter = _characterRepository.MainCharacter.WithFrozen(true); + + foreach (var notifier in _mainCharacterEventNotifiers) + notifier.NotifyFrozen(); + + return true; + } + } +} diff --git a/EOLib/PacketHandlers/Walk/WalkOpenHandler.cs b/EOLib/PacketHandlers/Walk/WalkOpenHandler.cs new file mode 100644 index 000000000..d2243d02b --- /dev/null +++ b/EOLib/PacketHandlers/Walk/WalkOpenHandler.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; + +using AutomaticTypeMapper; + +using EOLib.Domain.Character; +using EOLib.Domain.Login; +using EOLib.Domain.Notifiers; +using EOLib.Net.Handlers; + +using Moffat.EndlessOnline.SDK.Protocol.Net; +using Moffat.EndlessOnline.SDK.Protocol.Net.Server; + +namespace EOLib.PacketHandlers.Walk +{ + [AutoMappedType] + public class WalkOpenHandler : InGameOnlyPacketHandler + { + private readonly ICharacterRepository _characterRepository; + private readonly IEnumerable _mainCharacterEventNotifiers; + + public override PacketFamily Family => PacketFamily.Walk; + + public override PacketAction Action => PacketAction.Open; + + public WalkOpenHandler(IPlayerInfoProvider playerInfoProvider, + ICharacterRepository characterRepository, + IEnumerable mainCharacterEventNotifiers) + : base(playerInfoProvider) + { + _characterRepository = characterRepository; + _mainCharacterEventNotifiers = mainCharacterEventNotifiers; + } + + public override bool HandlePacket(WalkOpenServerPacket packet) + { + _characterRepository.MainCharacter = _characterRepository.MainCharacter.WithFrozen(false); + + foreach (var notifier in _mainCharacterEventNotifiers) + notifier.NotifyFrozen(); + + return true; + } + } +} diff --git a/EndlessClient/Audio/SoundEffectID.cs b/EndlessClient/Audio/SoundEffectID.cs index 21f4863f4..fc9fe665a 100644 --- a/EndlessClient/Audio/SoundEffectID.cs +++ b/EndlessClient/Audio/SoundEffectID.cs @@ -41,7 +41,7 @@ public enum SoundEffectID DoorOrChestLocked, BuySell, Craft, - UnknownBuzzSound = 28, + PlayerFrozen = 28, AdminChatReceived, AdminChatSent = AdminChatReceived, AlternateMeleeAttack, diff --git a/EndlessClient/Controllers/ArrowKeyController.cs b/EndlessClient/Controllers/ArrowKeyController.cs index 123c9fd98..7e4a23b82 100644 --- a/EndlessClient/Controllers/ArrowKeyController.cs +++ b/EndlessClient/Controllers/ArrowKeyController.cs @@ -1,13 +1,16 @@ using AutomaticTypeMapper; + using EndlessClient.Audio; using EndlessClient.HUD; using EndlessClient.Input; using EndlessClient.Rendering.Character; + using EOLib; using EOLib.Domain.Character; using EOLib.Domain.Extensions; using EOLib.Domain.Map; using EOLib.Localization; + using Optional; namespace EndlessClient.Controllers @@ -101,6 +104,9 @@ private bool CurrentDirectionIs(EODirection direction) private void FaceOrAttemptWalk(EODirection direction) { + if (_characterProvider.MainCharacter.Frozen) + return; + if (!CurrentDirectionIs(direction) && _characterProvider.MainCharacter.RenderProperties.IsActing(CharacterActionState.Standing)) { _characterAnimationActions.Face(direction); @@ -133,6 +139,9 @@ private void AttemptToStartWalking() case WalkValidationResult.Walkable: _characterAnimationActions.StartWalking(Option.None()); break; + case WalkValidationResult.Frozen: + // no-op + break; } } } diff --git a/EndlessClient/Controllers/FunctionKeyController.cs b/EndlessClient/Controllers/FunctionKeyController.cs index 8a1f5d7fc..54b877d67 100644 --- a/EndlessClient/Controllers/FunctionKeyController.cs +++ b/EndlessClient/Controllers/FunctionKeyController.cs @@ -68,29 +68,48 @@ public bool SelectSpell(int index, bool isAlternate) { _spellSelectActions.SelectSpellBySlot(index + (isAlternate ? ActiveSpellsPanel.SpellRowLength : 0)); - _spellSlotDataProvider.SelectedSpellInfo.MatchSome(x => - { - var spellData = _esfFileProvider.ESFFile[x.ID]; - if (spellData.Type == SpellType.Bard && _spellCastValidationActions.ValidateBard()) + _spellSlotDataProvider.SelectedSpellInfo.Match( + some: x => { - _inGameDialogActions.ShowBardDialog(); - } - else if (spellData.Target == SpellTarget.Self || spellData.Target == SpellTarget.Group) - { - var castResult = _spellCastValidationActions.ValidateSpellCast(x.ID); + var spellData = _esfFileProvider.ESFFile[x.ID]; + if (spellData.Type == SpellType.Bard && _spellCastValidationActions.ValidateBard()) + { + _inGameDialogActions.ShowBardDialog(); + } + else + { + var castResult = _spellCastValidationActions.ValidateSpellCast(x.ID); - if (castResult == SpellCastValidationResult.ExhaustedNoTp) - _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.ATTACK_YOU_ARE_EXHAUSTED_TP); - else if (castResult == SpellCastValidationResult.ExhaustedNoSp) - _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.ATTACK_YOU_ARE_EXHAUSTED_SP); - else if (_characterAnimationActions.PrepareMainCharacterSpell(x.ID, _characterProvider.MainCharacter)) - _characterActions.PrepareCastSpell(x.ID); - } - else - { - _sfxPlayer.PlaySfx(SoundEffectID.SpellActivate); - } - }); + switch (castResult) + { + case SpellCastValidationResult.ExhaustedNoTp: + _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.ATTACK_YOU_ARE_EXHAUSTED_TP); + break; + case SpellCastValidationResult.ExhaustedNoSp: + _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.ATTACK_YOU_ARE_EXHAUSTED_SP); + break; + case SpellCastValidationResult.NotMemberOfGroup: + _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.SPELL_ONLY_WORKS_ON_GROUP); + break; + case SpellCastValidationResult.Frozen: + // no-op + break; + default: + _statusLabelSetter.SetStatusLabel(EOResourceID.SKILLMASTER_WORD_SPELL, $"{spellData.Name} ", EOResourceID.SPELL_WAS_SELECTED); + if (spellData.Target == SpellTarget.Normal) + { + _sfxPlayer.PlaySfx(SoundEffectID.SpellActivate); + } + else if (_characterAnimationActions.PrepareMainCharacterSpell(x.ID, _characterProvider.MainCharacter)) + { + _characterActions.PrepareCastSpell(x.ID); + } + break; + } + } + }, + none: () => _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.SPELL_NOTHING_WAS_SELECTED) + ); return true; } diff --git a/EndlessClient/Controllers/InventoryController.cs b/EndlessClient/Controllers/InventoryController.cs index 66b57abdb..b02aff060 100644 --- a/EndlessClient/Controllers/InventoryController.cs +++ b/EndlessClient/Controllers/InventoryController.cs @@ -16,6 +16,7 @@ using EOLib.Domain.Interact; using EOLib.Domain.Interact.Bank; using EOLib.Domain.Item; +using EOLib.Domain.Login; using EOLib.Domain.Map; using EOLib.Domain.Trade; using EOLib.IO; @@ -118,6 +119,9 @@ public void UseItem(EIFRecord record) { //usable items case ItemType.Teleport: + if (_characterProvider.MainCharacter.Frozen) + break; + if (!_currentMapProvider.CurrentMap.Properties.CanScroll) { _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_ACTION, EOResourceID.STATUS_LABEL_NOTHING_HAPPENED); diff --git a/EndlessClient/Controllers/MapInteractionController.cs b/EndlessClient/Controllers/MapInteractionController.cs index 4dce3563a..0ff4c1d86 100644 --- a/EndlessClient/Controllers/MapInteractionController.cs +++ b/EndlessClient/Controllers/MapInteractionController.cs @@ -20,6 +20,7 @@ using EOLib.Domain.Extensions; using EOLib.Domain.Interact; using EOLib.Domain.Item; +using EOLib.Domain.Login; using EOLib.Domain.Map; using EOLib.Domain.Spells; using EOLib.IO.Extensions; @@ -127,6 +128,9 @@ public void LeftClick(IMapCellState cellState) // vanilla client prioritizes standing first, then board interaction else if (_characterProvider.MainCharacter.RenderProperties.SitState != SitState.Standing) { + if (_characterProvider.MainCharacter.Frozen) + return; + var mapRenderer = _hudControlProvider.GetComponent(HudControlIdentifier.MapRenderer); _characterActions.Sit(mapRenderer.GridCoordinates); } @@ -143,6 +147,9 @@ public void LeftClick(IMapCellState cellState) } else if (cellState.TileSpec.IsChair()) { + if (_characterProvider.MainCharacter.Frozen) + return; + _characterActions.Sit(cellState.Coordinate, isChair: true); } else diff --git a/EndlessClient/HUD/Controls/HudControlsFactory.cs b/EndlessClient/HUD/Controls/HudControlsFactory.cs index c249d437e..3d171b9ea 100644 --- a/EndlessClient/HUD/Controls/HudControlsFactory.cs +++ b/EndlessClient/HUD/Controls/HudControlsFactory.cs @@ -48,6 +48,7 @@ public class HudControlsFactory : IHudControlsFactory private readonly IClientWindowSizeRepository _clientWindowSizeRepository; private readonly IEndlessGameProvider _endlessGameProvider; private readonly ICharacterRepository _characterRepository; + private readonly IPlayerInfoProvider _playerInfoProvider; private readonly ICurrentMapStateRepository _currentMapStateRepository; private readonly IUserInputRepository _userInputRepository; private readonly IStatusLabelSetter _statusLabelSetter; @@ -85,6 +86,7 @@ public HudControlsFactory(IHudButtonController hudButtonController, IClientWindowSizeRepository clientWindowSizeRepository, IEndlessGameProvider endlessGameProvider, ICharacterRepository characterRepository, + IPlayerInfoProvider playerInfoProvider, ICurrentMapStateRepository currentMapStateRepository, IUserInputRepository userInputRepository, IStatusLabelSetter statusLabelSetter, @@ -120,6 +122,7 @@ public HudControlsFactory(IHudButtonController hudButtonController, _clientWindowSizeRepository = clientWindowSizeRepository; _endlessGameProvider = endlessGameProvider; _characterRepository = characterRepository; + _playerInfoProvider = playerInfoProvider; _currentMapStateRepository = currentMapStateRepository; _userInputRepository = userInputRepository; _statusLabelSetter = statusLabelSetter; @@ -578,7 +581,7 @@ private IUserInputHandler CreateUserInputHandler() private ICharacterAnimator CreateCharacterAnimator() { return new CharacterAnimator( - _endlessGameProvider, _characterRepository, _currentMapStateRepository, + _endlessGameProvider, _characterRepository, _playerInfoProvider, _currentMapStateRepository, _currentMapProvider, _spellSlotDataRepository, _characterActions, _walkValidationActions, _pathFinder, _fixedTimeStepRepository, _weaponMetadataProvider); diff --git a/EndlessClient/HUD/Spells/SpellSelectActions.cs b/EndlessClient/HUD/Spells/SpellSelectActions.cs index 4990e1f8e..57d8f48fc 100644 --- a/EndlessClient/HUD/Spells/SpellSelectActions.cs +++ b/EndlessClient/HUD/Spells/SpellSelectActions.cs @@ -1,8 +1,5 @@ -using System.Linq; -using AutomaticTypeMapper; -using EOLib.Domain.Party; -using EOLib.IO.Repositories; -using EOLib.Localization; +using AutomaticTypeMapper; + using Optional; namespace EndlessClient.HUD.Spells @@ -10,47 +7,27 @@ namespace EndlessClient.HUD.Spells [AutoMappedType] public class SpellSelectActions : ISpellSelectActions { - private readonly IStatusLabelSetter _statusLabelSetter; private readonly ISpellSlotDataRepository _spellSlotDataRepository; - private readonly IPartyDataProvider _partyDataProvider; - private readonly IESFFileProvider _esfFileProvider; - public SpellSelectActions(IStatusLabelSetter statusLabelSetter, - ISpellSlotDataRepository spellSlotDataRepository, - IPartyDataProvider partyDataProvider, - IESFFileProvider esfFileProvider) + public SpellSelectActions(ISpellSlotDataRepository spellSlotDataRepository) { - _statusLabelSetter = statusLabelSetter; _spellSlotDataRepository = spellSlotDataRepository; - _partyDataProvider = partyDataProvider; - _esfFileProvider = esfFileProvider; } public void SelectSpellBySlot(int slot) { _spellSlotDataRepository.SpellSlots[slot].Match( - some: si => + some: x => { - var spellData = _esfFileProvider.ESFFile[si.ID]; - - if (spellData.Target == EOLib.IO.SpellTarget.Group && !_partyDataProvider.Members.Any()) - { - _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.SPELL_ONLY_WORKS_ON_GROUP); - } - else - { - _statusLabelSetter.SetStatusLabel(EOResourceID.SKILLMASTER_WORD_SPELL, $"{spellData.Name} ", EOResourceID.SPELL_WAS_SELECTED); - _spellSlotDataRepository.SelectedSpellSlot = Option.Some(slot); - _spellSlotDataRepository.SpellIsPrepared = true; - } + _spellSlotDataRepository.SelectedSpellSlot = Option.Some(slot); + _spellSlotDataRepository.SpellIsPrepared = true; }, none: () => { - _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_WARNING, EOResourceID.SPELL_NOTHING_WAS_SELECTED); - _spellSlotDataRepository.SelectedSpellSlot = Option.None(); _spellSlotDataRepository.SpellIsPrepared = false; - }); + } + ); } } diff --git a/EndlessClient/Input/UserInputHandlerFactory.cs b/EndlessClient/Input/UserInputHandlerFactory.cs index 3cbc3b809..7c2f896ce 100644 --- a/EndlessClient/Input/UserInputHandlerFactory.cs +++ b/EndlessClient/Input/UserInputHandlerFactory.cs @@ -1,9 +1,11 @@ using AutomaticTypeMapper; + using EndlessClient.Controllers; using EndlessClient.Dialogs; using EndlessClient.GameExecution; using EndlessClient.HUD; using EndlessClient.Rendering; + using EOLib.Domain.Map; namespace EndlessClient.Input diff --git a/EndlessClient/Rendering/Character/CharacterAnimator.cs b/EndlessClient/Rendering/Character/CharacterAnimator.cs index e5ff3f03d..1a1e85c11 100644 --- a/EndlessClient/Rendering/Character/CharacterAnimator.cs +++ b/EndlessClient/Rendering/Character/CharacterAnimator.cs @@ -10,6 +10,7 @@ using EOLib; using EOLib.Domain.Character; using EOLib.Domain.Extensions; +using EOLib.Domain.Login; using EOLib.Domain.Map; using EOLib.Domain.Spells; using EOLib.IO.Map; @@ -26,6 +27,7 @@ public class CharacterAnimator : GameComponent, ICharacterAnimator public const int TICKS_PER_CAST_TIME = 48; private readonly ICharacterRepository _characterRepository; + private readonly IPlayerInfoProvider _playerInfoProvider; private readonly ICurrentMapStateRepository _currentMapStateRepository; private readonly ICurrentMapProvider _currentMapProvider; private readonly ISpellSlotDataRepository _spellSlotDataRepository; @@ -52,6 +54,7 @@ public class CharacterAnimator : GameComponent, ICharacterAnimator public CharacterAnimator(IEndlessGameProvider gameProvider, ICharacterRepository characterRepository, + IPlayerInfoProvider playerInfoProvider, ICurrentMapStateRepository currentMapStateRepository, ICurrentMapProvider currentMapProvider, ISpellSlotDataRepository spellSlotDataRepository, @@ -63,6 +66,7 @@ public CharacterAnimator(IEndlessGameProvider gameProvider, : base((Game)gameProvider.Game) { _characterRepository = characterRepository; + _playerInfoProvider = playerInfoProvider; _currentMapStateRepository = currentMapStateRepository; _currentMapProvider = currentMapProvider; _spellSlotDataRepository = spellSlotDataRepository; diff --git a/EndlessClient/Subscribers/MainCharacterEventSubscriber.cs b/EndlessClient/Subscribers/MainCharacterEventSubscriber.cs index fcdddd1e9..529ab1184 100644 --- a/EndlessClient/Subscribers/MainCharacterEventSubscriber.cs +++ b/EndlessClient/Subscribers/MainCharacterEventSubscriber.cs @@ -1,6 +1,9 @@ using AutomaticTypeMapper; + +using EndlessClient.Audio; using EndlessClient.HUD; using EndlessClient.Rendering.Character; + using EOLib.Domain.Chat; using EOLib.Domain.Notifiers; using EOLib.IO.Repositories; @@ -16,18 +19,21 @@ public class MainCharacterEventSubscriber : IMainCharacterEventNotifier private readonly ILocalizedStringFinder _localizedStringFinder; private readonly IPubFileProvider _pubFileProvider; private readonly ICharacterRendererProvider _characterRendererProvider; + private readonly ISfxPlayer _sfxPlayer; public MainCharacterEventSubscriber(IStatusLabelSetter statusLabelSetter, IChatRepository chatRepository, ILocalizedStringFinder localizedStringFinder, IPubFileProvider pubFileProvider, - ICharacterRendererProvider characterRendererProvider) + ICharacterRendererProvider characterRendererProvider, + ISfxPlayer sfxPlayer) { _statusLabelSetter = statusLabelSetter; _chatRepository = chatRepository; _localizedStringFinder = localizedStringFinder; _pubFileProvider = pubFileProvider; _characterRendererProvider = characterRendererProvider; + _sfxPlayer = sfxPlayer; } public void NotifyGainedExp(int expDifference) @@ -82,5 +88,10 @@ public void JunkItem(int id, int amountRemoved) _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_INFORMATION, EOResourceID.STATUS_LABEL_ITEM_JUNK_YOU_JUNKED, $" {amountRemoved} {rec.Name}"); } + + public void NotifyFrozen() + { + _sfxPlayer.PlaySfx(SoundEffectID.PlayerFrozen); + } } }