Skip to content

Commit

Permalink
Moved rotation and angle calculations to trajectory worker
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxDorob committed Nov 25, 2024
1 parent 7c4c72a commit 414eb6f
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 55 deletions.
21 changes: 1 addition & 20 deletions Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1510,26 +1510,7 @@ protected float GetHeightAtTicks(int ticks)
/// <returns>Distance in cells that the projectile will fly at the given arc.</returns>
protected float DistanceTraveled => TrajectoryWorker.DistanceTraveled(shotHeight, shotSpeed, shotAngle, GravityFactor);

/// <summary>
/// Calculates the shot angle necessary to reach <i>range</i> with a projectile of speed <i>velocity</i> at a height difference of <i>heightDifference</i>, returning either the upper or lower arc in radians. Does not take into account air resistance.
/// </summary>
/// <param name="velocity">Projectile velocity in cells per second.</param>
/// <param name="range">Cells between shooter and target.</param>
/// <param name="heightDifference">Difference between initial shot height and target height in vertical cells.</param>
/// <param name="flyOverhead">Whether to take the lower (False) or upper (True) arc angle.</param>
/// <returns>Arc angle in radians off the ground.</returns>
public static float GetShotAngle(float velocity, float range, float heightDifference, bool flyOverhead, float gravity)
{
float squareRootCheck = Mathf.Sqrt(Mathf.Pow(velocity, 4f) - gravity * (gravity * Mathf.Pow(range, 2f) + 2f * heightDifference * Mathf.Pow(velocity, 2f)));
if (float.IsNaN(squareRootCheck))
{
//Target is too far to hit with given velocity/range/gravity params
//set firing angle for maximum distance
Log.Warning("[CE] Tried to fire projectile to unreachable target cell, truncating to maximum distance.");
return 45.0f * Mathf.Deg2Rad;
}
return Mathf.Atan((Mathf.Pow(velocity, 2f) + (flyOverhead ? 1f : -1f) * squareRootCheck) / (gravity * range));
}

#endregion

protected static Material[] GetShadowMaterial(Graphic_Collection g)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,44 @@ public virtual Vector3 GetVelocity(float shotSpeed, float rotation, float angle)
angle = angle * Mathf.Rad2Deg; // transform to degrees
return Vector2.up.RotatedBy(rotation).ToVector3().RotatedBy(angle) * shotSpeed / GenTicks.TicksPerRealSecond;
}

/// <summary>
/// Shot angle in radians
/// </summary>
/// <param name="source">Source shot, including shot height</param>
/// <param name="targetPos">Target position, including target height</param>
/// <returns>angle in radians</returns>
public virtual float ShotAngle(ProjectilePropertiesCE projectilePropsCE, Vector3 source, Vector3 targetPos, float? velocity = null)
{
var targetHeight = targetPos.y;
var shotHeight = source.y;
var newTargetLoc = new Vector2(targetPos.x, targetPos.z);
var sourceV2 = new Vector2(source.x, source.z);
if (projectilePropsCE.isInstant)
{
return Mathf.Atan2(targetHeight - shotHeight, (newTargetLoc - sourceV2).magnitude);
}
else
{
var _velocity = velocity ?? projectilePropsCE.speed;
var gravity = projectilePropsCE.Gravity;
var heightDifference = targetHeight - shotHeight;
var range = (newTargetLoc - sourceV2).magnitude;
float squareRootCheck = Mathf.Sqrt(Mathf.Pow(_velocity, 4f) - gravity * (gravity * Mathf.Pow(range, 2f) + 2f * heightDifference * Mathf.Pow(_velocity, 2f)));
if (float.IsNaN(squareRootCheck))
{
//Target is too far to hit with given velocity/range/gravity params
//set firing angle for maximum distance
Log.Warning("[CE] Tried to fire projectile to unreachable target cell, truncating to maximum distance.");
return 45.0f * Mathf.Deg2Rad;
}
return Mathf.Atan((Mathf.Pow(_velocity, 2f) + (projectilePropsCE.flyOverhead ? 1f : -1f) * squareRootCheck) / (gravity * range));
}
}
public virtual float ShotRotation(ProjectilePropertiesCE projectilePropertiesCE, Vector3 source, Vector3 targetPos)
{
var w = targetPos - source;
return ( - 90 + Mathf.Rad2Deg * Mathf.Atan2(w.z, w.x)) % 360;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -610,16 +610,7 @@ protected float ShotAngle(Vector3 targetPos)
/// <returns>angle in radians</returns>
protected virtual float ShotAngle(Vector3 source, Vector3 targetPos)
{
var targetHeight = targetPos.y;
var newTargetLoc = new Vector2(targetPos.x, targetPos.z);
if (projectilePropsCE.isInstant)
{
return Mathf.Atan2(targetHeight - ShotHeight, (newTargetLoc - sourceLoc).magnitude);
}
else
{
return ProjectileCE.GetShotAngle(ShotSpeed, (newTargetLoc - sourceLoc).magnitude, targetHeight - ShotHeight, Projectile.projectile.flyOverhead, projectilePropsCE.Gravity);
}
return projectilePropsCE.TrajectoryWorker.ShotAngle(projectilePropsCE, source, targetPos);
}
protected float ShotRotation(Vector3 targetPos)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,20 +151,18 @@ private bool TryShell(WorldObject worldObject)

private void LaunchProjectile(IntVec3 sourceCell, LocalTargetInfo target, Map map, float shotSpeed = 20, float shotHeight = 200)
{
IntVec3 targetCell = target.Cell;
Vector2 source = new Vector2(sourceCell.x, sourceCell.z);
Vector2 destination = new Vector2(targetCell.x, targetCell.z);
Vector2 w = (destination - source);
Vector3 source = new Vector3(sourceCell.x, shotHeight, sourceCell.z);
Vector3 targetPos = target.Cell.ToVector3Shifted();

ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(shellDef);
ProjectilePropertiesCE pprops = projectile.def.projectile as ProjectilePropertiesCE;
float shotRotation = (-90 + Mathf.Rad2Deg * Mathf.Atan2(w.y, w.x)) % 360;
float shotAngle = ProjectileCE.GetShotAngle(shotSpeed, (destination - source).magnitude, -shotHeight, false, pprops.Gravity);
float shotRotation = pprops.TrajectoryWorker.ShotRotation(pprops, source, targetPos);
float shotAngle = pprops.TrajectoryWorker.ShotAngle(pprops, source, targetPos, shotSpeed);

projectile.canTargetSelf = false;
projectile.Position = sourceCell;
projectile.SpawnSetup(map, false);
projectile.Launch(launcher, source, shotAngle, shotRotation, shotHeight, shotSpeed);
projectile.Launch(launcher, new Vector2(source.x, source.z), shotAngle, shotRotation, shotHeight, shotSpeed);
//projectile.cameraShakingInit = Rand.Range(0f, 2f);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,14 @@ internal static bool Prefix(CompAbilityEffect_LaunchProjectile __instance, Local
if (projectileDef.projectile is ProjectilePropertiesCE ppce)
{
Pawn pawn = __instance.parent.pawn;
var u = pawn.TrueCenter();
var sourceLoc = new Vector2();
sourceLoc.Set(u.x, u.z);
var targetLocation = new Vector2();
var u = pawn.TrueCenter().WithY((new CollisionVertical(pawn)).shotHeight);
var targetPos = target.Thing != null ? target.Thing.TrueCenter() : target.Cell.ToVector3Shifted();
targetPos = targetPos.WithY((new CollisionVertical(target.Thing)).shotHeight);

if (target.HasThing)
{
targetLocation.Set(target.Thing.TrueCenter().x, target.Thing.TrueCenter().z);
}
else
{
targetLocation.Set(target.Cell.ToIntVec2.x, target.Cell.ToIntVec2.z);
}

var w = (targetLocation - sourceLoc);
float shotRotation = (-90 + Mathf.Rad2Deg * Mathf.Atan2(w.y, w.x)) % 360;

var targetVert = new CollisionVertical(target.Thing);
var angle = ProjectileCE.GetShotAngle(ppce.speed, (target.Cell - pawn.Position).LengthHorizontal, targetVert.HeightRange.Average - 1, ppce.flyOverhead, ppce.Gravity);
CE_Utility.LaunchProjectileCE(projectileDef, sourceLoc, target, pawn, angle, shotRotation, 1, ppce.speed);
var angle = ppce.TrajectoryWorker.ShotAngle(ppce, u, targetPos);
float shotRotation = ppce.TrajectoryWorker.ShotRotation(ppce, u, targetPos);
CE_Utility.LaunchProjectileCE(projectileDef, new Vector2(u.x, u.z), target, pawn, angle, shotRotation, u.y, ppce.speed);
return false;
}
}
Expand Down

0 comments on commit 414eb6f

Please sign in to comment.