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.