diff --git a/EOLib.IO/Map/Matrix.cs b/EOLib.IO/Map/Matrix.cs index 16f4196ac..e43f92c49 100644 --- a/EOLib.IO/Map/Matrix.cs +++ b/EOLib.IO/Map/Matrix.cs @@ -11,6 +11,8 @@ public class Matrix : IReadOnlyMatrix private readonly T[,] _arr; + private readonly T _default; + public int Rows { get; } public int Cols { get; } @@ -24,6 +26,7 @@ private Matrix(int rows, int cols) public Matrix(int rows, int cols, T defaultValue) : this(rows, cols) { + _default = defaultValue; Fill(defaultValue); } @@ -56,7 +59,12 @@ public T[] GetRow(int rowIndex) public T this[int row, int col] { - get { return _arr[row, col]; } + get + { + if (row < 0 || row >= Rows || col < 0 || col >= Cols) + return _default; + return _arr[row, col]; + } set { _arr[row, col] = value; } } diff --git a/EndlessClient/Rendering/Character/CharacterAnimationActions.cs b/EndlessClient/Rendering/Character/CharacterAnimationActions.cs index 28f0b17d9..510fe1bfb 100644 --- a/EndlessClient/Rendering/Character/CharacterAnimationActions.cs +++ b/EndlessClient/Rendering/Character/CharacterAnimationActions.cs @@ -57,9 +57,7 @@ public void StartWalking() return; Animator.StartMainCharacterWalkAnimation(); - ShowWaterSplashiesIfNeeded(CharacterActionState.Walking, - _characterRepository.MainCharacter, - _characterRendererProvider.MainCharacterRenderer); + ShowWaterSplashiesIfNeeded(CharacterActionState.Walking, _characterRepository.MainCharacter.ID); } public void StartAttacking() @@ -68,9 +66,7 @@ public void StartAttacking() return; Animator.StartMainCharacterAttackAnimation(); - ShowWaterSplashiesIfNeeded(CharacterActionState.Attacking, - _characterRepository.MainCharacter, - _characterRendererProvider.MainCharacterRenderer); + ShowWaterSplashiesIfNeeded(CharacterActionState.Attacking, _characterRepository.MainCharacter.ID); } public void StartOtherCharacterWalkAnimation(int characterID, byte destinationX, byte destinationY, EODirection direction) @@ -79,11 +75,8 @@ public void StartOtherCharacterWalkAnimation(int characterID, byte destinationX, return; Animator.StartOtherCharacterWalkAnimation(characterID, destinationX, destinationY, direction); - - ShowWaterSplashiesIfNeeded(CharacterActionState.Walking, - _currentMapStateProvider.Characters.Single(x => x.ID == characterID), - _characterRendererProvider.CharacterRenderers[characterID]); - + + ShowWaterSplashiesIfNeeded(CharacterActionState.Walking, characterID); _spikeTrapActions.HideSpikeTrap(characterID); _spikeTrapActions.ShowSpikeTrap(characterID); } @@ -94,9 +87,7 @@ public void StartOtherCharacterAttackAnimation(int characterID) return; Animator.StartOtherCharacterAttackAnimation(characterID); - ShowWaterSplashiesIfNeeded(CharacterActionState.Attacking, - _currentMapStateProvider.Characters.Single(x => x.ID == characterID), - _characterRendererProvider.CharacterRenderers[characterID]); + ShowWaterSplashiesIfNeeded(CharacterActionState.Attacking, characterID); } public void NotifyWarpLeaveEffect(short characterId, WarpAnimation anim) @@ -178,8 +169,21 @@ public void NotifyEarthquake(byte strength) mapRenderer.StartEarthquake(strength); } - private void ShowWaterSplashiesIfNeeded(CharacterActionState action, ICharacter character, ICharacterRenderer characterRenderer) + private void ShowWaterSplashiesIfNeeded(CharacterActionState action, int characterID) { + var character = characterID == _characterRepository.MainCharacter.ID + ? _characterRepository.MainCharacter + : _currentMapStateProvider.Characters.SingleOrDefault(x => x.ID == characterID); + + var characterRenderer = characterID == _characterRepository.MainCharacter.ID + ? _characterRendererProvider.MainCharacterRenderer + : _characterRendererProvider.CharacterRenderers.ContainsKey(characterID) + ? _characterRendererProvider.CharacterRenderers[characterID] + : null; + + if (character == null || characterRenderer == null) + return; + var rp = character.RenderProperties; if (action == CharacterActionState.Attacking) { diff --git a/EndlessClient/Rendering/Character/CharacterAnimator.cs b/EndlessClient/Rendering/Character/CharacterAnimator.cs index 4d10119d0..ce42b131a 100644 --- a/EndlessClient/Rendering/Character/CharacterAnimator.cs +++ b/EndlessClient/Rendering/Character/CharacterAnimator.cs @@ -230,8 +230,8 @@ private void AnimateCharacterWalking() private ICharacterRenderProperties AnimateOneWalkFrame(ICharacterRenderProperties renderProperties) { - var isSteppingStone = (IsInBounds(renderProperties, false) && _currentMapProvider.CurrentMap.Tiles[renderProperties.MapY, renderProperties.MapX] == TileSpec.Jump) - || (IsInBounds(renderProperties, true) && _currentMapProvider.CurrentMap.Tiles[renderProperties.GetDestinationY(), renderProperties.GetDestinationX()] == TileSpec.Jump); + var isSteppingStone = _currentMapProvider.CurrentMap.Tiles[renderProperties.MapY, renderProperties.MapX] == TileSpec.Jump + || _currentMapProvider.CurrentMap.Tiles[renderProperties.GetDestinationY(), renderProperties.GetDestinationX()] == TileSpec.Jump; var nextFrameRenderProperties = renderProperties.WithNextWalkFrame(isSteppingStone); if (nextFrameRenderProperties.CurrentAction != CharacterActionState.Walking) @@ -244,14 +244,6 @@ private ICharacterRenderProperties AnimateOneWalkFrame(ICharacterRenderPropertie return nextFrameRenderProperties; } - private bool IsInBounds(ICharacterRenderProperties renderProperties, bool dest) - { - var mapProps = _currentMapProvider.CurrentMap.Properties; - var x = dest ? renderProperties.GetDestinationX() : renderProperties.MapX; - var y = dest ? renderProperties.GetDestinationY() : renderProperties.MapY; - return x < mapProps.Width && x >= 0 && y < mapProps.Height && y >= 0; - } - #endregion #region Attack Animation diff --git a/EndlessClient/Rendering/Character/CharacterRenderer.cs b/EndlessClient/Rendering/Character/CharacterRenderer.cs index 0a008928e..8d215f3a4 100644 --- a/EndlessClient/Rendering/Character/CharacterRenderer.cs +++ b/EndlessClient/Rendering/Character/CharacterRenderer.cs @@ -362,8 +362,8 @@ private bool GetIsSteppingStone(ICharacterRenderProperties renderProps) if (_gameStateProvider.CurrentState != GameStates.PlayingTheGame) return false; - return (IsInBounds(renderProps, false) && _currentMapProvider.CurrentMap.Tiles[renderProps.MapY, renderProps.MapX] == TileSpec.Jump) - || (IsInBounds(renderProps, true) && renderProps.IsActing(CharacterActionState.Walking) && _currentMapProvider.CurrentMap.Tiles[renderProps.GetDestinationY(), renderProps.GetDestinationX()] == TileSpec.Jump); + return _currentMapProvider.CurrentMap.Tiles[renderProps.MapY, renderProps.MapX] == TileSpec.Jump + || (renderProps.IsActing(CharacterActionState.Walking) && _currentMapProvider.CurrentMap.Tiles[renderProps.GetDestinationY(), renderProps.GetDestinationX()] == TileSpec.Jump); } private int GetSteppingStoneOffset(ICharacterRenderProperties renderProps) @@ -384,14 +384,6 @@ private int GetSteppingStoneOffset(ICharacterRenderProperties renderProps) return 0; } - private bool IsInBounds(ICharacterRenderProperties renderProperties, bool dest) - { - var mapProps = _currentMapProvider.CurrentMap.Properties; - var x = dest ? renderProperties.GetDestinationX() : renderProperties.MapX; - var y = dest ? renderProperties.GetDestinationY() : renderProperties.MapY; - return x < mapProps.Width && x >= 0 && y < mapProps.Height && y >= 0; - } - #endregion #region Effects diff --git a/EndlessClient/Rendering/Character/CharacterRendererUpdater.cs b/EndlessClient/Rendering/Character/CharacterRendererUpdater.cs index 8fff538e4..433735324 100644 --- a/EndlessClient/Rendering/Character/CharacterRendererUpdater.cs +++ b/EndlessClient/Rendering/Character/CharacterRendererUpdater.cs @@ -85,11 +85,13 @@ private void CreateOtherCharacterRenderersAndCacheProperties() } else if (cached.Value != character) { - _characterRendererRepository.CharacterRenderers[id].Character = character; + if (_characterRendererRepository.CharacterRenderers.ContainsKey(id)) + _characterRendererRepository.CharacterRenderers[id].Character = character; _characterStateCache.UpdateCharacterState(id, character); } - if (_characterRendererRepository.NeedsWarpArriveAnimation.Contains(id)) + if (_characterRendererRepository.NeedsWarpArriveAnimation.Contains(id) && + _characterRendererRepository.CharacterRenderers.ContainsKey(id)) { _characterRendererRepository.CharacterRenderers[id].ShowWarpArrive(); _characterRendererRepository.NeedsWarpArriveAnimation.Remove(id); @@ -116,15 +118,19 @@ private void RemoveStaleCharacters() foreach (var id in staleIDs) { - if (_characterRendererRepository.CharacterRenderers[id].EffectIsPlaying()) + _characterStateCache.RemoveCharacterState(id); + + if (_characterRendererRepository.CharacterRenderers.ContainsKey(id)) { - _characterRendererRepository.CharacterRenderers[id].Visible = false; - continue; - } + if (_characterRendererRepository.CharacterRenderers[id].EffectIsPlaying()) + { + _characterRendererRepository.CharacterRenderers[id].Visible = false; + continue; + } - _characterStateCache.RemoveCharacterState(id); - _characterRendererRepository.CharacterRenderers[id].Dispose(); - _characterRendererRepository.CharacterRenderers.Remove(id); + _characterRendererRepository.CharacterRenderers[id].Dispose(); + _characterRendererRepository.CharacterRenderers.Remove(id); + } } } @@ -144,8 +150,12 @@ private void UpdateDeadCharacters() _characterStateCache.RemoveDeathStartTime(character.ID); _characterStateCache.RemoveCharacterState(character.ID); - _characterRendererRepository.CharacterRenderers[character.ID].Dispose(); - _characterRendererRepository.CharacterRenderers.Remove(character.ID); + if (_characterRendererRepository.CharacterRenderers.ContainsKey(character.ID)) + { + _characterRendererRepository.CharacterRenderers[character.ID].Dispose(); + _characterRendererRepository.CharacterRenderers.Remove(character.ID); + } + deadCharacters.Add(character); } } diff --git a/EndlessClient/Rendering/NPC/NPCActions.cs b/EndlessClient/Rendering/NPC/NPCActions.cs index 8a3c6e6d6..1dbd4d5ef 100644 --- a/EndlessClient/Rendering/NPC/NPCActions.cs +++ b/EndlessClient/Rendering/NPC/NPCActions.cs @@ -117,7 +117,7 @@ private void ShoutSpellCast(int playerId) { if (_characterRendererRepository.MainCharacterRenderer.Character.ID == playerId) _characterRendererRepository.MainCharacterRenderer.ShoutSpellCast(); - else + else if (_characterRendererRepository.CharacterRenderers.ContainsKey(playerId)) _characterRendererRepository.CharacterRenderers[playerId].ShoutSpellCast(); }