Пример #1
0
        private void DoUpdate(CameraUpdate update)
        {
            {
                bool wasEnabled = this.IsEnabled;
                bool isEnabled  = this.CalculateEnabled(update);

                if (wasEnabled != isEnabled)
                {
                    if (!isEnabled)
                    {
                        this.Stack.DisableAll(update);
                    }

                    this.IsEnabled = isEnabled;
                    if (isEnabled)
                    {
                        this.OnEnabled(update);
                    }
                    else
                    {
                        this.OnDisabled(update);
                    }
                }
            }

            if (this.IsEnabled)
            {
                this.OnUpdating(0);
            }

            if (this.IsEnabled)
            {
                if (this.Stabilize == null || this.Stabilize.ShouldRecreate(update.Target))
                {
                    this.Stabilize = new CameraStabilize(this, update.Target);
                }

                if (this.Stabilize != null)
                {
                    this.Stabilize.Update(update.Target.StabilizeRootNode, update.Target.HeadNode, update);
                }
            }

            this.Stack.Check(update);
            this.Stack.Update(update);
            update.Values.Update(this.Plugin.Time, this.IsEnabled);
            this.Hide.Update(update);
            {
                bool isFpArms = this.IsEnabled && update.Values.Show1stPersonArms.CurrentValue >= 0.5;
                if (isFpArms != this.WasUsingFirstPersonArms)
                {
                    this.WasUsingFirstPersonArms = isFpArms;
                }
            }

            if (this.IsEnabled)
            {
                double mode      = update.Values.SkeletonMode.CurrentValue;
                bool   wantThird = true;
                if (mode <= -0.5)
                {
                    wantThird = !this.WasUsingFirstPersonArms;
                }
                else if (mode >= 0.5)
                {
                    wantThird = false;
                }
                //else wantThird = true;

                bool showFirst = this.WasUsingFirstPersonArms;
                bool showThird = true;

                if (this.DidCollideLastUpdate && Settings.Instance.HidePlayerWhenColliding == 2)
                {
                    showThird = false;
                }

                this.UpdateSkeleton(showFirst, showThird, wantThird);
            }

            if (this.IsEnabled)
            {
                if (this.Stabilize == null || !this.Stabilize.Get(update.Target.StabilizeRootNode, this.BaseRoot.Transform))
                {
                    this.BaseRoot.Transform.CopyFrom(update.Target.HeadNode.WorldTransform);
                }
                this.BaseHead.Transform.CopyFrom(update.Target.HeadNode.WorldTransform);

                CameraResult cur = null;

                // Calculate base position.
                {
                    double posRatio = update.Values.PositionFromHead.CurrentValue;
                    if (posRatio == 0.0)
                    {
                        this.BaseResult.Transform.Position.CopyFrom(this.BaseRoot.Transform.Position);
                    }
                    else if (posRatio == 1.0)
                    {
                        this.BaseResult.Transform.Position.CopyFrom(this.BaseHead.Transform.Position);
                    }
                    else
                    {
                        var pos     = this.BaseResult.Transform.Position;
                        var rootPos = this.BaseRoot.Transform.Position;
                        var headPos = this.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);
                    }
                }

                // Calculate base rotation.
                {
                    double rotRatio = update.Values.RotationFromHead.CurrentValue;
                    if (rotRatio == 0.0)
                    {
                        this.BaseResult.Transform.Rotation.CopyFrom(this.BaseRoot.Transform.Rotation);
                    }
                    else if (rotRatio == 1.0)
                    {
                        this.BaseResult.Transform.Rotation.CopyFrom(this.BaseHead.Transform.Rotation);
                    }
                    else
                    {
                        var rot     = this.BaseResult.Transform.Rotation;
                        var rootRot = this.BaseRoot.Transform.Rotation;
                        var headRot = this.BaseHead.Transform.Rotation;

                        rootRot.Interpolate(headRot, (float)rotRatio, rot);
                    }
                }

                cur = this.BaseResult;

                // Calculate offset based on object rotation itself.
                {
                    var root = update.Target.RootNode;
                    if (root != null)
                    {
                        double x = this.Values.OffsetObjectPositionX.CurrentValue;
                        double y = this.Values.OffsetObjectPositionY.CurrentValue;
                        double z = this.Values.OffsetObjectPositionZ.CurrentValue;

                        if (x != 0.0 || y != 0.0 || z != 0.0)
                        {
                            this.Offset1Result.Transform.Position.CopyFrom(this.BaseResult.Transform.Position);
                            this.Offset1Result.Transform.Rotation.CopyFrom(root.WorldTransform.Rotation);
                            this.ApplyPositionOffset(this.Offset1Result.Transform, (float)x, (float)y, (float)z, this.BaseResult.Transform.Position);
                        }
                    }
                }

                // Look down offset.
                if (States.Default._look_downoffset_ratio > 0.0f || States.Default._look_downoffset_ratio_leftrightmove > 0.0f)
                {
                    float ratio = States.Default._look_downoffset_ratio;
                    var   root  = update.Target.RootNode;
                    if (root != null)
                    {
                        float x = Settings.Instance.DownOffsetX * ratio;
                        float y = Settings.Instance.DownOffsetY * ratio;
                        float z = Settings.Instance.DownOffsetZ * ratio;

                        y += Settings.Instance.TryFixLeftRightMovementClipping * States.Default._look_downoffset_ratio_leftrightmove;

                        if (x != 0.0f || y != 0.0f || z != 0.0f)
                        {
                            this.Offset1Result.Transform.Position.CopyFrom(this.BaseResult.Transform.Position);
                            this.Offset1Result.Transform.Rotation.CopyFrom(root.WorldTransform.Rotation);
                            this.ApplyPositionOffset(this.Offset1Result.Transform, x, y, z, this.BaseResult.Transform.Position);
                        }
                    }
                }

                // Calculate offset #1.
                {
                    float rx = (float)this.Values.Offset1RotationX.CurrentValue;
                    float ry = (float)this.Values.Offset1RotationY.CurrentValue;
                    float px = (float)this.Values.Offset1PositionX.CurrentValue;
                    float py = (float)this.Values.Offset1PositionY.CurrentValue;
                    float pz = (float)this.Values.Offset1PositionZ.CurrentValue;

                    bool hasRot = rx != 0.0f || ry != 0.0f;
                    bool hasPos = px != 0.0f || py != 0.0f || pz != 0.0f;

                    if (hasRot || hasPos)
                    {
                        this.Offset1Result.Transform.CopyFrom(cur.Transform);
                        if (hasRot)
                        {
                            this.ApplyRotationOffset(this.Offset1Result.Transform.Rotation, rx, ry, this.Offset1Result.Transform.Rotation);
                        }
                        if (hasPos)
                        {
                            this.ApplyPositionOffset(this.Offset1Result.Transform, px, py, pz, this.Offset1Result.Transform.Position);
                        }

                        cur = this.Offset1Result;
                    }
                }

                // Calculate input.
                {
                    float extraX = 0.0f;
                    float extraY = 0.0f;
                    if (this.LastActorTurnFrames > 0)
                    {
                        this.LastActorTurnFrames--;
                        extraX = this.LastActorTurnX;
                        //extraY = this.LastActorTurnY;
                    }

                    float rx = (float)(this.Values.InputRotationX.CurrentValue + extraX) * (float)this.Values.InputRotationXMultiplier.CurrentValue;
                    float ry = (float)(this.Values.InputRotationY.CurrentValue + extraY) * (float)this.Values.InputRotationYMultiplier.CurrentValue;

                    if (rx != 0.0f || ry != 0.0f)
                    {
                        this.InputResult.Transform.CopyFrom(cur.Transform);
                        this.ApplyRotationOffset(this.InputResult.Transform.Rotation, rx, ry, this.InputResult.Transform.Rotation);

                        cur = this.InputResult;
                    }
                }

                // Calculate offset #2.
                {
                    float rx = (float)this.Values.Offset2RotationX.CurrentValue;
                    float ry = (float)this.Values.Offset2RotationY.CurrentValue;
                    float px = (float)this.Values.Offset2PositionX.CurrentValue;
                    float py = (float)this.Values.Offset2PositionY.CurrentValue;
                    float pz = (float)this.Values.Offset2PositionZ.CurrentValue;

                    bool hasRot = rx != 0.0f || ry != 0.0f;
                    bool hasPos = px != 0.0f || py != 0.0f || pz != 0.0f;

                    if (hasRot || hasPos)
                    {
                        this.Offset2Result.Transform.CopyFrom(cur.Transform);
                        if (hasRot)
                        {
                            this.ApplyRotationOffset(this.Offset2Result.Transform.Rotation, rx, ry, this.Offset2Result.Transform.Rotation);
                        }
                        if (hasPos)
                        {
                            this.ApplyPositionOffset(this.Offset2Result.Transform, px, py, pz, this.Offset2Result.Transform.Position);
                        }

                        cur = this.Offset2Result;
                    }
                }

                // Apply tween from stabilize.
                {
                    if (this.Stabilize != null)
                    {
                        this.Stabilize.ApplyTween(cur.Transform.Position, this.Plugin.Time);
                    }
                }

                // Apply collision of camera so we don't go inside walls, this can be done within the same transform.
                {
                    this.DidCollideLastUpdate = CameraCollision.Apply(update, cur.Transform, cur.Transform.Position);
                }

                // Calculate final result.
                {
                    this.FinalResult.Transform.CopyFrom(cur.Transform);
                }

                update.GameCameraNode.LocalTransform.CopyFrom(this.FinalResult.Transform);
                update.GameCameraNode.Update(0.0f);

                this.Hide.UpdateFirstPersonSkeletonRotation(update);

                var third = update.GameCameraState.As <ThirdPersonState>();
                if (third != null)
                {
                    third.Position.CopyFrom(update.GameCameraNode.LocalTransform.Position);
                }

                if (this.WasUsingFirstPersonArms)
                {
                    this.UpdateMagicNodePosition(update);
                }
            }
            else
            {
                this.DidCollideLastUpdate = false;
            }

            if (this.IsEnabled)
            {
                this.OnUpdating(1);
            }

            if (!this.IsEnabled && Settings.Instance.ReplaceDefaultCamera && update.GameCameraState.Id == TESCameraStates.FirstPerson && this.IsGameCameraSwitchControlsEnabled())
            {
                update.GameCamera.EnterThirdPerson();
                this.SetWantState(WantStates.EnabledFromTogglePOV);
            }

            this.FixSensitivityMode = this.IsEnabled && update.GameCameraState.Id == TESCameraStates.ThirdPerson2 && Memory.ReadUInt8(update.GameCameraState.Address + 0xDC) != 0;
        }
        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;
        }