示例#1
0
        private void _Initialize()
        {
            this.Settings = new Settings();
            this.Settings.Load();

            this.Timer = new NetScriptFramework.Tools.Timer();
            this.Timer.Start();

            Events.OnFrame.Register(e =>
            {
                long now  = this.Timer.Time;
                long diff = 0;
                if (this.LastUpdateTime.HasValue)
                {
                    diff = now - this.LastUpdateTime.Value;
                }
                this.LastUpdateTime = now;

                if (this.State != null)
                {
                    this.State.Update((float)diff / 1000.0f, (float)now / 1000.0f);
                }
            });

            Events.OnMainMenu.Register(e =>
            {
                this.State = new BlinkState(this);
                this.State.Initialize();
            });

            Events.OnMagicCasterFire.Register(e =>
            {
                if (this.State == null)
                {
                    return;
                }

                var item  = e.Item;
                var spell = this.Settings.SpellForm;
                if (item == null || spell == null || !spell.Equals(item))
                {
                    return;
                }

                var casterBase = e.Caster;
                if (casterBase == null)
                {
                    return;
                }

                var casterActor = casterBase.As <ActorMagicCaster>();
                Actor owner     = null;
                if (casterActor == null || (owner = casterActor.Owner) == null || !owner.IsPlayer)
                {
                    return;
                }

                this.State.Fire(true);
            });

            Events.OnUpdateCamera.Register(e =>
            {
                if (this.State == null)
                {
                    return;
                }

                float amt = this.State.GetDistortionEffect();
                if (amt == 0.0f)
                {
                    return;
                }

                var cameraBase = e.Camera;
                if (cameraBase == null)
                {
                    return;
                }

                var playerCamera = cameraBase.As <PlayerCamera>();
                if (playerCamera == null)
                {
                    return;
                }

                var node = playerCamera.Node;
                if (node == null)
                {
                    return;
                }

                if (amt > 0.0f)
                {
                    node.LocalTransform.Rotation[2, 2] *= 1.0f + amt;
                }
                else
                {
                    node.LocalTransform.Rotation[2, 2] /= 1.0f - amt;
                }
                node.Update(0.0f);
            }, 100000);
        }
        private void init()
        {
            this.Timer = new NetScriptFramework.Tools.Timer();
            this.Timer.Start();

            this.Settings = new Settings();
            this.Settings.Load();

            this.PlayerControls_IsCamSwitchControlsEnabled = this.PrepareFunction("player camera switch controls check", 41263, 0);
            this.NiNode_ctor            = this.PrepareFunction("ninode ctor", 68936, 0);
            this.MagicNodeArt1          = this.PrepareFunction("magic node art 1", 33403, 0x6F);
            this.MagicNodeArt2          = this.PrepareFunction("magic node art 2", 33391, 0x64);
            this.MagicNodeArt3          = this.PrepareFunction("magic node art 3", 33375, 0xF5);
            this.MagicNodeArt4          = this.PrepareFunction("magic node art 4", 33683, 0x63);
            this.ActorTurnX             = this.PrepareFunction("actor turn x", 36603, 0);
            this.ActorTurnZ             = this.PrepareFunction("actor turn z", 36250, 0);
            this.SwitchSkeleton         = this.PrepareFunction("switch skeleton", 39401, 0);
            this.Actor_GetMoveDirection = this.PrepareFunction("actor move direction", 36935, 0);

            if (this.Settings.AllowLookDownAlot)
            {
                var allowLookDownMore         = NetScriptFramework.Main.GameInfo.GetAddressOf(49978, 0xBA, 0, "F3 0F 5C 15");
                var allowLookDownDisableCheck = NetScriptFramework.Main.GameInfo.GetAddressOf(49978, 0x100, 0, "0F 57 C9 0F 2F C1 73");
                var skipSetAddr = allowLookDownDisableCheck + 0x20;
                if (!NetScriptFramework.Memory.VerifyBytes(skipSetAddr, "48 8B 44 24 40"))
                {
                    throw new ArgumentException("Failed to verify bytes for disabling down look check!");
                }

                var allowMoveDownDisableCheck = NetScriptFramework.Main.GameInfo.GetAddressOf(36602, 0xE4, 0, "44 0F 2F C7");

                Memory.WriteHook(new HookParameters()
                {
                    Address       = allowLookDownMore,
                    ReplaceLength = 8,
                    IncludeLength = 0,
                    Before        = ctx =>
                    {
                        float half = (float)(Math.PI * 0.5);
                        if (this.CameraMain != null && this.CameraMain.IsEnabled)
                        {
                            ctx.XMM2f -= half * 1.5f;
                        }
                        else
                        {
                            ctx.XMM2f -= half;
                        }
                    }
                });

                Memory.WriteHook(new HookParameters()
                {
                    Address       = allowLookDownDisableCheck,
                    ReplaceLength = 8,
                    IncludeLength = 0,
                    Before        = ctx =>
                    {
                        float angle   = ctx.XMM0f;
                        float allowed = 0.0f;
                        if (this.CameraMain != null && this.CameraMain.IsEnabled)
                        {
                            allowed = -(float)(Math.PI / 4.0);
                        }

                        if (angle <= allowed)
                        {
                            ctx.IP = skipSetAddr;
                        }
                    }
                });

                Memory.WriteHook(new HookParameters()
                {
                    Address       = allowMoveDownDisableCheck,
                    IncludeLength = 0,
                    ReplaceLength = 0x1A,
                    Before        = ctx =>
                    {
                        float cur = ctx.XMM8f;
                        float min = ctx.XMM7f;
                        float max = ctx.XMM6f;

                        if (this.CameraMain != null && this.CameraMain.IsEnabled)
                        {
                            max += (float)(Math.PI / 4.0);
                        }

                        if (cur > max)
                        {
                            ctx.XMM1f = max;
                        }
                        else if (cur < min)
                        {
                            ctx.XMM1f = min;
                        }
                        else
                        {
                            ctx.XMM1f = cur;
                        }
                    }
                });
            }

            this.CameraMain = new CameraMain(this);

            Events.OnFrame.Register(e =>
            {
                var main = NetScriptFramework.SkyrimSE.Main.Instance;
                if (main != null)
                {
#if PROFILING
                    if (this.CameraMain._prof_state == 1)
                    {
                        this.CameraMain.end_track(CameraMain._performance_track.Frame);
                        this.CameraMain.begin_track(CameraMain._performance_track.Frame);
                    }
#endif

                    bool paused    = main.IsGamePaused;
                    bool anyPaused = paused;
                    if (paused != this.WasGamePaused)
                    {
                        anyPaused          = true;
                        this.WasGamePaused = paused;
                    }

                    long now       = this.Timer.Time;
                    this._lastDiff = 0;
                    if (!anyPaused)
                    {
                        long diff = now - this._lastTimer;
                        if (diff > 200)
                        {
                            diff = 200;
                        }
                        this.Time     += diff;
                        this._lastDiff = diff;
                    }
                    this._lastTimer = now;
                    this._lastDiff2 = this._lastDiff;
                }
            });

            Events.OnMainMenu.Register(e =>
            {
                if (this.CameraMain != null && !this.CameraMain.IsInitialized)
                {
                    this.CameraMain.Initialize();
                }
            }, 0, 1);

            Events.OnUpdateCamera.Register(e =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized)
                {
#if PROFILING
                    if (this.CameraMain._prof_state == 1)
                    {
                        this.CameraMain.begin_track(CameraMain._performance_track.CameraUpdate);
                    }
#endif

                    bool ok;
                    if (!(ok = this.CameraMain.Update(e)))
                    {
                        if (this._lastDiff > 0)
                        {
                            this.Time     -= this._lastDiff;
                            this._lastDiff = 0;
                        }
                    }

#if PROFILING
                    if (this.CameraMain._prof_state == 1)
                    {
                        this.CameraMain.end_track(CameraMain._performance_track.CameraUpdate);
                    }
#endif

#if PROFILING
                    if (ok && this.CameraMain._prof_state == 0)
                    {
                        this.CameraMain._prof_state = 1;
                        this.CameraMain.begin_track(CameraMain._performance_track.Frame);
                    }
                    else if (this.CameraMain._prof_state == 1 && NetScriptFramework.Tools.Input.IsPressed(NetScriptFramework.Tools.VirtualKeys.N9))
                    {
                        this.CameraMain._prof_state = 2;
                        this.CameraMain._end_profiling();
                    }
#endif
                }
            }, 1000);

            Events.OnUpdatedPlayerHeadtrack.Register(e =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized)
                {
                    this.CameraMain.UpdateHeadtrack();
                }
            }, 50);

            Events.OnUpdatePlayerTurnToCamera.Register(e =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized)
                {
                    double value = this.CameraMain.Values.FaceCamera.CurrentValue;
                    if (value >= 1.0)
                    {
                        e.FreeLook = false;
                    }
                    else if (value <= -1.0)
                    {
                        e.FreeLook = true;
                    }

                    bool isFree = e.FreeLook;
                    if (_had_free_look != isFree)
                    {
                        _had_free_look = isFree;
                        if (!isFree && this.CameraMain.IsEnabled)
                        {
                            this.CameraMain.OnMakeTurn();
                        }
                    }
                }
            }, 50);

            Events.OnShadowCullingBegin.Register(e =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized && this.CameraMain.IsEnabled && Settings.SeparateShadowCulling)
                {
                    e.Separate = true;
                    this.CameraMain.OnShadowCulling(0);
                }
            }, 1000);

            Events.OnShadowCullingEnd.Register(e =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized && this.CameraMain.IsEnabled && Settings.SeparateShadowCulling)
                {
                    this.CameraMain.OnShadowCulling(1);
                }
            }, 1000);

            Events.OnWeaponFireProjectilePosition.Register(e =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized)
                {
                    var obj  = e.Attacker;
                    bool did = this.CameraMain.GetOverwriteWeaponNode(obj, e.Position);

                    if (did)
                    {
                        e.Node = null;
                    }
                }
            });

            this.InstallHook("magic fire node art", 33361, 0x7E, 7, "41 FF 90 78 03 00 00", ctx =>
            {
                if (this.CameraMain == null || !this.CameraMain.IsInitialized || !this.CameraMain.WasUsingFirstPersonArms)
                {
                    return;
                }

                var caster = MemoryObject.FromAddress <MagicCaster>(ctx.DI);
                var node   = this.CameraMain.GetOverwriteMagicNode(caster);
                if (node != null)
                {
                    ctx.DX = new IntPtr((long)1);
                }
            });

            this.InstallHook("magic fire node", 33361, 0, 6, "40 57 48 83 EC 20", ctx =>
            {
                if (this.CameraMain == null || !this.CameraMain.IsInitialized || !this.CameraMain.WasUsingFirstPersonArms)
                {
                    return;
                }

                IntPtr calledFrom = Memory.ReadPointer(ctx.SP);
                if (calledFrom == this.MagicNodeArt1 || calledFrom == this.MagicNodeArt2 || calledFrom == this.MagicNodeArt3 || calledFrom == this.MagicNodeArt4)
                {
                    //NetScriptFramework.Main.WriteDebugMessage("Bad called from: " + calledFrom.ToBase().ToHexString());
                    return;
                }

                var node = this.CameraMain.GetOverwriteMagicNode(MemoryObject.FromAddress <MagicCaster>(ctx.CX));
                if (node == null)
                {
                    //NetScriptFramework.Main.WriteDebugMessage("Null overwrite");
                    return;
                }

                ctx.Skip();
                ctx.IP = ctx.IP + 0x2D;
                ctx.AX = node.Address;

                //NetScriptFramework.Main.WriteDebugMessage("Replaced node");
            });

            // Block character model fading out
            this.InstallHook("block fade out", 49899, 0x3C, 6, "4C 8B F2 48 8B F9", ctx =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized && this.CameraMain.Values.BlockPlayerFadeOut.CurrentValue >= 0.5)
                {
                    if (Settings.Instance.HidePlayerWhenColliding != 1 || !this.CameraMain.DidCollideLastUpdate)
                    {
                        ctx.R13 = new IntPtr(0);
                    }
                }
            });

            // Overwrite the turn part
            this.InstallHook("actor turn overwrite", 49968, 0xBB, 0x2E, "F3 0F 10 8B D4 00 00 00", ctx =>
            {
                var third = MemoryObject.FromAddress <ThirdPersonState>(ctx.BX);
                var actor = MemoryObject.FromAddress <Actor>(ctx.AX);

                if (this.CameraMain != null && this.CameraMain.IsInitialized)
                {
                    this.CameraMain.HandleActorTurnToCamera(actor, third, true);
                }

                ctx.IP = ctx.IP + 0x10;
            }, null, true);

            if (Settings.Instance.ReplaceDefaultCamera)
            {
                // Make sure we always use the custom code instead of allowing min zoom to enter first person.
                this.InstallHook("replace zoom #1", 49970, 0x1E1, 5, "E8", null, ctx =>
                {
                    ctx.AX = IntPtr.Zero;
                });

                // Custom zoom
                this.InstallHook("replace zoom #1", 49970, 0x22F, 7, "48 8B 8B E8 01 00 00", ctx =>
                {
                    IntPtr cptr = Memory.ReadPointer(ctx.AX);
                    IntPtr dptr = Memory.ReadPointer(ctx.BX + 0x1E8);
                    var third   = MemoryObject.FromAddress <ThirdPersonState>(ctx.DI);

                    if (this.CameraMain != null && this.CameraMain.IsInitialized && third != null)
                    {
                        this.CameraMain.HandleZoom(third, cptr == dptr);
                    }

                    ctx.Skip();
                    ctx.IP = ctx.IP + 0x40;
                });

                // Dragon and horse must use regular toggle pov handler
                {
                    var ptr = PrepareFunction("dragon toggle pov", 32363, 0x1F);
                    if (!Memory.VerifyBytes(ptr, "74 52", true))
                    {
                        throw new InvalidOperationException("Couldn't verify byte pattern for 'dragon toggle pov'!");
                    }
                    Memory.WriteUInt8(ptr, 0xEB, true);
                    ptr = PrepareFunction("horse toggle pov", 49832, 0x1F);
                    if (!Memory.VerifyBytes(ptr, "74 52", true))
                    {
                        throw new InvalidOperationException("Couldn't verify byte pattern for 'horse toggle pov'!");
                    }
                    Memory.WriteUInt8(ptr, 0xEB, true);
                }

                // Don't toggle pov from zoom delayed parameter
                {
                    var ptr = PrepareFunction("zoom delayed toggle pov", 49977, 0x291);
                    if (!Memory.VerifyBytes(ptr, "74 1C", true))
                    {
                        throw new InvalidOperationException("Couldn't verify byte pattern for 'zoom delayed toggle pov'!");
                    }
                    Memory.WriteUInt8(ptr, 0xEB, true);
                }

                // Toggle POV hotkey was pressed
                this.InstallHook("toggle pov", 49970, 0xD5, 5, "E8", null, ctx =>
                {
                    // Skip default action
                    ctx.AX = new IntPtr((long)0);

                    if (this.CameraMain != null && this.CameraMain.IsInitialized)
                    {
                        this.CameraMain.SetWantState(this.CameraMain.AlreadyHasWantState() ? CameraMain.WantStates.DisabledFromTogglePOV : CameraMain.WantStates.EnabledFromTogglePOV);
                    }
                });

                // Replace forced first person mode from papyrus or other scripted events.
                this.InstallHook("replace first person", 49858, 0, 6, "40 53 48 83 EC 20", ctx =>
                {
                    if (this.CameraMain == null || !this.CameraMain.IsInitialized)
                    {
                        return;
                    }

                    IntPtr calledFrom = Memory.ReadPointer(ctx.SP);
                    ulong vid         = 0;
                    if (!_fp_called.TryGetValue(calledFrom, out vid))
                    {
                        var fn = NetScriptFramework.Main.GameInfo.GetFunctionInfo(calledFrom, true);
                        if (fn != null)
                        {
                            vid = fn.Id;
                        }

                        _fp_called[calledFrom] = vid;
                    }

                    bool skip = false;
                    bool want = false;

                    switch (vid)
                    {
                    case 22463:     // Console command
                    case 43115:     // Forced by game scripted camera
                        break;

                    case 43098:     // Some kind of VATS thing?
                        skip = true;
                        //want = true;
                        break;

                    case 49880:     // Piece of furniture had a keyword on it
                        skip = true;
                        //want = true;
                        break;

                    default:     // Other, this usually is controlled by papyrus or other script event
                        // Must let it happen otherwise Solstheim boat ride is bugged and some other stuff too probably.
                        // It's fine because if camswitch is enabled IFPV will re-enable itself anyway.
                        break;
                    }

                    if (skip)
                    {
                        ctx.Skip();
                        ctx.IP = ctx.IP + 0x39;
                    }

                    if (want && !this.CameraMain.AlreadyHasWantState())
                    {
                        this.CameraMain.SetWantState(CameraMain.WantStates.EnabledFromTogglePOV);
                    }
                });
            }

            this.InstallHook("fix crosshair pick", 39534, 0x159, 10, "F3 0F 58 45 E8 F3 0F 11 45 D8", ctx =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized && this.CameraMain.IsEnabled)
                {
                    var pt   = MemoryObject.FromAddress <NiPoint3>(ctx.BP - 0x30);
                    var pcam = PlayerCamera.Instance;
                    if (pcam != null)
                    {
                        ctx.Skip();

                        pt.CopyFrom(pcam.LastNodePosition);
                    }
                }
            });

            this.InstallHook("fix look sensitivity", 41275, 0x38D, 0xE, "75 0E", ctx =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized)
                {
                    float x = Memory.ReadFloat(ctx.BX);
                    float y = Memory.ReadFloat(ctx.BX + 4);
                    this.CameraMain.FixMouseSensitivity(ref x, ref y, ctx.XMM1f);
                    Memory.WriteFloat(ctx.BX, x);
                    Memory.WriteFloat(ctx.BX + 4, y);
                }
            }, null, true);

            this.InstallHook("switch skeleton override", 39401, 0, 7, "40 55 56 48 83 EC 78", ctx =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized)
                {
                    if (this.CameraMain.HookSwitchSkeleton(MemoryObject.FromAddress <Actor>(ctx.CX), ctx.DX.ToBool()))
                    {
                        ctx.Skip();
                        ctx.IP = ctx.IP + 0x2DD;
                    }
                }
            });

            this.InstallHook("fix bound node update", 18683, 0x7C, 6, "FF 90 68 04 00 00", ctx =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized && this.CameraMain.IsEnabled)
                {
                    ctx.Skip();
                    var obj  = MemoryObject.FromAddress <TESObjectREFR>(ctx.CX);
                    var node = obj.GetSkeletonNode(false);
                    ctx.AX   = node != null ? node.Address : IntPtr.Zero;
                }
            });

            this.InstallHook("fix spine twist", 59246, 0x75, 5, "48 83 C4 20 5F", ctx =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized &&
                    System.Threading.Interlocked.CompareExchange(ref _is_spine, 0, 0) > 0
                    )
                {
                    this.CameraMain.FixSpineTwist(ctx.DI);
                }
            });

            this.InstallHook("player update animation", 39445, 0x97, 5, "E8", ctx =>
            {
                System.Threading.Interlocked.Increment(ref _is_spine);
            },
                             ctx =>
            {
                System.Threading.Interlocked.Decrement(ref _is_spine);
            });
            this.InstallHook("player control inc counter", 41259, 0, 5, "48 89 5C 24 08", ctx =>
            {
                System.Threading.Interlocked.Increment(ref _is_spine);
            });

            this.InstallHook("player controls dec counter", 41259, 0x241, 5, "48 83 C4 30 5F", ctx =>
            {
                System.Threading.Interlocked.Decrement(ref _is_spine);
            });

            this.InstallHook("player movement controller type", 40937, 0x2EA, 6, "FF 90 88 03 00 00", null, ctx =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized)
                {
                    if (this.CameraMain.Values.ExtraResponsiveControls.CurrentValue >= 0.5)
                    {
                        ctx.AX = IntPtr.Zero;
                    }
                }
            });

            this.InstallHook("before draw", 35560, 0x199, 7, "83 8F F4 00 00 00 01", ctx =>
            {
                if (this.CameraMain != null && this.CameraMain.IsInitialized && this.CameraMain.IsEnabled)
                {
                    this.CameraMain.UpdateSkeletonWithLastParameters();
                }
            });
        }