public void Handle(Stabilize message) { _node.LogMessage(message); _commMgr.SendAck(message, message.CorrelationId); var reply = new StabilizeReply(_node.Identity, message.From, message.CorrelationId) { Predecessor = _node.Predecessor, // Take the opportunity to ensure the successor table is up to date. SuccessorTableEntries = _node.SuccessorTable.Entries, }; _node.Log($"Sending {reply.TypeName()} Id:{reply.CorrelationId}"); _commMgr.Send(reply); }
internal void OnMakeTurn() { if (Stabilize == null) { return; } double ftime = Settings.Instance.ActorTurnStabilizeTime; if (ftime <= 0.0) { return; } var now = Plugin.Time; if (now < _LastTurnIsFromAutoTurn) { ftime *= 1.5; } var pcam = PlayerCamera.Instance; var pstate = pcam?.State; if (!(pstate is ThirdPersonState third)) { return; } double x = Math.Abs(third.XRotationFromLastResetPoint); var mult = x / (Math.PI * 0.5); ftime *= mult; var ms = (long)(ftime * 1000.0); if (ms < 33) { return; } Stabilize.AddTweenFrom(ms, FinalResult.Transform.Position); }
private void Stabilize(NodeInfo successorInfo) { // Send a stabilize message to my successor to learn it's predecessor // Stabilize might need to be retried as other nodes will be joining at the same location as it is a seed node. var opId = _node.Config.CorrelationFactory.GetNextCorrelation(); var messageHandler = _node.CreateAwaitAllResponsesHandler(); messageHandler .PerformAction(() => { var msg = new Stabilize(_node.Identity, successorInfo, opId); _node.Log($"Sending {msg.TypeName()} To:{msg.To} Id:{opId}"); _commMgr.Send(msg); }) .AndAwait(opId, (StabilizeReply reply) => { var thisHash = _node.Identity.RoutingHash; var predecessorHash = reply.Predecessor.RoutingHash; var successorHash = successorInfo.RoutingHash; // We need to check the order of the predecessor or the successor before adopting a value // as nodes are racing to join the seed node - our last query may be out of date, but not by much if (thisHash.IsBetween(predecessorHash, successorHash)) { // No ordering change. We can adopt the predecessor values and tell the successor to rectify StabilizeFromSuccessor(reply); } else if (predecessorHash.IsBetween(thisHash, successorHash)) { // another node beat this one to join to the successor, changing the ordering... StabilizeFromPredecessor(reply); } }) .Run(opId); }
private void DoUpdate(CameraUpdate update) { { var wasEnabled = IsEnabled; var isEnabled = CalculateEnabled(update); if (wasEnabled != isEnabled) { if (!isEnabled) { Stack.DisableAll(update); } IsEnabled = isEnabled; if (isEnabled) { OnEnabled(update); } else { OnDisabled(update); } } } if (IsEnabled) { OnUpdating(0); } if (IsEnabled) { if (Stabilize == null || Stabilize.ShouldRecreate(update.Target)) { Stabilize = new CameraStabilize(this, update.Target); } Stabilize?.Update(update.Target.StabilizeRootNode, update.Target.HeadNode, update); } Stack.Check(update); Stack.Update(update); update.Values.Update(Plugin.Time, IsEnabled); Hide.Update(update); { var isFpArms = IsEnabled && update.Values.Show1stPersonArms.CurrentValue >= 0.5; if (isFpArms != WasUsingFirstPersonArms) { WasUsingFirstPersonArms = isFpArms; } } if (IsEnabled) { var mode = update.Values.SkeletonMode.CurrentValue; var wantThird = true; if (mode <= -0.5) { wantThird = !WasUsingFirstPersonArms; } else if (mode >= 0.5) { wantThird = false; } //else wantThird = true; var showFirst = WasUsingFirstPersonArms; var showThird = !(DidCollideLastUpdate && Settings.Instance.HidePlayerWhenColliding == 2); UpdateSkeleton(showFirst, showThird, wantThird); } if (IsEnabled) { if (Stabilize == null || !Stabilize.Get(update.Target.StabilizeRootNode, BaseRoot.Transform)) { BaseRoot.Transform.CopyFrom(update.Target.HeadNode.WorldTransform); } BaseHead.Transform.CopyFrom(update.Target.HeadNode.WorldTransform); CameraResult cur = null; using (cur) { { var posRatio = update.Values.PositionFromHead.CurrentValue; switch (posRatio) { case 0.0: BaseResult.Transform.Position.CopyFrom(BaseRoot.Transform.Position); break; case 1.0: BaseResult.Transform.Position.CopyFrom(BaseHead.Transform.Position); break; default: { var pos = BaseResult.Transform.Position; var rootPos = BaseRoot.Transform.Position; var headPos = BaseHead.Transform.Position; pos.X = (float)((headPos.X - rootPos.X) * posRatio + rootPos.X); pos.Y = (float)((headPos.Y - rootPos.Y) * posRatio + rootPos.Y); pos.Z = (float)((headPos.Z - rootPos.Z) * posRatio + rootPos.Z); break; } } } // Calculate base rotation. { var rotRatio = update.Values.RotationFromHead.CurrentValue; switch (rotRatio) { case 0.0: BaseResult.Transform.Rotation.CopyFrom(BaseRoot.Transform.Rotation); break; case 1.0: BaseResult.Transform.Rotation.CopyFrom(BaseHead.Transform.Rotation); break; default: { var rot = BaseResult.Transform.Rotation; var rootRot = BaseRoot.Transform.Rotation; var headRot = BaseHead.Transform.Rotation; rootRot.Interpolate(headRot, (float)rotRatio, rot); break; } } } cur = BaseResult; // Calculate offset based on object rotation itself. { var root = update.Target.RootNode; if (root != null) { var x = Values.OffsetObjectPositionX.CurrentValue; var y = Values.OffsetObjectPositionY.CurrentValue; var z = Values.OffsetObjectPositionZ.CurrentValue; if (x != 0.0 || y != 0.0 || z != 0.0) { Offset1Result.Transform.Position.CopyFrom(BaseResult.Transform.Position); Offset1Result.Transform.Rotation.CopyFrom(root.WorldTransform.Rotation); ApplyPositionOffset(Offset1Result.Transform, (float)x, (float)y, (float)z, BaseResult.Transform.Position); } } } // Look down offset. if (Default._look_downoffset_ratio > 0.0f || Default._look_downoffset_ratio_leftrightmove > 0.0f) { var ratio = Default._look_downoffset_ratio; var root = update.Target.RootNode; if (root != null) { var x = Settings.Instance.DownOffsetX * ratio; var y = Settings.Instance.DownOffsetY * ratio; var z = Settings.Instance.DownOffsetZ * ratio; y += Settings.Instance.TryFixLeftRightMovementClipping * Default._look_downoffset_ratio_leftrightmove; if (x != 0.0f || y != 0.0f || z != 0.0f) { Offset1Result.Transform.Position.CopyFrom(BaseResult.Transform.Position); Offset1Result.Transform.Rotation.CopyFrom(root.WorldTransform.Rotation); ApplyPositionOffset(Offset1Result.Transform, x, y, z, BaseResult.Transform.Position); } } } // Calculate offset #1. { var rx = (float)Values.Offset1RotationX.CurrentValue; var ry = (float)Values.Offset1RotationY.CurrentValue; var px = (float)Values.Offset1PositionX.CurrentValue; var py = (float)Values.Offset1PositionY.CurrentValue; var pz = (float)Values.Offset1PositionZ.CurrentValue; var hasRot = rx != 0.0f || ry != 0.0f; var hasPos = px != 0.0f || py != 0.0f || pz != 0.0f; if (hasRot || hasPos) { Offset1Result.Transform.CopyFrom(cur.Transform); if (hasRot) { ApplyRotationOffset(Offset1Result.Transform.Rotation, rx, ry, Offset1Result.Transform.Rotation); } if (hasPos) { ApplyPositionOffset(Offset1Result.Transform, px, py, pz, Offset1Result.Transform.Position); } cur = Offset1Result; } } // Calculate input. { var extraX = 0.0f; var extraY = 0.0f; if (LastActorTurnFrames > 0) { LastActorTurnFrames--; extraX = LastActorTurnX; //extraY = this.LastActorTurnY; } var rx = (float)(Values.InputRotationX.CurrentValue + extraX) * (float)Values.InputRotationXMultiplier.CurrentValue; var ry = (float)(Values.InputRotationY.CurrentValue + extraY) * (float)Values.InputRotationYMultiplier.CurrentValue; if (rx != 0.0f || ry != 0.0f) { InputResult.Transform.CopyFrom(cur.Transform); ApplyRotationOffset(InputResult.Transform.Rotation, rx, ry, InputResult.Transform.Rotation); cur = InputResult; } } // Calculate offset #2. { var rx = (float)Values.Offset2RotationX.CurrentValue; var ry = (float)Values.Offset2RotationY.CurrentValue; var px = (float)Values.Offset2PositionX.CurrentValue; var py = (float)Values.Offset2PositionY.CurrentValue; var pz = (float)Values.Offset2PositionZ.CurrentValue; var hasRot = rx != 0.0f || ry != 0.0f; var hasPos = px != 0.0f || py != 0.0f || pz != 0.0f; if (hasRot || hasPos) { Offset2Result.Transform.CopyFrom(cur.Transform); if (hasRot) { ApplyRotationOffset(Offset2Result.Transform.Rotation, rx, ry, Offset2Result.Transform.Rotation); } if (hasPos) { ApplyPositionOffset(Offset2Result.Transform, px, py, pz, Offset2Result.Transform.Position); } cur = Offset2Result; } } // Apply tween from stabilize. { Stabilize?.ApplyTween(cur.Transform.Position, Plugin.Time); } // Apply collision of camera so we don't go inside walls, this can be done within the same transform. { DidCollideLastUpdate = CameraCollision.Apply(update, cur.Transform, cur.Transform.Position); } // Calculate final result. { FinalResult.Transform.CopyFrom(cur.Transform); } } update.GameCameraNode.LocalTransform.CopyFrom(FinalResult.Transform); update.GameCameraNode.Update(0.0f); Hide.UpdateFirstPersonSkeletonRotation(update); if (update.GameCameraState is ThirdPersonState third) { third.Position.CopyFrom(update.GameCameraNode.LocalTransform.Position); } if (WasUsingFirstPersonArms) { UpdateMagicNodePosition(update); } } else { DidCollideLastUpdate = false; } if (IsEnabled) { OnUpdating(1); } if (!IsEnabled && Settings.Instance.ReplaceDefaultCamera && update.GameCameraState.Id == TESCameraStates.FirstPerson && IsGameCameraSwitchControlsEnabled()) { update.GameCamera.EnterThirdPerson(); SetWantState(WantStates.EnabledFromTogglePOV); } FixSensitivityMode = IsEnabled && update.GameCameraState.Id == TESCameraStates.ThirdPerson2 && Memory.ReadUInt8(update.GameCameraState.Address + 0xDC) != 0; }