Fixed frustum dynamic projectile index
(cherry picked from commit 2b30d22c1f49ac3e8ec42815a48cef6fa646e119)
This commit is contained in:
@@ -134,6 +134,7 @@ public class AreaSkillAttackAction
|
|||||||
.GetAttackablesInRange(targetAreaCenter, range)
|
.GetAttackablesInRange(targetAreaCenter, range)
|
||||||
.Where(a => a != player)
|
.Where(a => a != player)
|
||||||
.Where(a => !a.IsAtSafezone())
|
.Where(a => !a.IsAtSafezone())
|
||||||
|
.Where(a => a.IsActive())
|
||||||
?? [];
|
?? [];
|
||||||
|
|
||||||
if (skill.AreaSkillSettings is { UseFrustumFilter: true } areaSkillSettings)
|
if (skill.AreaSkillSettings is { UseFrustumFilter: true } areaSkillSettings)
|
||||||
@@ -239,6 +240,7 @@ public class AreaSkillAttackAction
|
|||||||
|
|
||||||
var orderedTargets = targets.ToList();
|
var orderedTargets = targets.ToList();
|
||||||
FrustumBasedTargetFilter? filter = null;
|
FrustumBasedTargetFilter? filter = null;
|
||||||
|
var extraProjectiles = 0;
|
||||||
var projectileCount = 1;
|
var projectileCount = 1;
|
||||||
var attackRounds = areaSkillSettings.MaximumNumberOfHitsPerTarget;
|
var attackRounds = areaSkillSettings.MaximumNumberOfHitsPerTarget;
|
||||||
|
|
||||||
@@ -246,11 +248,12 @@ public class AreaSkillAttackAction
|
|||||||
{
|
{
|
||||||
// Order targets by distance to process nearest targets first
|
// Order targets by distance to process nearest targets first
|
||||||
orderedTargets.Sort((a, b) => player.GetDistanceTo(a).CompareTo(player.GetDistanceTo(b)));
|
orderedTargets.Sort((a, b) => player.GetDistanceTo(a).CompareTo(player.GetDistanceTo(b)));
|
||||||
projectileCount = areaSkillSettings.ProjectileCount + (int)(player.Attributes?[Stats.ExtraProjectiles] ?? 0);
|
filter = FrustumFilters.GetOrAdd(areaSkillSettings, static s => new FrustumBasedTargetFilter(s.FrustumStartWidth, s.FrustumEndWidth, s.FrustumDistance, s.ProjectileCount));
|
||||||
|
extraProjectiles += (int)player.Attributes![Stats.ExtraProjectiles];
|
||||||
|
projectileCount = areaSkillSettings.ProjectileCount + extraProjectiles;
|
||||||
attackRounds = 1; // One attack round per projectile
|
attackRounds = 1; // One attack round per projectile
|
||||||
filter = FrustumFilters.GetOrAdd(areaSkillSettings, s => new FrustumBasedTargetFilter(s.FrustumStartWidth, s.FrustumEndWidth, s.FrustumDistance, projectileCount));
|
|
||||||
minAttacks = projectileCount;
|
|
||||||
maxAttacks = projectileCount;
|
maxAttacks = projectileCount;
|
||||||
|
minAttacks = projectileCount;
|
||||||
|
|
||||||
extraTarget = orderedTargets.FirstOrDefault(t => t.Id == extraTargetId);
|
extraTarget = orderedTargets.FirstOrDefault(t => t.Id == extraTargetId);
|
||||||
if (extraTarget is not null)
|
if (extraTarget is not null)
|
||||||
@@ -296,7 +299,7 @@ public class AreaSkillAttackAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For multiple projectiles, check if this specific projectile can hit the target
|
// For multiple projectiles, check if this specific projectile can hit the target
|
||||||
if (filter != null && !filter.IsTargetWithinBounds(player, target, rotation, projectileIndex))
|
if (filter != null && !filter.IsTargetWithinBounds(player, target, rotation, projectileIndex, extraProjectiles))
|
||||||
{
|
{
|
||||||
continue; // This projectile cannot hit this target
|
continue; // This projectile cannot hit this target
|
||||||
}
|
}
|
||||||
@@ -345,6 +348,11 @@ public class AreaSkillAttackAction
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter != null)
|
||||||
|
{
|
||||||
|
break; // This projectile has hit, so we move on to the next projectile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDelay += areaSkillSettings.DelayBetweenHits;
|
currentDelay += areaSkillSettings.DelayBetweenHits;
|
||||||
|
|||||||
@@ -78,8 +78,9 @@ public record FrustumBasedTargetFilter
|
|||||||
/// <param name="target">The target.</param>
|
/// <param name="target">The target.</param>
|
||||||
/// <param name="rotation">The rotation.</param>
|
/// <param name="rotation">The rotation.</param>
|
||||||
/// <param name="projectileIndex">The zero-based index of the projectile (0 to ProjectileCount-1).</param>
|
/// <param name="projectileIndex">The zero-based index of the projectile (0 to ProjectileCount-1).</param>
|
||||||
|
/// <param name="extraProjectiles">The number of extra projectiles, if any.</param>
|
||||||
/// <returns><c>true</c> if the target is within hit bounds for the specified projectile; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if the target is within hit bounds for the specified projectile; otherwise, <c>false</c>.</returns>
|
||||||
public bool IsTargetWithinBounds(ILocateable attacker, ILocateable target, byte rotation, int projectileIndex)
|
public bool IsTargetWithinBounds(ILocateable attacker, ILocateable target, byte rotation, int projectileIndex, int extraProjectiles = 0)
|
||||||
{
|
{
|
||||||
if (this.ProjectileCount <= 1)
|
if (this.ProjectileCount <= 1)
|
||||||
{
|
{
|
||||||
@@ -87,7 +88,8 @@ public record FrustumBasedTargetFilter
|
|||||||
return this.IsTargetWithinBounds(attacker, target, rotation);
|
return this.IsTargetWithinBounds(attacker, target, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (projectileIndex < 0 || projectileIndex >= this.ProjectileCount)
|
var totalProjectiles = this.ProjectileCount + extraProjectiles;
|
||||||
|
if (projectileIndex < 0 || projectileIndex >= totalProjectiles)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -103,19 +105,19 @@ public record FrustumBasedTargetFilter
|
|||||||
|
|
||||||
// Divide the frustum into sections (-1 to 1 range)
|
// Divide the frustum into sections (-1 to 1 range)
|
||||||
// For 3 projectiles: left (-1 to -0.33), center (-0.33 to 0.33), right (0.33 to 1)
|
// For 3 projectiles: left (-1 to -0.33), center (-0.33 to 0.33), right (0.33 to 1)
|
||||||
var sectionWidth = 2.0 / this.ProjectileCount;
|
var sectionWidth = 2.0 / totalProjectiles;
|
||||||
var sectionStart = -1.0 + (projectileIndex * sectionWidth);
|
var sectionStart = -1.0 + (projectileIndex * sectionWidth);
|
||||||
var sectionEnd = sectionStart + sectionWidth;
|
var sectionEnd = sectionStart + sectionWidth;
|
||||||
|
|
||||||
// Add overlap so targets near boundaries can be hit by adjacent projectiles
|
// Add overlap so targets near boundaries can be hit by adjacent projectiles
|
||||||
var overlap = this.GetOverlap(attacker.Position, target.Position);
|
var overlap = this.GetOverlap(attacker.Position, target.Position, extraProjectiles);
|
||||||
sectionStart -= overlap;
|
sectionStart -= overlap;
|
||||||
sectionEnd += overlap;
|
sectionEnd += overlap;
|
||||||
|
|
||||||
return relativePosition >= sectionStart && relativePosition <= sectionEnd;
|
return relativePosition >= sectionStart && relativePosition <= sectionEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double GetOverlap(Point attackerPos, Point targetPos)
|
private double GetOverlap(Point attackerPos, Point targetPos, int extraProjectiles = 0)
|
||||||
{
|
{
|
||||||
var distance = attackerPos.EuclideanDistanceTo(targetPos);
|
var distance = attackerPos.EuclideanDistanceTo(targetPos);
|
||||||
if (distance == 0)
|
if (distance == 0)
|
||||||
@@ -124,7 +126,7 @@ public record FrustumBasedTargetFilter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The overlap decreases over higher distance
|
// The overlap decreases over higher distance
|
||||||
var overlap = (1.0 / Math.Floor(distance)) / this.ProjectileCount;
|
var overlap = (1.0 / Math.Floor(distance)) / (this.ProjectileCount + extraProjectiles);
|
||||||
overlap += 0.001; // Adding a small epsilon to make it slightly more tolerant in the comparisons
|
overlap += 0.001; // Adding a small epsilon to make it slightly more tolerant in the comparisons
|
||||||
return overlap;
|
return overlap;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -828,7 +828,7 @@ internal class SkillsInitializer : SkillsInitializerBase
|
|||||||
this.AddMasterSkillDefinition(SkillNumber.PenetrationStrengthener, SkillNumber.Penetration, SkillNumber.Undefined, 2, 3, SkillNumber.Penetration, 20, Formula502);
|
this.AddMasterSkillDefinition(SkillNumber.PenetrationStrengthener, SkillNumber.Penetration, SkillNumber.Undefined, 2, 3, SkillNumber.Penetration, 20, Formula502);
|
||||||
this.AddMasterSkillDefinition(SkillNumber.DefenseIncreaseStr, SkillNumber.GreaterDefense, SkillNumber.Undefined, 2, 3, SkillNumber.GreaterDefense, 20, $"{Formula502} / 100", Formula502, Stats.GreaterDefenseBonus, AggregateType.Multiplicate);
|
this.AddMasterSkillDefinition(SkillNumber.DefenseIncreaseStr, SkillNumber.GreaterDefense, SkillNumber.Undefined, 2, 3, SkillNumber.GreaterDefense, 20, $"{Formula502} / 100", Formula502, Stats.GreaterDefenseBonus, AggregateType.Multiplicate);
|
||||||
this.AddMasterSkillDefinition(SkillNumber.TripleShotMastery, SkillNumber.TripleShotStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.TripleShotStrengthener, 10, Formula1WhenComplete, Formula1WhenComplete, Stats.ExtraProjectiles, AggregateType.AddRaw);
|
this.AddMasterSkillDefinition(SkillNumber.TripleShotMastery, SkillNumber.TripleShotStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.TripleShotStrengthener, 10, Formula1WhenComplete, Formula1WhenComplete, Stats.ExtraProjectiles, AggregateType.AddRaw);
|
||||||
this.AddPassiveMasterSkillDefinition(SkillNumber.SummonedMonsterStr2, Stats.SummonedMonsterDefenseIncrease, AggregateType.AddRaw, Formula6020, 2, 3, SkillNumber.SummonGoblin);
|
this.AddPassiveMasterSkillDefinition(SkillNumber.SummonedMonsterStr2, Stats.SummonedMonsterDefenseIncrease, AggregateType.AddRaw, Formula6020Value, 3, 2, SkillNumber.SummonGoblin);
|
||||||
this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseStr, SkillNumber.GreaterDamage, SkillNumber.Undefined, 2, 4, SkillNumber.GreaterDamage, 20, $"{Formula502} / 100", Formula502, Stats.GreaterDamageBonus, AggregateType.Multiplicate);
|
this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseStr, SkillNumber.GreaterDamage, SkillNumber.Undefined, 2, 4, SkillNumber.GreaterDamage, 20, $"{Formula502} / 100", Formula502, Stats.GreaterDamageBonus, AggregateType.Multiplicate);
|
||||||
this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryHighElf, Stats.MasterSkillPhysBonusDmg, AggregateType.AddRaw, Formula502, 4, 2);
|
this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryHighElf, Stats.MasterSkillPhysBonusDmg, AggregateType.AddRaw, Formula502, 4, 2);
|
||||||
this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseMastery, SkillNumber.AttackIncreaseStr, SkillNumber.Undefined, 2, 5, SkillNumber.AttackIncreaseStr, 20, $"{Formula502} / 100", Formula502, Stats.GreaterDamageBonus, AggregateType.Multiplicate, true);
|
this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseMastery, SkillNumber.AttackIncreaseStr, SkillNumber.Undefined, 2, 5, SkillNumber.AttackIncreaseStr, 20, $"{Formula502} / 100", Formula502, Stats.GreaterDamageBonus, AggregateType.Multiplicate, true);
|
||||||
|
|||||||
Reference in New Issue
Block a user