public void AddTarget(float x, float y, float beatTime, float beatLength = 1, TargetVelocity velocity = TargetVelocity.Standard, TargetHandType handType = TargetHandType.Either, TargetBehavior behavior = TargetBehavior.Standard) { // Add to timeline var timelineClone = Instantiate(timelineNotePrefab, timelineNotes); timelineClone.transform.localPosition = new Vector3(beatTime, 0, 0); // Add to grid var gridClone = Instantiate(gridNotePrefab, gridNotes); gridClone.transform.localPosition = new Vector3(x, y, beatTime); gridClone.timelineTarget = timelineClone; timelineClone.timelineTarget = timelineClone; gridClone.gridTarget = gridClone; timelineClone.gridTarget = gridClone; gridClone.SetHandType(handType); gridClone.SetBehavior(behavior); gridClone.SetBeatLength(beatLength); gridClone.SetVelocity(velocity); notes.Add(gridClone); UpdateTrail(); }
private void CalculateTargetVelocity() { TargetVelocity = MoveInput; TargetVelocity = TargetVelocity.Rotated(Agent.Body._rotation.y, Agent.Body._rotation.x); TargetVelocity *= Speed; TargetVelocityReached = false; }
public TargetData(Target target) { x = target.gridTargetIcon.transform.localPosition.x; y = target.gridTargetIcon.transform.localPosition.y; beatTime = target.gridTargetIcon.transform.localPosition.z; beatLength = target.beatLength; velocity = target.velocity; handType = target.handType; behavior = target.behavior; }
public TargetData(Cue cue, float offset) { Vector2 pos = NotePosCalc.PitchToPos(cue); x = pos.x; y = pos.y; beatTime = (cue.tick - offset) / 480f; beatLength = cue.tickLength; velocity = cue.velocity; handType = cue.handType; behavior = cue.behavior; }
protected override YAMLMappingNode ExportYAMLRoot(IExportContainer container) { YAMLMappingNode node = base.ExportYAMLRoot(container); node.Add(ConnectedBodyName, ConnectedBody.ExportYAML(container)); node.Add(AnchorName, Anchor.ExportYAML(container)); node.Add(AxisName, Axis.ExportYAML(container)); node.Add(AutoConfigureConnectedAnchorName, AutoConfigureConnectedAnchor); node.Add(ConnectedAnchorName, ConnectedAnchor.ExportYAML(container)); node.AddSerializedVersion(GetSerializedVersion(container.ExportVersion)); node.Add(SecondaryAxisName, SecondaryAxis.ExportYAML(container)); node.Add(XMotionName, (int)XMotion); node.Add(YMotionName, (int)YMotion); node.Add(ZMotionName, (int)ZMotion); node.Add(AngularXMotionName, (int)AngularXMotion); node.Add(AngularYMotionName, (int)AngularYMotion); node.Add(AngularZMotionName, (int)AngularZMotion); node.Add(LinearLimitSpringName, LinearLimitSpring.ExportYAML(container)); node.Add(LinearLimitName, LinearLimit.ExportYAML(container)); node.Add(AngularXLimitSpringName, AngularXLimitSpring.ExportYAML(container)); node.Add(LowAngularXLimitName, LowAngularXLimit.ExportYAML(container)); node.Add(HighAngularXLimitName, HighAngularXLimit.ExportYAML(container)); node.Add(AngularYZLimitSpringName, AngularYZLimitSpring.ExportYAML(container)); node.Add(AngularYLimitName, AngularYLimit.ExportYAML(container)); node.Add(AngularZLimitName, AngularZLimit.ExportYAML(container)); node.Add(TargetPositionName, TargetPosition.ExportYAML(container)); node.Add(TargetVelocityName, TargetVelocity.ExportYAML(container)); node.Add(XDriveName, XDrive.ExportYAML(container)); node.Add(YDriveName, YDrive.ExportYAML(container)); node.Add(ZDriveName, ZDrive.ExportYAML(container)); node.Add(TargetRotationName, TargetRotation.ExportYAML(container)); node.Add(TargetAngularVelocityName, TargetAngularVelocity.ExportYAML(container)); node.Add(RotationDriveModeName, (int)RotationDriveMode); node.Add(AngularXDriveName, AngularXDrive.ExportYAML(container)); node.Add(AngularYZDriveName, AngularYZDrive.ExportYAML(container)); node.Add(SlerpDriveName, SlerpDrive.ExportYAML(container)); node.Add(ProjectionModeName, (int)ProjectionMode); node.Add(ProjectionDistanceName, ProjectionDistance); node.Add(ProjectionAngleName, ProjectionAngle); node.Add(ConfiguredInWorldSpaceName, ConfiguredInWorldSpace); node.Add(SwapBodiesName, SwapBodies); node.Add(BreakForceName, BreakForce); node.Add(BreakTorqueName, BreakTorque); node.Add(EnableCollisionName, EnableCollision); node.Add(EnablePreprocessingName, EnablePreprocessing); node.Add(MassScaleName, MassScale); node.Add(ConnectedMassScaleName, ConnectedMassScale); return(node); }
public void Update(ComponentizedEntity entity, IGameContext gameContext, IUpdateContext updateContext) { if (!Enabled) { return; } if (_jitterWorld != _physicsEngine.GetInternalPhysicsWorld()) { // TODO: Deregister rigid bodies from old world. if (_jitterWorld != null && _physicsControllerConstraint != null) { _jitterWorld.RemoveConstraint(_physicsControllerConstraint); _physicsControllerConstraint = null; } _jitterWorld = _physicsEngine.GetInternalPhysicsWorld(); } if (_physicalComponent.RigidBodies.Length > 0 && _physicalComponent.RigidBodies[0] != _rigidBody) { if (_physicsControllerConstraint != null) { _jitterWorld.RemoveConstraint(_physicsControllerConstraint); _physicsControllerConstraint = null; } } if (_physicalComponent.RigidBodies.Length > 0) { if (_physicsControllerConstraint == null) { _physicsControllerConstraint = new PhysicsControllerConstraint( _jitterWorld, _physicalComponent.RigidBodies[0]); _jitterWorld.AddConstraint(_physicsControllerConstraint); } _physicsControllerConstraint.TargetVelocity = TargetVelocity.ToJitterVector(); _physicsControllerConstraint.TryJump = TryJump; _physicsControllerConstraint.JumpVelocity = JumpVelocity; _physicsControllerConstraint.Stiffness = Stiffness; if (TargetVelocity.LengthSquared() > 0f) { // Wake up the rigid body. _physicalComponent.RigidBodies[0].IsActive = true; } } }
private void SetHitsoundAction(TargetVelocity velocity) { targetSetHitsoundIntents = new List <TargetSetHitsoundIntent>(); timeline.selectedNotes.ForEach(target => { var intent = new TargetSetHitsoundIntent(); intent.target = target.data; intent.startingVelocity = target.data.velocity; intent.newVelocity = velocity; targetSetHitsoundIntents.Add(intent); }); timeline.SetTargetHitsounds(targetSetHitsoundIntents); }
public static void CalculateChainNotes(TargetData data) { if (data.behavior != TargetBehavior.NR_Pathbuilder) { return; } if (data.pathBuilderData.createdNotes) { data.pathBuilderData.generatedNotes.ForEach(t => { timeline.DeleteTargetFromAction(t); }); data.pathBuilderData.createdNotes = false; } data.pathBuilderData.generatedNotes = new List <TargetData>(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////// WARNING! ///////// ///////// Chainging this calculation breaks backwards compatibility with saves of older NotReaper versions! ///////// ///////// Make sure to update NRCueData.Version, and handle an upgrade path! ///////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Generate first note at the start TargetData firstData = new TargetData(); firstData.behavior = data.pathBuilderData.behavior; firstData.velocity = data.pathBuilderData.velocity; firstData.handType = data.pathBuilderData.handType; firstData.beatTime = data.beatTime; firstData.position = data.position; data.pathBuilderData.generatedNotes.Add(firstData); //We increment as if all these values were for 1/4 notes over 4 beats, makes the ui much better float quarterIncrConvert = (4.0f / data.pathBuilderData.interval) * (480.0f * 4.0f / data.beatLength); //Generate new notes Vector2 currentPos = data.position; Vector2 currentDir = new Vector2(Mathf.Sin(data.pathBuilderData.initialAngle * Mathf.Deg2Rad), Mathf.Cos(data.pathBuilderData.initialAngle * Mathf.Deg2Rad)); float currentAngle = (data.pathBuilderData.angle / 4) * quarterIncrConvert; float currentStep = data.pathBuilderData.stepDistance * quarterIncrConvert; TargetBehavior generatedBehavior = data.pathBuilderData.behavior; if (generatedBehavior == TargetBehavior.ChainStart) { generatedBehavior = TargetBehavior.Chain; } TargetVelocity generatedVelocity = data.pathBuilderData.velocity; if (generatedVelocity == TargetVelocity.ChainStart) { generatedVelocity = TargetVelocity.Chain; } for (int i = 1; i <= (data.beatLength / 480) * (data.pathBuilderData.interval / 4.0f); ++i) { currentPos += currentDir * currentStep; currentDir = currentDir.Rotate(currentAngle); currentAngle += (data.pathBuilderData.angleIncrement / 4) * quarterIncrConvert; currentStep += data.pathBuilderData.stepIncrement * quarterIncrConvert; TargetData newData = new TargetData(); newData.behavior = generatedBehavior; newData.velocity = generatedVelocity; newData.handType = data.pathBuilderData.handType; newData.beatTime = data.beatTime + i * (4.0f / data.pathBuilderData.interval); newData.position = currentPos; data.pathBuilderData.generatedNotes.Add(newData); } data.pathBuilderData.OnFinishRecalculate(); }
public void SetVelocity(TargetVelocity velocity) { gridTarget.velocity = velocity; }
private void UpdateAutoPilot(float deltaTime) { if (controlledSub == null) { return; } if (posToMaintain != null) { Vector2 steeringVel = GetSteeringVelocity((Vector2)posToMaintain, 10.0f); TargetVelocity = Vector2.Lerp(TargetVelocity, steeringVel, AutoPilotSteeringLerp); showIceSpireWarning = false; return; } autopilotRayCastTimer -= deltaTime; autopilotRecalculatePathTimer -= deltaTime; if (autopilotRecalculatePathTimer <= 0.0f) { //periodically recalculate the path in case the sub ends up to a position //where it can't keep traversing the initially calculated path UpdatePath(); autopilotRecalculatePathTimer = RecalculatePathInterval; } if (steeringPath == null) { showIceSpireWarning = false; return; } steeringPath.CheckProgress(ConvertUnits.ToSimUnits(controlledSub.WorldPosition), 10.0f); connectedSubUpdateTimer -= deltaTime; if (connectedSubUpdateTimer <= 0.0f) { connectedSubs.Clear(); connectedSubs = controlledSub?.GetConnectedSubs(); connectedSubUpdateTimer = ConnectedSubUpdateInterval; } if (autopilotRayCastTimer <= 0.0f && steeringPath.NextNode != null) { Vector2 diff = ConvertUnits.ToSimUnits(steeringPath.NextNode.Position - controlledSub.WorldPosition); //if the node is close enough, check if it's visible float lengthSqr = diff.LengthSquared(); if (lengthSqr > 0.001f && lengthSqr < AutopilotMinDistToPathNode * AutopilotMinDistToPathNode) { diff = Vector2.Normalize(diff); //check if the next waypoint is visible from all corners of the sub //(i.e. if we can navigate directly towards it or if there's obstacles in the way) bool nextVisible = true; for (int x = -1; x < 2; x += 2) { for (int y = -1; y < 2; y += 2) { Vector2 cornerPos = new Vector2(controlledSub.Borders.Width * x, controlledSub.Borders.Height * y) / 2.0f; cornerPos = ConvertUnits.ToSimUnits(cornerPos * 1.1f + controlledSub.WorldPosition); float dist = Vector2.Distance(cornerPos, steeringPath.NextNode.SimPosition); if (Submarine.PickBody(cornerPos, cornerPos + diff * dist, null, Physics.CollisionLevel) == null) { continue; } nextVisible = false; x = 2; y = 2; } } if (nextVisible) { steeringPath.SkipToNextNode(); } } autopilotRayCastTimer = AutopilotRayCastInterval; } Vector2 newVelocity = Vector2.Zero; if (steeringPath.CurrentNode != null) { newVelocity = GetSteeringVelocity(steeringPath.CurrentNode.WorldPosition, 2.0f); } Vector2 avoidDist = new Vector2( Math.Max(1000.0f * Math.Abs(controlledSub.Velocity.X), controlledSub.Borders.Width * 0.75f), Math.Max(1000.0f * Math.Abs(controlledSub.Velocity.Y), controlledSub.Borders.Height * 0.75f)); float avoidRadius = avoidDist.Length(); float damagingWallAvoidRadius = MathHelper.Clamp(avoidRadius * 1.5f, 5000.0f, 10000.0f); Vector2 newAvoidStrength = Vector2.Zero; debugDrawObstacles.Clear(); //steer away from nearby walls showIceSpireWarning = false; var closeCells = Level.Loaded.GetCells(controlledSub.WorldPosition, 4); foreach (VoronoiCell cell in closeCells) { if (cell.DoesDamage) { foreach (GraphEdge edge in cell.Edges) { Vector2 closestPoint = MathUtils.GetClosestPointOnLineSegment(edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, controlledSub.WorldPosition); Vector2 diff = closestPoint - controlledSub.WorldPosition; float dist = diff.Length() - Math.Max(controlledSub.Borders.Width, controlledSub.Borders.Height) / 2; if (dist > damagingWallAvoidRadius) { continue; } Vector2 normalizedDiff = Vector2.Normalize(diff); float dot = Vector2.Dot(normalizedDiff, controlledSub.Velocity); float avoidStrength = MathHelper.Clamp(MathHelper.Lerp(1.0f, 0.0f, dist / damagingWallAvoidRadius - dot), 0.0f, 1.0f); Vector2 avoid = -normalizedDiff * avoidStrength; newAvoidStrength += avoid; debugDrawObstacles.Add(new ObstacleDebugInfo(edge, edge.Center, 1.0f, avoid, cell.Translation)); if (dot > 0.0f) { showIceSpireWarning = true; } } continue; } foreach (GraphEdge edge in cell.Edges) { if (MathUtils.GetLineIntersection(edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, controlledSub.WorldPosition, cell.Center, out Vector2 intersection)) { Vector2 diff = controlledSub.WorldPosition - intersection; //far enough -> ignore if (Math.Abs(diff.X) > avoidDist.X && Math.Abs(diff.Y) > avoidDist.Y) { debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, 0.0f, Vector2.Zero, Vector2.Zero)); continue; } if (diff.LengthSquared() < 1.0f) { diff = Vector2.UnitY; } Vector2 normalizedDiff = Vector2.Normalize(diff); float dot = controlledSub.Velocity == Vector2.Zero ? 0.0f : Vector2.Dot(controlledSub.Velocity, -normalizedDiff); //not heading towards the wall -> ignore if (dot < 1.0) { debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, dot, Vector2.Zero, cell.Translation)); continue; } Vector2 change = (normalizedDiff * Math.Max((avoidRadius - diff.Length()), 0.0f)) / avoidRadius; if (change.LengthSquared() < 0.001f) { continue; } newAvoidStrength += change * (dot - 1.0f); debugDrawObstacles.Add(new ObstacleDebugInfo(edge, intersection, dot - 1.0f, change * (dot - 1.0f), cell.Translation)); } } } avoidStrength = Vector2.Lerp(avoidStrength, newAvoidStrength, deltaTime * 10.0f); TargetVelocity = Vector2.Lerp(TargetVelocity, newVelocity + avoidStrength * 100.0f, AutoPilotSteeringLerp); //steer away from other subs foreach (Submarine sub in Submarine.Loaded) { if (sub == controlledSub || connectedSubs.Contains(sub)) { continue; } Point sizeSum = controlledSub.Borders.Size + sub.Borders.Size; Vector2 minDist = sizeSum.ToVector2() / 2; Vector2 diff = controlledSub.WorldPosition - sub.WorldPosition; float xDist = Math.Abs(diff.X); float yDist = Math.Abs(diff.Y); Vector2 maxAvoidDistance = minDist * 2; if (xDist > maxAvoidDistance.X || yDist > maxAvoidDistance.Y) { //far enough -> ignore continue; } float dot = controlledSub.Velocity == Vector2.Zero ? 0.0f : Vector2.Dot(Vector2.Normalize(controlledSub.Velocity), -diff); if (dot < 0.0f) { //heading away -> ignore continue; } float distanceFactor = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(maxAvoidDistance.X + maxAvoidDistance.Y, minDist.X + minDist.Y, xDist + yDist)); float velocityFactor = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, 3, controlledSub.Velocity.Length())); TargetVelocity += 100 * Vector2.Normalize(diff) * distanceFactor * velocityFactor; } //clamp velocity magnitude to 100.0f (Is this required? The X and Y components are clamped in the property setter) float velMagnitude = TargetVelocity.Length(); if (velMagnitude > 100.0f) { TargetVelocity *= 100.0f / velMagnitude; } #if CLIENT HintManager.OnAutoPilotPathUpdated(this); #endif }
public override void Update(float deltaTime, Camera cam) { if (!searchedConnectedDockingPort) { FindConnectedDockingPort(); } networkUpdateTimer -= deltaTime; if (unsentChanges) { if (networkUpdateTimer <= 0.0f) { #if CLIENT if (GameMain.Client != null) { item.CreateClientEvent(this); correctionTimer = CorrectionDelay; } else #endif #if SERVER if (GameMain.Server != null) { item.CreateServerEvent(this); } #endif networkUpdateTimer = 0.1f; unsentChanges = false; } } controlledSub = item.Submarine; var sonar = item.GetComponent <Sonar>(); if (sonar != null && sonar.UseTransducers) { controlledSub = sonar.ConnectedTransducers.Any() ? sonar.ConnectedTransducers.First().Item.Submarine : null; } currPowerConsumption = powerConsumption; if (Voltage < MinVoltage) { return; } if (user != null && user.Removed) { user = null; } ApplyStatusEffects(ActionType.OnActive, deltaTime, null); float userSkill = 0.0f; if (user != null && controlledSub != null && (user.SelectedConstruction == item || item.linkedTo.Contains(user.SelectedConstruction))) { userSkill = user.GetSkillLevel("helm") / 100.0f; } if (AutoPilot) { UpdateAutoPilot(deltaTime); TargetVelocity = TargetVelocity.ClampLength(MathHelper.Lerp(AutoPilotMaxSpeed, AIPilotMaxSpeed, userSkill) * 100.0f); } else { showIceSpireWarning = false; if (user != null && user.Info != null && user.SelectedConstruction == item && controlledSub != null && controlledSub.Velocity.LengthSquared() > 0.01f) { IncreaseSkillLevel(user, deltaTime); } Vector2 velocityDiff = steeringInput - targetVelocity; if (velocityDiff != Vector2.Zero) { if (steeringAdjustSpeed >= 0.99f) { TargetVelocity = steeringInput; } else { float steeringChange = 1.0f / (1.0f - steeringAdjustSpeed); steeringChange *= steeringChange * 10.0f; TargetVelocity += Vector2.Normalize(velocityDiff) * Math.Min(steeringChange * deltaTime, velocityDiff.Length()); } } } float velX = targetVelocity.X; if (controlledSub != null && controlledSub.FlippedX) { velX *= -1; } item.SendSignal(new Signal(velX.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_x_out"); float velY = MathHelper.Lerp((neutralBallastLevel * 100 - 50) * 2, -100 * Math.Sign(targetVelocity.Y), Math.Abs(targetVelocity.Y) / 100.0f); item.SendSignal(new Signal(velY.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_y_out"); }
public override void DoAction(Timeline timeline) { oldBehavior = new List <TargetBehavior>(); affectedTargets.ForEach(targetData => { TargetVelocity velocity = TargetVelocity.None; if (newBehavior == TargetBehavior.ChainStart) { velocity = TargetVelocity.ChainStart; } else if (newBehavior == TargetBehavior.Chain) { velocity = TargetVelocity.Chain; } else if (newBehavior == TargetBehavior.Melee) { velocity = TargetVelocity.Melee; } else if (newBehavior == TargetBehavior.Mine) { velocity = TargetVelocity.Mine; } else if (newBehavior == TargetBehavior.Standard || newBehavior == TargetBehavior.Hold || newBehavior == TargetBehavior.Horizontal || newBehavior == TargetBehavior.Vertical) { velocity = TargetVelocity.Standard; } //Path notes and regular notes both use the same beat length oldBeatLength.Add(targetData.beatLength); if (targetData.behavior == TargetBehavior.NR_Pathbuilder) { oldBehavior.Add(targetData.pathBuilderData.behavior); oldHandTypes.Add(targetData.pathBuilderData.handType); oldVelocities.Add(targetData.pathBuilderData.velocity); targetData.pathBuilderData.behavior = newBehavior; if (velocity != TargetVelocity.None) { targetData.pathBuilderData.velocity = velocity; } //Fix hand type when going to melee if (newBehavior == TargetBehavior.Melee) { targetData.pathBuilderData.handType = TargetHandType.Either; } //Fixup hand type when coming from melee if (oldBehavior.Last() == TargetBehavior.Melee) { targetData.pathBuilderData.handType = targetData.handType; } ChainBuilder.ChainBuilder.GenerateChainNotes(targetData); } else { oldBehavior.Add(targetData.behavior); oldHandTypes.Add(targetData.handType); oldVelocities.Add(targetData.velocity); targetData.behavior = newBehavior; if (velocity != TargetVelocity.None) { targetData.velocity = velocity; } //Fix hand type when going to melee if (newBehavior == TargetBehavior.Melee) { targetData.handType = TargetHandType.Either; } //Fixup hand type when coming from melee if (oldBehavior.Last() == TargetBehavior.Melee) { targetData.handType = TargetHandType.Left; } if (TargetData.BehaviorSupportsBeatLength(newBehavior) && targetData.beatLength < Constants.QuarterNoteDuration) { targetData.beatLength = Constants.QuarterNoteDuration; } } }); }
public void SetVelocity(TargetVelocity velocity) { selectedVelocity = velocity; }
public void AddTarget(float x, float y, float beatTime, float beatLength = 0.25f, TargetVelocity velocity = TargetVelocity.Standard, TargetHandType handType = TargetHandType.Either, TargetBehavior behavior = TargetBehavior.Standard, bool userAdded = false) { // Add to timeline var timelineClone = Instantiate(timelineNotePrefab, timelineNotes); timelineClone.transform.localPosition = new Vector3(beatTime, 0, 0); // Add to grid var gridClone = Instantiate(gridNotePrefab, gridNotes); gridClone.GetComponentInChildren <HoldController>().length.text = "" + beatLength; gridClone.transform.localPosition = new Vector3(x, y, beatTime); gridClone.timelineTarget = timelineClone; timelineClone.timelineTarget = timelineClone; gridClone.gridTarget = gridClone; timelineClone.gridTarget = gridClone; //set velocity if (userAdded) { switch (CurrentSound) { case OptionsMenu.DropdownToVelocity.Standard: gridClone.velocity = TargetVelocity.Standard; break; case OptionsMenu.DropdownToVelocity.Snare: gridClone.velocity = TargetVelocity.Snare; break; case OptionsMenu.DropdownToVelocity.Percussion: gridClone.velocity = TargetVelocity.Percussion; break; case OptionsMenu.DropdownToVelocity.ChainStart: gridClone.velocity = TargetVelocity.ChainStart; break; case OptionsMenu.DropdownToVelocity.Chain: gridClone.velocity = TargetVelocity.Chain; break; case OptionsMenu.DropdownToVelocity.Melee: gridClone.velocity = TargetVelocity.Melee; break; default: gridClone.velocity = velocity; break; } } else { gridClone.SetVelocity(velocity); } gridClone.SetHandType(handType); gridClone.SetBehavior(behavior); if (gridClone.behavior == TargetBehavior.Hold) { gridClone.SetBeatLength(beatLength); } else { gridClone.SetBeatLength(0.25f); } notes.Add(gridClone); notesTimeline.Add(timelineClone); orderedNotes = notes.OrderBy(v => v.transform.position.z).ToList(); UpdateTrail(); UpdateChainConnectors(); }
public override void Update(float deltaTime, Camera cam) { if (!searchedConnectedDockingPort) { FindConnectedDockingPort(); } networkUpdateTimer -= deltaTime; if (unsentChanges) { if (networkUpdateTimer <= 0.0f) { #if CLIENT if (GameMain.Client != null) { item.CreateClientEvent(this); correctionTimer = CorrectionDelay; } else #endif #if SERVER if (GameMain.Server != null) { item.CreateServerEvent(this); } #endif networkUpdateTimer = 0.1f; unsentChanges = false; } } controlledSub = item.Submarine; var sonar = item.GetComponent <Sonar>(); if (sonar != null && sonar.UseTransducers) { controlledSub = sonar.ConnectedTransducers.Any() ? sonar.ConnectedTransducers.First().Item.Submarine : null; } currPowerConsumption = powerConsumption; if (Voltage < MinVoltage) { return; } if (user != null && user.Removed) { user = null; } ApplyStatusEffects(ActionType.OnActive, deltaTime, null); float userSkill = 0.0f; if (user != null && controlledSub != null && (user.SelectedConstruction == item || item.linkedTo.Contains(user.SelectedConstruction))) { userSkill = user.GetSkillLevel("helm") / 100.0f; } // override autopilot pathing while the AI rams, and go full speed ahead if (AIRamTimer > 0f) { AIRamTimer -= deltaTime; TargetVelocity = GetSteeringVelocity(AITacticalTarget, 0f); } else if (AutoPilot) { UpdateAutoPilot(deltaTime); float throttle = 1.0f; if (controlledSub != null) { //if the sub is heading in the correct direction, throttle the speed according to the user's skill //if it's e.g. sinking due to extra water, don't throttle, but allow emptying up the ballast completely throttle = MathHelper.Clamp(Vector2.Dot(controlledSub.Velocity, TargetVelocity) / 100.0f, 0.0f, 1.0f); } float maxSpeed = MathHelper.Lerp(AutoPilotMaxSpeed, AIPilotMaxSpeed, userSkill) * 100.0f; TargetVelocity = TargetVelocity.ClampLength(MathHelper.Lerp(100.0f, maxSpeed, throttle)); } else { showIceSpireWarning = false; if (user != null && user.Info != null && user.SelectedConstruction == item && controlledSub != null && controlledSub.Velocity.LengthSquared() > 0.01f) { IncreaseSkillLevel(user, deltaTime); } Vector2 velocityDiff = steeringInput - targetVelocity; if (velocityDiff != Vector2.Zero) { if (steeringAdjustSpeed >= 0.99f) { TargetVelocity = steeringInput; } else { float steeringChange = 1.0f / (1.0f - steeringAdjustSpeed); steeringChange *= steeringChange * 10.0f; TargetVelocity += Vector2.Normalize(velocityDiff) * Math.Min(steeringChange * deltaTime, velocityDiff.Length()); } } } float velX = targetVelocity.X; if (controlledSub != null && controlledSub.FlippedX) { velX *= -1; } item.SendSignal(new Signal(velX.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_x_out"); float velY = MathHelper.Lerp((neutralBallastLevel * 100 - 50) * 2, -100 * Math.Sign(targetVelocity.Y), Math.Abs(targetVelocity.Y) / 100.0f); item.SendSignal(new Signal(velY.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_y_out"); // converts the controlled sub's velocity to km/h and sends it. if (controlledSub is { } sub) { item.SendSignal(new Signal((ConvertUnits.ToDisplayUnits(sub.Velocity.X * Physics.DisplayToRealWorldRatio) * 3.6f).ToString("0.0000", CultureInfo.InvariantCulture), sender: user), "current_velocity_x"); item.SendSignal(new Signal((ConvertUnits.ToDisplayUnits(sub.Velocity.Y * Physics.DisplayToRealWorldRatio) * -3.6f).ToString("0.0000", CultureInfo.InvariantCulture), sender: user), "current_velocity_y"); item.SendSignal(new Signal((sub.WorldPosition.X * Physics.DisplayToRealWorldRatio).ToString("0.0000", CultureInfo.InvariantCulture), sender: user), "current_position_x"); item.SendSignal(new Signal(sub.RealWorldDepth.ToString("0.0000", CultureInfo.InvariantCulture), sender: user), "current_position_y"); } // if our tactical AI pilot has left, revert back to maintaining position if (navigateTactically && (user == null || user.SelectedConstruction != item)) { navigateTactically = false; AIRamTimer = 0f; SetMaintainPosition(); } }
public void SetVelocity(TargetVelocity newVel) { velocity = newVel; gridTargetIcon.velocity = velocity; timelineTargetIcon.velocity = velocity; }