diff --git a/Patches/Vanilla Factions Expanded - Settlers/ThingDefs_Buildings/TurretGatlingGun.xml b/Patches/Vanilla Factions Expanded - Settlers/ThingDefs_Buildings/TurretGatlingGun.xml index 604ae94975..e6127f76d6 100644 --- a/Patches/Vanilla Factions Expanded - Settlers/ThingDefs_Buildings/TurretGatlingGun.xml +++ b/Patches/Vanilla Factions Expanded - Settlers/ThingDefs_Buildings/TurretGatlingGun.xml @@ -77,8 +77,8 @@ -
  • - Defs/ThingDef[defName="Turret_GatlingGun"]/costList +
  • + Defs/ThingDef[defName="Turret_GatlingGun"] 325 diff --git a/Source/CombatExtended/CombatExtended/Comps/CompSuppressable.cs b/Source/CombatExtended/CombatExtended/Comps/CompSuppressable.cs index 322125000f..16bf2ac8aa 100644 --- a/Source/CombatExtended/CombatExtended/Comps/CompSuppressable.cs +++ b/Source/CombatExtended/CombatExtended/Comps/CompSuppressable.cs @@ -246,7 +246,7 @@ public void AddSuppression(float amount, IntVec3 origin) } public bool IgnoreSuppresion(IntVec3 origin) { - return BlockerRegistry.PawnUnsuppresableFromCallback(parent as Pawn, origin) || SuppressionUtility.InterceptorZonesFor((Pawn)parent).Where(x => x.Contains(parent.Position)).Any(x => !x.Contains(origin)); + return BlockerRegistry.PawnUnsuppressableFromCallback(parent as Pawn, origin) || SuppressionUtility.InterceptorZonesFor((Pawn)parent).Where(x => x.Contains(parent.Position)).Any(x => !x.Contains(origin)); } public override void CompTick() diff --git a/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs b/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs index dfea34a41d..8087b71485 100644 --- a/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs +++ b/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs @@ -28,17 +28,6 @@ public abstract class ProjectileCE : ThingWithComps /// protected const int collisionCheckSize = 5; - #region Kinetic Projectiles - protected bool lerpPosition = true; - protected bool kinit = false; - protected float ballisticCoefficient; - protected float mass; - protected float radius; - protected float gravity; - protected Vector3 velocity; - protected float initialSpeed; - #endregion - #region Origin destination public bool OffMapOrigin = false; @@ -112,11 +101,7 @@ public virtual float DamageAmount this.damageAmount = def.projectile.GetDamageAmount(weaponDamageMultiplier); } - if (lerpPosition) - { - return (float)this.damageAmount; - } - return ((float)this.damageAmount) * (shotSpeed * shotSpeed) / (initialSpeed * initialSpeed); + return (float)this.damageAmount; } } @@ -139,7 +124,7 @@ public virtual float DamageAmount #region Vanilla public bool landed; public int ticksToImpact; - protected Sustainer ambientSustainer; + private Sustainer ambientSustainer; #endregion @@ -148,25 +133,33 @@ public virtual float DamageAmount public float AccuracyFactor; #region Height + protected int lastHeightTick = -1; + protected float heightInt = 0f; + /// + /// If lastHeightTick is not FlightTicks, Height calculates the quadratic formula (g/2)t^2 + (-v_0y)t + (y-y0) for {g -> gravity, v_0y -> shotSpeed * Mathf.Sin(shotAngle), y0 -> shotHeight, t -> seconds} to find y rounded to the nearest 3 decimals. + /// + /// If lastHeightTick equals FlightTicks, it returns a locally stored value heightInt which is the product of previous calculation. + /// public virtual float Height { get { - return ExactPosition.y; + if (lastHeightTick != FlightTicks) + { + heightInt = ticksToImpact > 0 ? GetHeightAtTicks(FlightTicks) : 0f; + lastHeightTick = FlightTicks; + } + return heightInt; } } #endregion #region Ticks/Seconds - protected float startingTicksToImpactInt = -1f; + float startingTicksToImpactInt = -1f; public float StartingTicksToImpact { get { - if (!lerpPosition) - { - return float.MaxValue; - } if (startingTicksToImpactInt < 0f) { // Optimization in case shotHeight is zero (for example for fragments) @@ -203,10 +196,6 @@ public int IntTicksToImpact { get { - if (!lerpPosition) - { - return 1; - } if (intTicksToImpact < 0) { intTicksToImpact = Mathf.CeilToInt(StartingTicksToImpact); @@ -215,7 +204,6 @@ public int IntTicksToImpact } } - private int flightTicks; /// /// The amount of integer ticks this projectile has remained in the air for, ignoring impact. /// @@ -223,7 +211,7 @@ public int FlightTicks { get { - return flightTicks; + return IntTicksToImpact - ticksToImpact; } } /// @@ -248,7 +236,7 @@ protected virtual Vector2 Vec2Position(float ticks = -1f) return Vector2.Lerp(origin, Destination, ticks / StartingTicksToImpact); } - private Vector3? exactPosition = null; + private Vector3 impactPosition = new Vector3(); /// /// Exact x,y,z (x,height,y) position in terms of Vec2Position.x, .y (lerped origin to Destination) and Height. /// @@ -256,16 +244,17 @@ public virtual Vector3 ExactPosition { set { - exactPosition = new Vector3(value.x, value.y, value.z); - Position = ((Vector3)exactPosition).ToIntVec3(); + impactPosition = new Vector3(value.x, value.y, value.z); + Position = impactPosition.ToIntVec3(); } get { - if (exactPosition == null) + if (landed) { - exactPosition = new Vector3(origin.x, shotHeight, origin.y); + return impactPosition; } - return ((Vector3)exactPosition); + var v = Vec2Position(); + return new Vector3(v.x, Height, v.y); } } @@ -273,7 +262,7 @@ public virtual Vector2 DrawPosV2 { get { - return new Vector2(ExactPosition.x, ExactPosition.z); + return Vec2Position() + new Vector2(0, Height - shotHeight * ((StartingTicksToImpact - fTicks) / StartingTicksToImpact)); } } @@ -281,7 +270,8 @@ public override Vector3 DrawPos { get { - return ExactPosition; + var v = DrawPosV2; + return new Vector3(v.x, def.Altitude, v.y); } } @@ -380,7 +370,7 @@ public virtual Quaternion ExactRotation /// public float shotHeight = 0f; /// - /// The assigned shot speed [cells/s] (not speed in y axis or x-z plane), in general equal to the projectile.def.speed value. + /// The assigned shot speed [cells/s] (not speed in z axis or x-y plane), in general equal to the projectile.def.speed value. /// public float shotSpeed = -1f; @@ -472,42 +462,13 @@ public override void ExposeData() Scribe_Values.Look(ref canTargetSelf, "canTargetSelf"); Scribe_Values.Look(ref logMisses, "logMisses", true); Scribe_Values.Look(ref castShadow, "castShadow", true); - Scribe_Values.Look(ref lerpPosition, "lerpPosition", true); //To fix landed grenades sl problem - Scribe_Values.Look(ref exactPosition, "exactPosition"); + Scribe_Values.Look(ref impactPosition, "impactPosition"); // To insure saves don't get affected.. } #endregion - #region Throw - public virtual void Throw(Thing launcher, Vector3 origin, Vector3 heading, Thing equipment = null) - { - this.ExactPosition = origin; - this.shotHeight = origin.y; - this.origin = new Vector2(origin.x, origin.z); - this.shotSpeed = Math.Max(heading.magnitude, def.projectile.speed); - var projectileProperties = def.projectile as ProjectilePropertiesCE; - this.castShadow = projectileProperties.castShadow; - this.velocity = heading; - this.launcher = launcher; - this.equipment = equipment; - //For explosives/bullets, equipmentDef is important - equipmentDef = (equipment != null) ? equipment.def : null; - - if (!def.projectile.soundAmbient.NullOrUndefined()) - { - var info = SoundInfo.InMap(this, MaintenanceType.PerTick); - ambientSustainer = def.projectile.soundAmbient.TrySpawnSustainer(info); - } - ballisticCoefficient = projectileProperties.ballisticCoefficient.RandomInRange; - mass = projectileProperties.mass.RandomInRange; - radius = projectileProperties.diameter.RandomInRange / 2000; // half the diameter and mm -> m - gravity = projectileProperties.Gravity; - initialSpeed = shotSpeed; - } - #endregion - #region Raycast public virtual void RayCast(Thing launcher, VerbProperties verbProps, Vector2 origin, float shotAngle, float shotRotation, float shotHeight = 0f, float shotSpeed = -1f, float spreadDegrees = 0f, float aperatureSize = 0.03f, Thing equipment = null) { @@ -666,7 +627,6 @@ public virtual void Launch(Thing launcher, Vector2 origin, float shotAngle, floa if (def.projectile is ProjectilePropertiesCE props) { this.castShadow = props.castShadow; - this.lerpPosition = props.lerpPosition; } Launch(launcher, origin, equipment); this.ticksToImpact = IntTicksToImpact; @@ -926,7 +886,7 @@ protected bool CheckCellForCollision(IntVec3 cell) roofChecked = true; } - foreach (var thing in mainThingList.Distinct().Where(x => !(x is ProjectileCE)).OrderBy(x => (x.DrawPos - LastPos).sqrMagnitude)) + foreach (var thing in mainThingList.Distinct().OrderBy(x => (x.DrawPos - LastPos).sqrMagnitude)) { if ((thing == launcher || thing == mount) && !canTargetSelf) { @@ -1166,47 +1126,6 @@ protected void ApplySuppression(Pawn pawn, float suppressionMultiplier = 1f) } } - // If anyone wants to override how projectiles move, this can be made virtual. - // For now, it is non-virtual for performance. - protected Vector3 MoveForward() - { - Vector3 curPosition = ExactPosition; - float sr = shotRotation * Mathf.Deg2Rad + 3.14159f / 2.0f; - if (!kinit) - { - kinit = true; - var projectileProperties = def.projectile as ProjectilePropertiesCE; - ballisticCoefficient = projectileProperties.ballisticCoefficient.RandomInRange; - mass = projectileProperties.mass.RandomInRange; - radius = projectileProperties.diameter.RandomInRange / 2000; - gravity = projectileProperties.Gravity; - float sspt = shotSpeed / GenTicks.TicksPerRealSecond; - velocity = new Vector3(Mathf.Cos(sr) * Mathf.Cos(shotAngle) * sspt, Mathf.Sin(shotAngle) * sspt, Mathf.Sin(sr) * Mathf.Cos(shotAngle) * sspt); - initialSpeed = sspt; - } - Vector3 newPosition = curPosition + velocity; - Accelerate(); - return newPosition; - } - - // This can also be made virtual, and would be the ideal entry point for guided ammunition and rockets. - protected void Accelerate() - { - float crossSectionalArea = radius; - crossSectionalArea *= crossSectionalArea * 3.14159f; - // 2.5f is half the mass of 1m² x 1cell of air. - var q = 2.5f * shotSpeed * shotSpeed; - var dragForce = q * crossSectionalArea / ballisticCoefficient; - // F = mA - // A = F / m - var a = (float)((-dragForce / (float)mass)); - var normalized = velocity.normalized; - velocity.x += a * normalized.x; - velocity.y += a * normalized.y - (float)(1 / ballisticCoefficient) * (float)gravity / GenTicks.TicksPerRealSecond; - velocity.z += a * normalized.z; - shotSpeed = velocity.magnitude; - } - #region Tick/Draw public override void Tick() { @@ -1217,18 +1136,7 @@ public override void Tick() } LastPos = ExactPosition; ticksToImpact--; - flightTicks++; - Vector3 nextPosition; - if (lerpPosition) - { - var v = Vec2Position(); - nextPosition = new Vector3(v.x, Height, v.y); - } - else - { - nextPosition = MoveForward(); - } - if (!nextPosition.InBounds(Map)) + if (!ExactPosition.InBounds(Map)) { if (globalTargetInfo.IsValid) { @@ -1257,12 +1165,11 @@ public override void Tick() Destroy(); return; } - ExactPosition = nextPosition; if (CheckForCollisionBetween()) { return; } - Position = nextPosition.ToIntVec3(); + Position = ExactPosition.ToIntVec3(); if (globalTargetInfo.IsValid) { return; @@ -1272,7 +1179,7 @@ public override void Tick() def.projectile.soundImpactAnticipate.PlayOneShot(this); } //TODO : It appears that the final steps in the arc (past ticksToImpact == 0) don't CheckForCollisionBetween. - if (ticksToImpact <= 0 || nextPosition.y <= 0f) + if (ticksToImpact <= 0) { ImpactSomething(); return; @@ -1298,7 +1205,7 @@ public override void Tick() } float distToOrigin = originInt.DistanceTo(positionInt); float dangerFactor = (def.projectile as ProjectilePropertiesCE).dangerFactor; - if (dangerFactor > 0f && nextPosition.y < CollisionVertical.WallCollisionHeight && distToOrigin > 3) + if (dangerFactor > 0f && ExactPosition.y < CollisionVertical.WallCollisionHeight && distToOrigin > 3) { DangerTracker?.Notify_BulletAt(Position, def.projectile.damageAmountBase * dangerFactor); } @@ -1575,7 +1482,7 @@ public virtual void Impact(Thing hitThing) /// /// Integer ticks, since the only time value which is not an integer (accessed by StartingTicksToImpact) has height zero by definition. /// Projectile height at time ticks in ticks. - private float GetHeightAtTicks(int ticks) + protected virtual float GetHeightAtTicks(int ticks) { var seconds = ((float)ticks) / GenTicks.TicksPerRealSecond; return (float)Math.Round(shotHeight + shotSpeed * Mathf.Sin(shotAngle) * seconds - (GravityFactor * seconds * seconds) / 2f, 3); diff --git a/Source/CombatExtended/CombatExtended/Projectiles/ProjectilePropertiesCE.cs b/Source/CombatExtended/CombatExtended/Projectiles/ProjectilePropertiesCE.cs index 3a55f3ae30..3c42e78272 100644 --- a/Source/CombatExtended/CombatExtended/Projectiles/ProjectilePropertiesCE.cs +++ b/Source/CombatExtended/CombatExtended/Projectiles/ProjectilePropertiesCE.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -31,11 +31,6 @@ public class ProjectilePropertiesCE : ProjectileProperties public float airborneSuppressionFactor = 1; public float dangerFactor = 1; - public FloatRange ballisticCoefficient = new FloatRange(1f, 1f); - public FloatRange mass = new FloatRange(1f, 1f); - public FloatRange diameter = new FloatRange(1f, 1f); - - public bool lerpPosition = true; public ThingDef detonateMoteDef; public FleckDef detonateFleckDef; public float detonateEffectsScaleOverride = -1; diff --git a/Source/CombatExtended/Compatibility/BlockerRegistry.cs b/Source/CombatExtended/Compatibility/BlockerRegistry.cs index f0f3fdf7cd..5489f34c28 100644 --- a/Source/CombatExtended/Compatibility/BlockerRegistry.cs +++ b/Source/CombatExtended/Compatibility/BlockerRegistry.cs @@ -21,7 +21,7 @@ public static class BlockerRegistry private static List> checkCellForCollisionCallbacks; private static List> impactSomethingCallbacks; private static List> beforeCollideWithCallbacks; - private static List> pawnUnsuppresableFromCallback; + private static List> pawnUnsuppressableFromCallback; private static List>>> shieldZonesCallback; private static void EnableCB() @@ -47,7 +47,7 @@ private static void EnableSZ() private static void EnablePUF() { enabledPUF = true; - pawnUnsuppresableFromCallback = new List>(); + pawnUnsuppressableFromCallback = new List>(); } private static void EnableBCW() { @@ -118,7 +118,7 @@ public static void RegisterUnsuppresableFromCallback(Func f { EnablePUF(); } - pawnUnsuppresableFromCallback.Add(f); + pawnUnsuppressableFromCallback.Add(f); } public static bool CheckCellForCollisionCallback(ProjectileCE projectile, IntVec3 cell, Thing launcher) @@ -159,13 +159,13 @@ public static IEnumerable> ShieldZonesCallback(Thing thing) } return shieldZonesCallback.SelectMany(cb => cb(thing)); } - public static bool PawnUnsuppresableFromCallback(Pawn pawn, IntVec3 origin) + public static bool PawnUnsuppressableFromCallback(Pawn pawn, IntVec3 origin) { if (!enabledPUF) { return false; } - foreach (var cb in pawnUnsuppresableFromCallback) + foreach (var cb in pawnUnsuppressableFromCallback) { if (cb(pawn, origin)) {