private void updateGrav() { // get grav vector var tempGrav = MyParticlesManager.CalculateGravityInPoint(Entity.PositionComp.GetPosition()); //MyAPIGateway.Utilities.ShowNotification(Entity.DisplayName + gravity.ToString()); // if grav changed, flip flag, update grav if (tempGrav != gravity) { gravity = tempGrav; updateCable = true; } }
public Vector3D GetPredictedTargetPositionOld(Vector3D targetPos, Vector3 targetLinVel, Vector3D targetAccel) { if (Comp.Ai.VelocityUpdateTick != Comp.Session.Tick) { Comp.Ai.GridVel = Comp.Ai.MyGrid.Physics?.LinearVelocity ?? Vector3D.Zero; Comp.Ai.IsStatic = Comp.Ai.MyGrid.Physics?.IsStatic ?? false; Comp.Ai.VelocityUpdateTick = Comp.Session.Tick; } if (ActiveAmmoDef.AmmoDef.Const.FeelsGravity && Comp.Ai.Session.Tick - GravityTick > 119) { GravityTick = Comp.Ai.Session.Tick; GravityPoint = MyParticlesManager.CalculateGravityInPoint(MyPivotPos); } var gravityMultiplier = ActiveAmmoDef.AmmoDef.Const.FeelsGravity && !MyUtils.IsZero(GravityPoint) ? ActiveAmmoDef.AmmoDef.Trajectory.GravityMultiplier : 0f; var predictedPos = TrajectoryEstimation(targetPos, targetLinVel, targetAccel, Comp.Session.MaxEntitySpeed, MyPivotPos, Comp.Ai.GridVel, ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed, ActiveAmmoDef.AmmoDef.Trajectory.AccelPerSec * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS, ActiveAmmoDef.AmmoDef.Trajectory.AccelPerSec, gravityMultiplier, GravityPoint, System.Prediction != Prediction.Advanced); return(predictedPos); }
public Vector3D GetPredictedTargetPosition(Vector3D targetPos, Vector3 targetLinVel, Vector3D targetAccel) { if (Comp.Ai.VelocityUpdateTick != Comp.Session.Tick) { Comp.Ai.GridVel = Comp.Ai.MyGrid.Physics?.LinearVelocity ?? Vector3D.Zero; Comp.Ai.IsStatic = Comp.Ai.MyGrid.Physics?.IsStatic ?? false; Comp.Ai.VelocityUpdateTick = Comp.Session.Tick; } var gravityMultiplier = 0f; var gravityPoint = Vector3D.Zero; if (ActiveAmmoDef.AmmoDef.Const.FeelsGravity) { gravityMultiplier = ActiveAmmoDef.AmmoDef.Trajectory.GravityMultiplier; gravityPoint = MyParticlesManager.CalculateGravityInPoint(MyPivotPos); } var predictedPos = TrajectoryEstimation(targetPos, targetLinVel, targetAccel, Comp.Session.MaxEntitySpeed, MyPivotPos, Comp.Ai.GridVel, ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed, 0, ActiveAmmoDef.AmmoDef.Trajectory.AccelPerSec, gravityMultiplier, gravityPoint, System.Prediction != Prediction.Advanced); return(predictedPos); }
internal static Vector3D TrajectoryEstimation(Weapon weapon, Vector3D targetPos, Vector3D targetVel, Vector3D targetAcc, out bool valid) { valid = true; var ai = weapon.Comp.Ai; var session = ai.Session; var ammoDef = weapon.ActiveAmmoDef.AmmoDef; if (ai.VelocityUpdateTick != session.Tick) { ai.GridVel = ai.MyGrid.Physics?.LinearVelocity ?? Vector3D.Zero; ai.IsStatic = ai.MyGrid.Physics?.IsStatic ?? false; ai.VelocityUpdateTick = session.Tick; } if (ammoDef.Const.FeelsGravity && session.Tick - weapon.GravityTick > 119) { weapon.GravityTick = session.Tick; weapon.GravityPoint = MyParticlesManager.CalculateGravityInPoint(weapon.MyPivotPos); } var gravityMultiplier = ammoDef.Const.FeelsGravity && !MyUtils.IsZero(weapon.GravityPoint) ? ammoDef.Trajectory.GravityMultiplier : 0f; var targetMaxSpeed = weapon.Comp.Session.MaxEntitySpeed; var shooterPos = weapon.MyPivotPos; var shooterVel = (Vector3D)weapon.Comp.Ai.GridVel; var projectileMaxSpeed = ammoDef.Const.DesiredProjectileSpeed; var projectileInitSpeed = ammoDef.Trajectory.AccelPerSec * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; var projectileAccMag = ammoDef.Trajectory.AccelPerSec; var gravity = weapon.GravityPoint; var basic = weapon.System.Prediction != Prediction.Advanced; Vector3D deltaPos = targetPos - shooterPos; Vector3D deltaVel = targetVel - shooterVel; Vector3D deltaPosNorm; if (Vector3D.IsZero(deltaPos)) { deltaPosNorm = Vector3D.Zero; } else if (Vector3D.IsUnit(ref deltaPos)) { deltaPosNorm = deltaPos; } else { Vector3D.Normalize(ref deltaPos, out deltaPosNorm); } double closingSpeed; Vector3D.Dot(ref deltaVel, ref deltaPosNorm, out closingSpeed); Vector3D closingVel = closingSpeed * deltaPosNorm; Vector3D lateralVel = deltaVel - closingVel; double projectileMaxSpeedSqr = projectileMaxSpeed * projectileMaxSpeed; double ttiDiff = projectileMaxSpeedSqr - lateralVel.LengthSquared(); if (ttiDiff < 0) { valid = false; return(targetPos); } double projectileClosingSpeed = Math.Sqrt(ttiDiff) - closingSpeed; double closingDistance; Vector3D.Dot(ref deltaPos, ref deltaPosNorm, out closingDistance); double timeToIntercept = ttiDiff < 0 ? 0 : closingDistance / projectileClosingSpeed; if (timeToIntercept < 0) { valid = false; return(targetPos); } double maxSpeedSqr = targetMaxSpeed * targetMaxSpeed; double shooterVelScaleFactor = 1; bool projectileAccelerates = projectileAccMag > 1e-6; bool hasGravity = gravityMultiplier > 1e-6; if (!basic && projectileAccelerates) { shooterVelScaleFactor = Math.Min(1, (projectileMaxSpeed - projectileInitSpeed) / projectileAccMag); } Vector3D estimatedImpactPoint = targetPos + timeToIntercept * (targetVel - shooterVel * shooterVelScaleFactor); if (basic) { return(estimatedImpactPoint); } Vector3D aimDirection = estimatedImpactPoint - shooterPos; Vector3D projectileVel = shooterVel; Vector3D projectilePos = shooterPos; Vector3D aimDirectionNorm; if (projectileAccelerates) { if (Vector3D.IsZero(deltaPos)) { aimDirectionNorm = Vector3D.Zero; } else if (Vector3D.IsUnit(ref deltaPos)) { aimDirectionNorm = aimDirection; } else { aimDirectionNorm = Vector3D.Normalize(aimDirection); } projectileVel += aimDirectionNorm * projectileInitSpeed; } else { if (targetAcc.LengthSquared() < 1 && !hasGravity) { return(estimatedImpactPoint); } if (Vector3D.IsZero(deltaPos)) { aimDirectionNorm = Vector3D.Zero; } else if (Vector3D.IsUnit(ref deltaPos)) { aimDirectionNorm = aimDirection; } else { Vector3D.Normalize(ref aimDirection, out aimDirectionNorm); } projectileVel += aimDirectionNorm * projectileMaxSpeed; } var count = projectileAccelerates ? 600 : 60; double dt = Math.Max(MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS, timeToIntercept / count); // This can be a const somewhere double dtSqr = dt * dt; Vector3D targetAccStep = targetAcc * dt; Vector3D projectileAccStep = aimDirectionNorm * projectileAccMag * dt; Vector3D gravityStep = gravity * gravityMultiplier * dt; Vector3D aimOffset = Vector3D.Zero; double minDiff = double.MaxValue; for (int i = 0; i < count; ++i) { targetVel += targetAccStep; if (targetVel.LengthSquared() > maxSpeedSqr) { Vector3D targetNormVel; Vector3D.Normalize(ref targetVel, out targetNormVel); targetVel = targetNormVel * targetMaxSpeed; } targetPos += targetVel * dt; if (projectileAccelerates) { projectileVel += projectileAccStep; if (projectileVel.LengthSquared() > projectileMaxSpeedSqr) { Vector3D pNormVel; Vector3D.Normalize(ref projectileVel, out pNormVel); projectileVel = pNormVel * projectileMaxSpeed; } } if (hasGravity) { projectileVel += gravityStep; } projectilePos += projectileVel * dt; Vector3D diff = (targetPos - projectilePos); double diffLenSq = diff.LengthSquared(); if (diffLenSq < projectileMaxSpeedSqr * dtSqr) { aimOffset = diff; break; } if (diffLenSq < minDiff) { minDiff = diffLenSq; aimOffset = diff; } } return(estimatedImpactPoint + aimOffset); }
private void UpdateState() { foreach (var p in ActiveProjetiles) { p.Info.Age++; p.Active = false; switch (p.State) { case ProjectileState.Destroy: p.DestroyProjectile(); continue; case ProjectileState.Dead: continue; case ProjectileState.Start: p.Start(); break; case ProjectileState.OneAndDone: case ProjectileState.Depleted: case ProjectileState.Detonate: p.ProjectileClose(); continue; } if (p.Info.Target.IsProjectile) { if (p.Info.Target.Projectile.State != ProjectileState.Alive) { p.UnAssignProjectile(true); } } if (p.FeelsGravity) { var update = p.FakeGravityNear || p.EntitiesNear || p.Info.Ai.InPlanetGravity && p.Info.Age % 30 == 0 || !p.Info.Ai.InPlanetGravity && p.Info.Age % 10 == 0; if (update) { p.Gravity = MyParticlesManager.CalculateGravityInPoint(p.Position); if (!p.Info.Ai.InPlanetGravity && !MyUtils.IsZero(p.Gravity)) { p.FakeGravityNear = true; } else { p.FakeGravityNear = false; } } p.Velocity += (p.Gravity * p.Info.AmmoDef.Trajectory.GravityMultiplier) * Projectile.StepConst; Vector3D.Normalize(ref p.Velocity, out p.Info.Direction); } if (p.AccelLength > 0 && !p.Info.TriggeredPulse) { if (p.SmartsOn) { p.RunSmart(); } else { var accel = true; Vector3D newVel; if (p.FieldTime > 0) { var distToMax = p.Info.MaxTrajectory - p.Info.DistanceTraveled; var stopDist = p.VelocityLengthSqr / 2 / (p.StepPerSec); if (distToMax <= stopDist) { accel = false; } newVel = accel ? p.Velocity + p.AccelVelocity : p.Velocity - p.AccelVelocity; p.VelocityLengthSqr = newVel.LengthSquared(); if (accel && p.VelocityLengthSqr > p.MaxSpeedSqr) { newVel = p.Info.Direction * p.MaxSpeed; } else if (!accel && distToMax <= 0) { newVel = Vector3D.Zero; p.VelocityLengthSqr = 0; } } else { newVel = p.Velocity + p.AccelVelocity; p.VelocityLengthSqr = newVel.LengthSquared(); if (p.VelocityLengthSqr > p.MaxSpeedSqr) { newVel = p.Info.Direction * p.MaxSpeed; } } p.Velocity = newVel; } } if (p.State == ProjectileState.OneAndDone) { p.LastPosition = p.Position; var beamEnd = p.Position + (p.Info.Direction * p.Info.MaxTrajectory); p.TravelMagnitude = p.Position - beamEnd; p.Position = beamEnd; } else { if (p.ConstantSpeed || p.VelocityLengthSqr > 0) { p.LastPosition = p.Position; } p.TravelMagnitude = p.Velocity * StepConst; p.Position += p.TravelMagnitude; } p.Info.PrevDistanceTraveled = p.Info.DistanceTraveled; p.Info.DistanceTraveled += Math.Abs(Vector3D.Dot(p.Info.Direction, p.Velocity * StepConst)); if (p.ModelState == EntityState.Exists) { var up = MatrixD.Identity.Up; MatrixD matrix; MatrixD.CreateWorld(ref p.Position, ref p.Info.VisualDir, ref up, out matrix); if (p.Info.AmmoDef.Const.PrimeModel) { p.Info.AvShot.PrimeMatrix = matrix; } if (p.Info.AmmoDef.Const.TriggerModel && p.Info.TriggerGrowthSteps < p.Info.AmmoDef.Const.AreaEffectSize) { p.Info.TriggerMatrix = matrix; } if (p.EnableAv && p.AmmoEffect != null && p.Info.AmmoDef.Const.AmmoParticle && p.Info.AmmoDef.Const.PrimeModel) { var offVec = p.Position + Vector3D.Rotate(p.Info.AmmoDef.AmmoGraphics.Particles.Ammo.Offset, p.Info.AvShot.PrimeMatrix); p.AmmoEffect.WorldMatrix = p.Info.AvShot.PrimeMatrix; p.AmmoEffect.SetTranslation(ref offVec); } } else if (p.EnableAv && p.AmmoEffect != null && p.Info.AmmoDef.Const.AmmoParticle) { var translation = p.AmmoEffect.WorldMatrix.Translation + p.TravelMagnitude; p.AmmoEffect.SetTranslation(ref translation); } if (p.DynamicGuidance) { if (p.PruningProxyId != -1) { var sphere = new BoundingSphereD(p.Position, p.Info.AmmoDef.Const.AreaEffectSize); BoundingBoxD result; BoundingBoxD.CreateFromSphere(ref sphere, out result); Session.ProjectileTree.MoveProxy(p.PruningProxyId, ref result, p.Velocity); } } if (p.State != ProjectileState.OneAndDone) { if (!p.SmartsOn && p.Info.Age > p.Info.AmmoDef.Const.MaxLifeTime) { p.DistanceToTravelSqr = p.Info.DistanceTraveled * p.Info.DistanceTraveled; p.EarlyEnd = true; } if (p.Info.DistanceTraveled * p.Info.DistanceTraveled >= p.DistanceToTravelSqr) { p.AtMaxRange = true; if (p.FieldTime > 0) { p.FieldTime--; if (p.Info.AmmoDef.Const.IsMine && !p.MineSeeking && !p.MineActivated) { if (p.EnableAv) { p.Info.AvShot.Cloaked = p.Info.AmmoDef.Trajectory.Mines.Cloak; } p.MineSeeking = true; } } } } else { p.AtMaxRange = true; } if (p.Info.AmmoDef.Const.Ewar) { p.RunEwar(); } p.Active = true; } }
private void GenProjectiles() { for (int i = 0; i < NewProjectiles.Count; i++) { var gen = NewProjectiles[i]; var w = gen.Weapon; var a = gen.AmmoDef; var t = gen.Type; var virts = gen.NewVirts; var muzzle = gen.Muzzle; var firingPlayer = w.Comp.Data.Repo.Base.State.PlayerId == w.Comp.Session.PlayerId || w.ClientStaticShot; w.ClientStaticShot = false; var patternCycle = gen.PatternCycle; var targetable = w.ActiveAmmoDef.AmmoDef.Health > 0 && !w.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon; var p = Session.Projectiles.ProjectilePool.Count > 0 ? Session.Projectiles.ProjectilePool.Pop() : new Projectile(); p.Info.Id = Session.Projectiles.CurrentProjectileId++; p.Info.System = w.System; p.Info.Ai = w.Comp.Ai; p.Info.IsFiringPlayer = firingPlayer; p.Info.ClientSent = t == Kind.Client; p.Info.AmmoDef = a; p.Info.Overrides = w.Comp.Data.Repo.Base.Set.Overrides; p.Info.Target.Entity = t != Kind.Client ? w.Target.Entity : gen.TargetEnt; p.Info.Target.Projectile = w.Target.Projectile; p.Info.Target.IsProjectile = w.Target.Projectile != null; p.Info.Target.IsFakeTarget = w.Comp.Data.Repo.Base.State.TrackingReticle; p.Info.Target.FiringCube = w.Comp.MyCube; p.Info.DummyTarget = w.Comp.Data.Repo.Base.State.TrackingReticle ? w.Comp.Session.PlayerDummyTargets[w.Comp.Data.Repo.Base.State.PlayerId] : null; p.Info.WeaponId = w.WeaponId; p.Info.BaseDamagePool = a == w.ActiveAmmoDef.AmmoDef ? w.BaseDamage : a.BaseDamage; p.Info.EnableGuidance = w.Comp.Data.Repo.Base.Set.Guidance; p.Info.WeaponCache = w.WeaponCache; p.Info.WeaponRng = w.TargetData.WeaponRandom; p.Info.LockOnFireState = w.LockOnFireState; p.Info.ShooterVel = w.Comp.Ai.GridVel; p.Info.OriginUp = t != Kind.Client ? w.MyPivotUp : gen.OriginUp; p.Info.MaxTrajectory = t != Kind.Client ? a.Const.MaxTrajectoryGrows && w.FireCounter < a.Trajectory.MaxTrajectoryTime ? a.Const.TrajectoryStep * w.FireCounter : a.Const.MaxTrajectory : gen.MaxTrajectory; p.Info.MuzzleId = t != Kind.Virtual ? muzzle.MuzzleId : -1; p.Info.UniqueMuzzleId = muzzle.UniqueId; p.Info.WeaponCache.VirutalId = t != Kind.Virtual ? -1 : p.Info.WeaponCache.VirutalId; p.Info.Origin = t != Kind.Client ? t != Kind.Virtual ? muzzle.Position : w.MyPivotPos : gen.Origin; p.Info.Direction = t != Kind.Client ? t != Kind.Virtual ? muzzle.DeviatedDir : w.MyPivotDir : gen.Direction; if (t == Kind.Client) { p.Velocity = gen.Velocity; } float shotFade; if (a.Const.HasShotFade && !a.Const.VirtualBeams) { if (patternCycle > a.AmmoGraphics.Lines.Tracer.VisualFadeStart) { shotFade = MathHelper.Clamp(((patternCycle - a.AmmoGraphics.Lines.Tracer.VisualFadeStart)) * a.Const.ShotFadeStep, 0, 1); } else if (w.System.DelayCeaseFire && w.CeaseFireDelayTick != Session.Tick) { shotFade = MathHelper.Clamp(((Session.Tick - w.CeaseFireDelayTick) - a.AmmoGraphics.Lines.Tracer.VisualFadeStart) * a.Const.ShotFadeStep, 0, 1); } else { shotFade = 0; } } else { shotFade = 0; } p.Info.ShotFade = shotFade; p.PredictedTargetPos = w.Target.TargetPos; p.DeadSphere.Center = w.MyPivotPos; p.DeadSphere.Radius = w.Comp.Ai.MyGrid.GridSizeHalf + 0.1; if (a.Const.FeelsGravity && w.System.Session.Tick - w.GravityTick > 60) { w.GravityTick = w.System.Session.Tick; w.GravityPoint = MyParticlesManager.CalculateGravityInPoint(p.Info.Origin); } p.Gravity = w.GravityPoint; if (t != Kind.Virtual) { p.Info.PrimeEntity = a.Const.PrimeModel ? a.Const.PrimeEntityPool.Get() : null; p.Info.TriggerEntity = a.Const.TriggerModel ? Session.TriggerEntityPool.Get() : null; if (targetable) { Session.Projectiles.AddTargets.Add(p); } } else { p.Info.WeaponCache.VirtualHit = false; p.Info.WeaponCache.Hits = 0; p.Info.WeaponCache.HitEntity.Entity = null; for (int j = 0; j < virts.Count; j++) { var v = virts[j]; p.VrPros.Add(v.Info); if (!a.Const.RotateRealBeam) { p.Info.WeaponCache.VirutalId = 0; } else if (v.Rotate) { p.Info.Origin = v.Muzzle.Position; p.Info.Direction = v.Muzzle.Direction; p.Info.WeaponCache.VirutalId = v.VirtualId; } } virts.Clear(); VirtInfoPools.Return(virts); } Session.Projectiles.ActiveProjetiles.Add(p); p.Start(); p.Info.Monitors = w.Monitors; if (p.Info.Monitors?.Count > 0) { Session.MonitoredProjectiles[p.Info.Id] = p; for (int j = 0; j < p.Info.Monitors.Count; j++) { p.Info.Monitors[j].Invoke(w.Comp.MyCube.EntityId, w.WeaponId, p.Info.Id, p.Info.Target.TargetId, p.Position, true); } } } NewProjectiles.Clear(); }
private void UpdateState(int end = 0) { for (int i = ActiveProjetiles.Count - 1; i >= end; i--) { var p = ActiveProjetiles[i]; ++p.Info.Age; ++p.Info.Ai.MyProjectiles; p.Info.Ai.ProjectileTicker = p.Info.System.Session.Tick; switch (p.State) { case ProjectileState.Destroy: p.DestroyProjectile(); continue; case ProjectileState.Dead: continue; case ProjectileState.OneAndDone: case ProjectileState.Depleted: case ProjectileState.Detonate: if (p.Info.Age == 0 && p.State == ProjectileState.OneAndDone) { break; } p.ProjectileClose(); ProjectilePool.Push(p); ActiveProjetiles.RemoveAtFast(i); continue; } if (p.Info.Target.IsProjectile) { if (p.Info.Target.Projectile.State != ProjectileState.Alive) { p.UnAssignProjectile(true); } } if (!p.AtMaxRange) { if (p.FeelsGravity) { var update = (p.Info.Age % 60 == 0 || (p.FakeGravityNear || p.EntitiesNear) && p.Info.Age % 10 == 0) && p.Info.Age > 0; if (update) { p.Gravity = MyParticlesManager.CalculateGravityInPoint(p.Position); if (!p.Info.InPlanetGravity && !MyUtils.IsZero(p.Gravity)) { p.FakeGravityNear = true; } else { p.FakeGravityNear = false; } p.EntitiesNear = false; } p.Velocity += (p.Gravity * p.Info.AmmoDef.Trajectory.GravityMultiplier) * Projectile.StepConst; Vector3D.Normalize(ref p.Velocity, out p.Info.Direction); } if (p.DeltaVelocityPerTick > 0 && !p.Info.EwarAreaPulse) { if (p.SmartsOn) { p.RunSmart(); } else { var accel = true; Vector3D newVel; if (p.FieldTime > 0) { var distToMax = p.Info.MaxTrajectory - p.Info.DistanceTraveled; var stopDist = p.VelocityLengthSqr / 2 / (p.AccelInMetersPerSec); if (distToMax <= stopDist) { accel = false; } newVel = accel ? p.Velocity + p.AccelVelocity : p.Velocity - p.AccelVelocity; p.VelocityLengthSqr = newVel.LengthSquared(); if (accel && p.VelocityLengthSqr > p.MaxSpeedSqr) { newVel = p.Info.Direction * p.MaxSpeed; } else if (!accel && distToMax <= 0) { newVel = Vector3D.Zero; p.VelocityLengthSqr = 0; } } else { newVel = p.Velocity + p.AccelVelocity; p.VelocityLengthSqr = newVel.LengthSquared(); if (p.VelocityLengthSqr > p.MaxSpeedSqr) { newVel = p.Info.Direction * p.MaxSpeed; } } p.Velocity = newVel; } } if (p.State == ProjectileState.OneAndDone) { p.LastPosition = p.Position; var beamEnd = p.Position + (p.Info.Direction * p.Info.MaxTrajectory); p.TravelMagnitude = p.Position - beamEnd; p.Position = beamEnd; } else { if (p.ConstantSpeed || p.VelocityLengthSqr > 0) { p.LastPosition = p.Position; } p.TravelMagnitude = p.Info.Age != 0 ? p.Velocity * StepConst : p.InitalStep; p.Position += p.TravelMagnitude; } p.Info.PrevDistanceTraveled = p.Info.DistanceTraveled; double distChanged; Vector3D.Dot(ref p.Info.Direction, ref p.TravelMagnitude, out distChanged); p.Info.DistanceTraveled += Math.Abs(distChanged); if (p.Info.DistanceTraveled <= 500) { ++p.Info.Ai.ProInMinCacheRange; } if (p.DynamicGuidance) { if (p.PruningProxyId != -1) { var sphere = new BoundingSphereD(p.Position, p.Info.AmmoDef.Const.AreaEffectSize); BoundingBoxD result; BoundingBoxD.CreateFromSphere(ref sphere, out result); Session.ProjectileTree.MoveProxy(p.PruningProxyId, ref result, p.Velocity); } } } if (p.ModelState == EntityState.Exists) { var up = MatrixD.Identity.Up; MatrixD matrix; MatrixD.CreateWorld(ref p.Position, ref p.Info.VisualDir, ref up, out matrix); if (p.Info.AmmoDef.Const.PrimeModel) { p.Info.AvShot.PrimeMatrix = matrix; } if (p.Info.AmmoDef.Const.TriggerModel && p.Info.TriggerGrowthSteps < p.Info.AmmoDef.Const.AreaEffectSize) { p.Info.TriggerMatrix = matrix; } } if (p.State != ProjectileState.OneAndDone) { if (p.Info.Age > p.Info.AmmoDef.Const.MaxLifeTime) { p.DistanceToTravelSqr = p.Info.DistanceTraveled * p.Info.DistanceTraveled; p.EarlyEnd = true; } if (p.Info.DistanceTraveled * p.Info.DistanceTraveled >= p.DistanceToTravelSqr) { p.AtMaxRange = !p.MineSeeking; if (p.FieldTime > 0) { p.FieldTime--; if (p.Info.AmmoDef.Const.IsMine && !p.MineSeeking && !p.MineActivated) { if (p.EnableAv) { p.Info.AvShot.Cloaked = p.Info.AmmoDef.Trajectory.Mines.Cloak; } p.MineSeeking = true; } } } } else { p.AtMaxRange = true; } if (p.Info.AmmoDef.Const.Ewar) { p.RunEwar(); } } }
public void Update() { if (_targetHit) { Kill(); return; } // Update velocity due to gravity Vector3D totalGravity = MyParticlesManager.CalculateGravityInPoint(_position); // Does this get affected by artificial grav? If so... cooooool Vector3D naturalGravity = RailgunCore.GetNaturalGravityAtPoint(_position); Vector3D artificialGravity = totalGravity - naturalGravity; _velocity += (naturalGravity * RailgunCore.MyConfig.NaturalGravityMultiplier + artificialGravity * RailgunCore.MyConfig.ArtificialGravityMultiplier) * _tick; // Update direction if velocity has changed if (!_velocity.Equals(_lastVelocity, 1e-3)) { _direction = Vector3D.Normalize(_velocity); } _lastVelocity = _velocity; // Update position _position += _velocity * _tick; var _toOrigin = _position - _origin; //draw tracer line if (_drawTrail && _currentTracerFadeTicks < _maxTracerFadeTicks) { _lineColor *= _trailColorDecayRatio; _currentTracerFadeTicks++; } if (_toOrigin.LengthSquared() > _maxTrajectory * _maxTrajectory) { MyLog.Default.WriteLine(">> Max range hit"); _targetHit = true; _hitPosition = _position; Kill(); if (_shouldExplode) { CreateExplosion(_position, _direction, _explosionRadius, _explosionDamage); } return; } _checkIntersectionIndex = ++_checkIntersectionIndex % 5; if (_checkIntersectionIndex != 0 && _positionChecked) { return; } // Add current position to trajectory list _trajectoryPoints.Add(_position); var to = _position; //_position + 5.0 * _velocity * _tick; var from = _lastPositionChecked; _positionChecked = true; _lastPositionChecked = _position; IHitInfo hitInfo; bool hit = false; if (Vector3D.DistanceSquared(to, from) > 50 * 50) { // Use faster raycast if ray is long enough hit = MyAPIGateway.Physics.CastLongRay(from, to, out hitInfo, true); } else { hit = MyAPIGateway.Physics.CastRay(from, to, out hitInfo, 0); } if (hit) { MyLog.Default.WriteLine(">> Raycast hit"); _hitPosition = hitInfo.Position + -0.5 * _direction; if ((_hitPosition - _origin).LengthSquared() > _minimumArmDistance * _minimumArmDistance) //only explode if beyond arm distance { if (_shouldExplode) { CreateExplosion(_hitPosition, _direction, _explosionRadius, _explosionDamage); } if (_shouldPenetrate) { GetObjectsToPenetrate(_hitPosition, _hitPosition + _direction * _penetrationRange); } _targetHit = true; Kill(); } else { _targetHit = true; _hitPosition = _position; Kill(); } return; } // implied else var line = new LineD(from, to); MyGamePruningStructure.GetVoxelMapsOverlappingRay(ref line, _voxelOverlap); foreach (var result in _voxelOverlap) { MatrixD matrix; MatrixD matrixInv; Vector3 sizeInMetersHalf; MyPlanet planet = result.Element as MyPlanet; IMyVoxelMap voxelMap = result.Element as IMyVoxelMap; if (planet == null && voxelMap == null) { continue; } if (planet != null) { matrix = planet.WorldMatrix; matrixInv = planet.PositionComp.WorldMatrixInvScaled; sizeInMetersHalf = planet.SizeInMetresHalf; } else { matrix = voxelMap.WorldMatrix; matrixInv = voxelMap.PositionComp.WorldMatrixInvScaled; sizeInMetersHalf = new Vector3(voxelMap.Storage.Size) * 0.5f; } Vector3 localTo; Vector3 localFrom; MyVoxelCoordSystems.WorldPositionToLocalPosition(from, matrix, matrixInv, sizeInMetersHalf, out localFrom); MyVoxelCoordSystems.WorldPositionToLocalPosition(to, matrix, matrixInv, sizeInMetersHalf, out localTo); var localLine = new LineD(localFrom, localTo); if (planet != null && ((IMyStorage)(planet.Storage)).Intersect(ref localLine)) { MyLog.Default.WriteLine(">> Railgun projectile hit planet"); _hitPosition = _position; _targetHit = true; Kill(); return; } // This is very broken //if (voxelMap != null && ((IMyStorage)(voxelMap.Storage)).Intersect(ref localLine)) //{ // MyLog.Default.WriteLine(">> Railgun projectile hit voxel"); // _hitPosition = _position; // _targetHit = true; // Kill(); // return; //} } }