From 80ce56fa357f0bcf36ba4c1c9beaa13d2a0c9917 Mon Sep 17 00:00:00 2001 From: Arufonsu <17498701+Arufonsu@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:17:45 -0400 Subject: [PATCH] weylon's review (I) --- .../Entities/Projectiles/Projectile.cs | 331 +++++++++--------- Intersect.Server.Core/Entities/Projectile.cs | 90 ++--- 2 files changed, 205 insertions(+), 216 deletions(-) diff --git a/Intersect.Client/Entities/Projectiles/Projectile.cs b/Intersect.Client/Entities/Projectiles/Projectile.cs index 35d0a1ef9e..6eaa7f2519 100644 --- a/Intersect.Client/Entities/Projectiles/Projectile.cs +++ b/Intersect.Client/Entities/Projectiles/Projectile.cs @@ -76,7 +76,7 @@ public override void Load(EntityPacket packet) { for (var x = 0; x < ProjectileBase.SPAWN_LOCATIONS_WIDTH; x++) { - for (var y = 0; y < ProjectileBase.SPAWN_LOCATIONS_WIDTH; y++) + for (var y = 0; y < ProjectileBase.SPAWN_LOCATIONS_HEIGHT; y++) { for (var d = 0; d < ProjectileBase.MAX_PROJECTILE_DIRECTIONS; d++) { @@ -100,13 +100,11 @@ public override void Load(EntityPacket packet) /// public override void Dispose() { - // Check if Dispose has already been called to avoid redundant calculations. if (!_isDisposing) { - // Use a lock to ensure thread safety when disposing resources. lock (_lock) { - _isDisposing = true; // Mark as disposing to prevent concurrent disposal calls. + _isDisposing = true; // Perform a final update if no projectiles have been spawned. if (_spawnedAmount == 0) @@ -114,17 +112,14 @@ public override void Dispose() Update(); } - // Dispose of each spawned projectile's animation resources. if (_spawns != null) { foreach (var s in _spawns) { - s?.Anim?.DisposeNextDraw(); // Safely call DisposeNextDraw, if the animation exists. + s?.Anim?.DisposeNextDraw(); } } - // Suppress finalization to optimize garbage collection. - // This is important for performance and to prevent the finalizer from running. GC.SuppressFinalize(this); } } @@ -172,27 +167,23 @@ private void AddProjectileSpawns() var spawn = FindSpawnAnimationData(); var animBase = AnimationBase.Get(_myBase.Animations[spawn].AnimationId); - // Iterate over all possible spawn locations within the defined width and height for (var x = 0; x < ProjectileBase.SPAWN_LOCATIONS_WIDTH; x++) { - for (var y = 0; y < ProjectileBase.SPAWN_LOCATIONS_WIDTH; y++) + for (var y = 0; y < ProjectileBase.SPAWN_LOCATIONS_HEIGHT; y++) { - // Iterate over all possible directions a projectile can be spawned in for (var d = 0; d < ProjectileBase.MAX_PROJECTILE_DIRECTIONS; d++) { - // Check if the current direction is enabled for spawning at this location - // and if the maximum number of spawned projectiles has not been reached + // Check if the current direction is enabled for spawning at this location. if (_myBase.SpawnLocations[x, y].Directions[d] == true) { // Calculate the spawn position and direction for the new projectile var s = new ProjectileSpawns( - FindProjectileRotationDir(Dir, (Direction)d), // Calculate the rotation direction + FindProjectileRotationDir(Dir, (Direction)d), (byte)(X + FindProjectileRotation(Dir, x - 2, y - 2, true)), (byte)(Y + FindProjectileRotation(Dir, x - 2, y - 2, false)), Z, MapId, animBase, _myBase.Animations[spawn].AutoRotate, _myBase, this ); - // Check for collision at the spawn location, mark as dead if collision is detected _spawns[_spawnedAmount] = s; if (Collided(_spawnedAmount)) { @@ -219,7 +210,7 @@ private void AddProjectileSpawns() /// The direction of the projectile. /// The x-coordinate value. /// The y-coordinate value. - /// Determines if the calculation is for the X axis (true) or Y axis (false). + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. /// The rotation value for the specified axis based on the direction. private static int FindProjectileRotation(Direction direction, int x, int y, bool isXAxis) { @@ -255,7 +246,7 @@ private static Direction FindProjectileRotationDir(Direction entityDir, Directio /// /// The direction of the projectile. /// The range of the projectile. - /// A boolean value indicating whether the axis is the X-axis. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. /// The calculated range value. private static float GetRange(Direction direction, float range, bool isXAxis) { @@ -318,7 +309,9 @@ public override bool Update() { for (var s = 0; s < _spawnedAmount; s++) { - if (_spawns[s] != null && Maps.MapInstance.Get(_spawns[s].SpawnMapId) != null) + var spawn = _spawns[s]; + + if (spawn != null && Maps.MapInstance.Get(spawn.SpawnMapId) != null) { if (_targetId != Guid.Empty && _targetId != _owner && Globals.Entities.ContainsKey(_targetId) && (_myBase.HomingBehavior || _myBase.DirectShotBehavior)) { @@ -327,9 +320,9 @@ public override bool Update() _lastTargetY = target.Y; _lastTargetMapId = target.MapId; - _spawns[s].OffsetX = GetProjectileLerping(_spawns[s], true); - _spawns[s].OffsetY = GetProjectileLerping(_spawns[s], false); - SetProjectileRotation(_spawns[s]); + spawn.OffsetX = GetProjectileLerping(spawn, true); + spawn.OffsetY = GetProjectileLerping(spawn, false); + SetProjectileRotation(spawn); if (_myBase.DirectShotBehavior) { @@ -338,32 +331,24 @@ public override bool Update() } else if (_lastTargetX != -1 && _lastTargetY != -1) { - _spawns[s].OffsetX = GetProjectileLerping(_spawns[s], true); - _spawns[s].OffsetY = GetProjectileLerping(_spawns[s], false); - SetProjectileRotation(_spawns[s]); + spawn.OffsetX = GetProjectileLerping(spawn, true); + spawn.OffsetY = GetProjectileLerping(spawn, false); + SetProjectileRotation(spawn); } else { - _spawns[s].OffsetX = GetRange(_spawns[s].Dir, GetDisplacement(_spawns[s].SpawnTime), true); - _spawns[s].OffsetY = GetRange(_spawns[s].Dir, GetDisplacement(_spawns[s].SpawnTime), false); - _spawns[s].Anim.SetRotation(false); + spawn.OffsetX = GetRange(spawn.Dir, GetDisplacement(spawn.SpawnTime), true); + spawn.OffsetY = GetRange(spawn.Dir, GetDisplacement(spawn.SpawnTime), false); + spawn.Anim.SetRotation(false); } - _spawns[s] - .Anim.SetPosition( - Maps.MapInstance.Get(_spawns[s].SpawnMapId).GetX() + - _spawns[s].SpawnX * Options.TileWidth + - _spawns[s].OffsetX + - Options.TileWidth / 2, - Maps.MapInstance.Get(_spawns[s].SpawnMapId).GetY() + - _spawns[s].SpawnY * Options.TileHeight + - _spawns[s].OffsetY + - Options.TileHeight / 2, X, Y, MapId, - _spawns[s].AutoRotate ? _spawns[s].Dir : Direction.Up, - _spawns[s].Z - ); - - _spawns[s].Anim.Update(); + var spawnMapId = Maps.MapInstance.Get(spawn.SpawnMapId); + var spawnX = spawnMapId.GetX() + spawn.SpawnX * Options.TileWidth + spawn.OffsetX + Options.TileWidth / 2; + var spawnY = spawnMapId.GetY() + spawn.SpawnY * Options.TileHeight + spawn.OffsetY + Options.TileHeight / 2; + var spawnDirection = spawn.AutoRotate ? spawn.Dir : Direction.Up; + + spawn.Anim.SetPosition(spawnX, spawnY, X, Y, MapId, spawnDirection, spawn.Z); + spawn.Anim.Update(); } } } @@ -377,56 +362,58 @@ public override bool Update() /// /// Calculates the offset for the projectile spawn position based on the target map and spawn location. /// - /// A boolean value indicating whether the calculation should be done horizontally (X-axis) or vertically (Y-axis). /// The projectile spawn information. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. /// The calculated offset value. - private float GetProjectileOffset(bool isXAxis, ProjectileSpawns spawn) + private float GetProjectileOffset(ProjectileSpawns spawn, bool isXAxis) { - if (_lastTargetMapId != Guid.Empty && _lastTargetMapId != spawn.SpawnMapId && Maps.MapInstance.TryGet(spawn.SpawnMapId, out var map)) + if (_lastTargetMapId == Guid.Empty || _lastTargetMapId == spawn.SpawnMapId || !Maps.MapInstance.TryGet(spawn.SpawnMapId, out var map)) { - for (var y = map.GridY - 1; y <= map.GridY + 1; y++) + return isXAxis ? _lastTargetX - spawn.SpawnX : _lastTargetY - spawn.SpawnY; + } + + for (var y = map.GridY - 1; y <= map.GridY + 1; y++) + { + for (var x = map.GridX - 1; x <= map.GridX + 1; x++) { - for (var x = map.GridX - 1; x <= map.GridX + 1; x++) + if (x < 0 || x >= Globals.MapGrid.GetLength(0) || y < 0 || y >= Globals.MapGrid.GetLength(1)) + { + continue; + } + + if (Globals.MapGrid[x, y] != _lastTargetMapId || Globals.MapGrid[x, y] == Guid.Empty) + { + continue; + } + + if (isXAxis) // Horizontal (X) calculation { - if (x < 0 || x >= Globals.MapGrid.GetLength(0) || y < 0 || y >= Globals.MapGrid.GetLength(1)) + var leftSide = x == map.GridX - 1; + var rightSide = x == map.GridX + 1; + + if (leftSide) { - continue; + return _lastTargetX - Options.MapWidth - spawn.SpawnX; } - if (Globals.MapGrid[x, y] != _lastTargetMapId || Globals.MapGrid[x, y] == Guid.Empty) + if (rightSide) { - continue; + return _lastTargetX + Options.MapWidth - spawn.SpawnX; } + } + else // Vertical (Y) calculation + { + var topSide = y == map.GridY + 1; + var bottomSide = y == map.GridY - 1; - if (isXAxis) // Horizontal (X) calculation + if (topSide) { - var leftSide = x == map.GridX - 1; - var rightSide = x == map.GridX + 1; - - if (leftSide) - { - return _lastTargetX - Options.MapWidth - spawn.SpawnX; - } - - if (rightSide) - { - return _lastTargetX + Options.MapWidth - spawn.SpawnX; - } + return _lastTargetY + Options.MapHeight - spawn.SpawnY; } - else // Vertical (Y) calculation - { - var topSide = y == map.GridY + 1; - var bottomSide = y == map.GridY - 1; - if (topSide) - { - return _lastTargetY + Options.MapHeight - spawn.SpawnY; - } - - if (bottomSide) - { - return _lastTargetY - Options.MapHeight - spawn.SpawnY; - } + if (bottomSide) + { + return _lastTargetY - Options.MapHeight - spawn.SpawnY; } } } @@ -439,7 +426,7 @@ private float GetProjectileOffset(bool isXAxis, ProjectileSpawns spawn) /// Calculates the interpolated (lerped) position value for a projectile along the X or Y axis. /// /// The spawn information of the projectile, including its initial position and spawn time. - /// True to calculate the position along the X axis, false for the Y axis. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. /// The interpolated position value for the projectile on the specified axis, taking into account the projectile's travel direction, speed, and elapsed time since spawning. /// /// This method determines the projectile's current position by interpolating between its initial offset and its desired position at the current time. @@ -449,7 +436,7 @@ private float GetProjectileOffset(bool isXAxis, ProjectileSpawns spawn) /// private float GetProjectileLerping(ProjectileSpawns spawn, bool isXAxis) { - var (directionX, directionY) = (GetProjectileOffset(true, spawn), GetProjectileOffset(false, spawn)); + var (directionX, directionY) = (GetProjectileOffset(spawn, true), GetProjectileOffset(spawn, false)); var distance = MathF.Sqrt(directionX * directionX + directionY * directionY); if (distance == 0) return 0; @@ -475,8 +462,7 @@ private float GetProjectileLerping(ProjectileSpawns spawn, bool isXAxis) /// private void SetProjectileRotation(ProjectileSpawns spawn) { - var directionX = GetProjectileOffset(true, spawn); - var directionY = GetProjectileOffset(false, spawn); + var (directionX, directionY) = (GetProjectileOffset(spawn, true), GetProjectileOffset(spawn, false)); var angle = (float)(Math.Atan2(directionY, directionX) * (180.0 / Math.PI) + 90); spawn.Anim.SetRotation(angle); } @@ -486,96 +472,99 @@ private void SetProjectileRotation(ProjectileSpawns spawn) /// public void CheckForCollision() { - if (_spawnCount != 0 || _quantity <= _myBase.Quantity) + if (_spawnCount == 0 && _quantity > _myBase.Quantity) { - for (var i = 0; i < _spawnedAmount && i < _spawns.Length; i++) // Ensure i is within _spawns bounds + Globals.Entities[Id].Dispose(); + return; + } + + for (var i = 0; i < _spawnedAmount && i < _spawns.Length; i++) + { + var projectileSpawn = _spawns[i]; + if (projectileSpawn == null || Timing.Global.Milliseconds <= projectileSpawn.TransmissionTimer) + { + continue; + } + + if (!Maps.MapInstance.TryGet(projectileSpawn.MapId, out var spawnMap)) + { + continue; + } + + float newx = projectileSpawn.X; + float newy = projectileSpawn.Y; + + if (_myBase.HomingBehavior || _myBase.DirectShotBehavior) { - if (_spawns[i] != null && Timing.Global.Milliseconds > _spawns[i].TransmissionTimer) + if (_targetId != Guid.Empty && _targetId != _owner || _lastTargetX != -1 && _lastTargetY != -1 && _lastTargetMapId != Guid.Empty) { - if (Maps.MapInstance.TryGet(_spawns[i].MapId, out var spawnMap)) - { - float newx = _spawns[i].X; - float newy = _spawns[i].Y; - - if (_myBase.HomingBehavior || _myBase.DirectShotBehavior) - { - if (_targetId != Guid.Empty && _targetId != _owner || _lastTargetX != -1 && _lastTargetY != -1 && _lastTargetMapId != Guid.Empty) - { - float deltaX = GetProjectileOffset(true, _spawns[i]); - float deltaY = GetProjectileOffset(false, _spawns[i]); - float distance = MathF.Sqrt(deltaX * deltaX + deltaY * deltaY); - float xFactor = deltaX / distance; - float yFactor = deltaY / distance; - newx += xFactor; - newy += yFactor; - } - } - else - { - newx += GetRange(_spawns[i].Dir, 1, true); - newy += GetRange(_spawns[i].Dir, 1, false); - } + var (deltaX, deltaY) = (GetProjectileOffset(projectileSpawn, true), GetProjectileOffset(projectileSpawn, false)); + float distance = MathF.Sqrt(deltaX * deltaX + deltaY * deltaY); + float xFactor = deltaX / distance; + float yFactor = deltaY / distance; + newx += xFactor; + newy += yFactor; + } + } + else + { + newx += GetRange(projectileSpawn.Dir, 1, true); + newy += GetRange(projectileSpawn.Dir, 1, false); + } - AdjustPositionOnMapBoundaries(ref newx, ref newy, ref spawnMap); + AdjustPositionOnMapBoundaries(ref newx, ref newy, ref spawnMap); - _spawns[i].X = (int)newx; - _spawns[i].Y = (int)newy; - _spawns[i].MapId = spawnMap.Id; - _spawns[i].Distance++; - _spawns[i].TransmissionTimer = Timing.Global.MillisecondsOffset + (long)(_myBase.Speed / (float)_myBase.Range); + projectileSpawn.X = (int)newx; + projectileSpawn.Y = (int)newy; + projectileSpawn.MapId = spawnMap.Id; + projectileSpawn.Distance++; + projectileSpawn.TransmissionTimer = Timing.Global.MillisecondsOffset + (long)(_myBase.Speed / (float)_myBase.Range); - var killSpawn = Collided(i) || _spawns[i].Distance >= _myBase.Range || - newx < 0 || newx >= Options.MapWidth || newy < 0 || - newy >= Options.MapHeight; + var killSpawn = Collided(i) || projectileSpawn.Distance >= _myBase.Range || + newx < 0 || newx >= Options.MapWidth || newy < 0 || + newy >= Options.MapHeight; - // Check for map boundaries and remove the spawn if it goes out of bounds. - if (killSpawn) - { - TryRemoveSpawn(i); - _spawnCount--; + // Check for map boundaries and remove the spawn if it goes out of bounds. + if (killSpawn) + { + TryRemoveSpawn(i); + _spawnCount--; - continue; - } + continue; + } - // Check for Z-Dimension - if (!killSpawn && spawnMap.Attributes != null && - _spawns[i].X >= 0 && _spawns[i].Y >= 0 && _spawns[i].X < spawnMap.Attributes.GetLength(0) && - _spawns[i].Y < spawnMap.Attributes.GetLength(1)) - { - var attribute = spawnMap.Attributes[_spawns[i].X, _spawns[i].Y]; + // Check for Z-Dimension + if (!killSpawn && spawnMap.Attributes != null && + projectileSpawn.X >= 0 && projectileSpawn.Y >= 0 && projectileSpawn.X < spawnMap.Attributes.GetLength(0) && + projectileSpawn.Y < spawnMap.Attributes.GetLength(1)) + { + var attribute = spawnMap.Attributes[projectileSpawn.X, projectileSpawn.Y]; - if (attribute != null && attribute.Type == MapAttribute.ZDimension) - { - var zDimensionAttribute = (MapZDimensionAttribute)attribute; - - // If the Z dimension attribute specifies a blocked level that matches the projectile's current Z level, - // mark the projectile for destruction. - if (zDimensionAttribute.BlockedLevel > 0 && _spawns[i].Z == zDimensionAttribute.BlockedLevel - 1) - { - killSpawn = true; - } - - // If the Z dimension attribute specifies a gateway to another level, - // adjust the projectile's Z level to the specified gateway level. - if (zDimensionAttribute.GatewayTo > 0) - { - _spawns[i].Z = zDimensionAttribute.GatewayTo - 1; - } - } - } + if (attribute != null && attribute.Type == MapAttribute.ZDimension) + { + var zDimensionAttribute = (MapZDimensionAttribute)attribute; - if (killSpawn) - { - TryRemoveSpawn(i); - _spawnCount--; - } + // If the Z dimension attribute specifies a blocked level that matches the projectile's current Z level, + // mark the projectile for destruction. + if (zDimensionAttribute.BlockedLevel > 0 && projectileSpawn.Z == zDimensionAttribute.BlockedLevel - 1) + { + killSpawn = true; + } + + // If the Z dimension attribute specifies a gateway to another level, + // adjust the projectile's Z level to the specified gateway level. + if (zDimensionAttribute.GatewayTo > 0) + { + projectileSpawn.Z = zDimensionAttribute.GatewayTo - 1; } } } - } - else - { - Globals.Entities[Id].Dispose(); + + if (killSpawn) + { + TryRemoveSpawn(i); + _spawnCount--; + } } } @@ -593,8 +582,8 @@ public void CheckForCollision() /// private static void AdjustPositionOnMapBoundaries(ref float newx, ref float newy, ref Maps.MapInstance spawnMap) { - int MapWidth = Options.MapWidth; // The width of the map. - int MapHeight = Options.MapHeight; // The height of the map. + int MapWidth = Options.MapWidth; + int MapHeight = Options.MapHeight; // Determine if the projectile crosses any of the map boundaries. bool crossesLeftBoundary = MathF.Floor(newx) < 0; @@ -693,20 +682,20 @@ private static void AdjustPositionOnMapBoundaries(ref float newx, ref float newy /// True if the projectile spawn has collided and should be destroyed; otherwise, false. private bool Collided(int i) { - var killSpawn = false; // Flag to determine if the spawn should be killed due to collision - IEntity? blockedBy = default; // Entity, resource, or map block that the projectile has potentially collided with - var spawn = _spawns[i]; // Current projectile spawn being checked for collision + var killSpawn = false; + IEntity? blockedBy = default; + var spawn = _spawns[i]; - // Check if the tile at the projectile's location is blocked + // Check if the tile at the projectile's location is blocked. var tileBlocked = Globals.Me.IsTileBlocked( - new Point(spawn.X, spawn.Y), // Projectile spawn location - Z, // Z-level of the projectile - spawn.MapId, // ID of the map where the projectile is located - ref blockedBy, // Reference to the entity blocking the projectile, if any - spawn.ProjectileBase.IgnoreActiveResources, // Whether active resources should be ignored - spawn.ProjectileBase.IgnoreExhaustedResources, // Whether exhausted resources should be ignored - true, // Always check for entities - true // Always check for map blocks + delta: new Point(spawn.X, spawn.Y), + z: Z, + mapId: spawn.MapId, + blockedBy: ref blockedBy, + ignoreAliveResources: spawn.ProjectileBase.IgnoreActiveResources, + ignoreDeadResources: spawn.ProjectileBase.IgnoreExhaustedResources, + ignoreNpcAvoids: true, + projectileTrigger: false ); switch (tileBlocked) diff --git a/Intersect.Server.Core/Entities/Projectile.cs b/Intersect.Server.Core/Entities/Projectile.cs index 0be68ae351..70f0b79422 100644 --- a/Intersect.Server.Core/Entities/Projectile.cs +++ b/Intersect.Server.Core/Entities/Projectile.cs @@ -112,7 +112,7 @@ private void AddProjectileSpawns() { // Calculate the spawn position and direction for the new projectile var s = new ProjectileSpawn( - FindProjectileRotationDir(Dir, (Direction)d), // Calculate the rotation direction + FindProjectileRotationDir(Dir, (Direction)d), (byte)(X + FindProjectileRotation(Dir, x - 2, y - 2, true)), (byte)(Y + FindProjectileRotation(Dir, x - 2, y - 2, false)), (byte)Z, MapId, MapInstanceId, Base, this @@ -123,7 +123,6 @@ private void AddProjectileSpawns() _spawnedAmount++; _spawnCount++; - // Check for collision at the spawn location, mark as dead if collision is detected if (CheckForCollision(s)) { s.Dead = true; @@ -144,7 +143,7 @@ private void AddProjectileSpawns() /// The direction of the projectile. /// The x-coordinate value. /// The y-coordinate value. - /// Determines if the calculation is for the X axis (true) or Y axis (false). + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. /// The rotation value for the specified axis based on the direction. private static int FindProjectileRotation(Direction direction, int x, int y, bool isXAxis) { @@ -190,7 +189,7 @@ public void Update(List projDeaths, List> spawnDea /// /// The direction of the projectile. /// The range of the projectile. - /// A boolean value indicating whether the axis is the X-axis. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. /// The calculated range value. private static float GetRange(Direction direction, float range, bool isXAxis) { @@ -333,6 +332,7 @@ public bool CheckForCollision(ProjectileSpawn spawn) !spawn.Parent.HasGrappled && (spawn.X != Owner.X || spawn.Y != Owner.Y)) { + // Grapple hooks are only allowed in the default projectile behavior if (!spawn.ProjectileBase.HomingBehavior && !spawn.ProjectileBase.DirectShotBehavior && (spawn.Dir <= Direction.Right || (spawn.Dir != Direction.None && Options.Instance.MapOpts.EnableDiagonalMovement))) { @@ -386,60 +386,62 @@ public bool CheckForCollision(ProjectileSpawn spawn) } /// - /// Calculates the offset of a projectile based on the target's position and the spawn location. + /// Calculates the offset for the projectile spawn position based on the target map and spawn location. /// - /// A boolean value indicating whether the calculation should be done horizontally (X-axis) or vertically (Y-axis). /// The projectile spawn information. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. /// The calculated offset value. - private float GetProjectileOffset(bool isXAxis, ProjectileSpawn spawn) + private float GetProjectileOffset(ProjectileSpawn spawn, bool isXAxis) { - if (_lastTargetMapId != Guid.Empty && _lastTargetMapId != spawn.MapId && MapController.TryGet(spawn.MapId, out var map)) + if (_lastTargetMapId == Guid.Empty || _lastTargetMapId == spawn.MapId || !MapController.TryGet(spawn.MapId, out var map)) { - var grid = DbInterface.GetGrid(map.MapGrid); + return isXAxis ? _lastTargetX - spawn.X : _lastTargetY - spawn.Y; + } + + var grid = DbInterface.GetGrid(map.MapGrid); - for (var y = map.MapGridY - 1; y <= map.MapGridY + 1; y++) + for (var y = map.MapGridY - 1; y <= map.MapGridY + 1; y++) + { + for (var x = map.MapGridX - 1; x <= map.MapGridX + 1; x++) { - for (var x = map.MapGridX - 1; x <= map.MapGridX + 1; x++) + if (x < 0 || x >= grid.MapIdGrid.GetLength(0) || y < 0 || y >= grid.MapIdGrid.GetLength(1)) { - if (x < 0 || x >= grid.MapIdGrid.GetLength(0) || y < 0 || y >= grid.MapIdGrid.GetLength(1)) + continue; + } + + if (grid.MapIdGrid[x, y] != _lastTargetMapId || grid.MapIdGrid[x, y] == Guid.Empty) + { + continue; + } + + if (isXAxis) + { + var leftSide = x == map.MapGridX - 1; + var rightSide = x == map.MapGridX + 1; + + if (leftSide) { - continue; + return _lastTargetX - Options.MapWidth - spawn.X; } - if (grid.MapIdGrid[x, y] != _lastTargetMapId || grid.MapIdGrid[x, y] == Guid.Empty) + if (rightSide) { - continue; + return _lastTargetX + Options.MapWidth - spawn.X; } + } + else + { + var topSide = y == map.MapGridY - 1; + var bottomSide = y == map.MapGridY + 1; - if (isXAxis) // Horizontal (X) calculation + if (topSide) { - var leftSide = x == map.MapGridX - 1; - var rightSide = x == map.MapGridX + 1; - - if (leftSide) - { - return _lastTargetX - Options.MapWidth - spawn.X; - } - - if (rightSide) - { - return _lastTargetX + Options.MapWidth - spawn.X; - } + return _lastTargetY - Options.MapHeight - spawn.Y; } - else // Vertical (Y) calculation - { - var topSide = y == map.MapGridY - 1; - var bottomSide = y == map.MapGridY + 1; - if (topSide) - { - return _lastTargetY - Options.MapHeight - spawn.Y; - } - - if (bottomSide) - { - return _lastTargetY + Options.MapHeight - spawn.Y; - } + if (bottomSide) + { + return _lastTargetY + Options.MapHeight - spawn.Y; } } } @@ -469,8 +471,7 @@ public bool MoveFragment(ProjectileSpawn spawn, bool move = true) _lastTargetX = Target.X; _lastTargetY = Target.Y; _lastTargetMapId = Target.MapId; - var directionX = GetProjectileOffset(true, spawn); - var directionY = GetProjectileOffset(false, spawn); + var (directionX, directionY) = (GetProjectileOffset(spawn, true), GetProjectileOffset(spawn, false)); var distance = MathF.Sqrt(directionX * directionX + directionY * directionY); // Normalize the direction and update the projectile's position. @@ -486,8 +487,7 @@ public bool MoveFragment(ProjectileSpawn spawn, bool move = true) else if (_lastTargetX != -1 && _lastTargetY != -1) { // Last known target location logic: Moves the projectile towards the last known position of the target. - var directionX = GetProjectileOffset(true, spawn); - var directionY = GetProjectileOffset(false, spawn); + var (directionX, directionY) = (GetProjectileOffset(spawn, true), GetProjectileOffset(spawn, false)); var distance = MathF.Sqrt(directionX * directionX + directionY * directionY); // Normalize the direction and update the projectile's position.