├── .editorconfig
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── mfgfix.sln
├── mfgfix.vcxproj
├── mfgfix.vcxproj.filters
└── src
├── main.cpp
├── mfgfix
├── BSFaceGenAnimationData.cpp
├── BSFaceGenAnimationData.h
├── BSFaceGenKeyframe.h
├── BSFaceGenKeyframeMultiple.cpp
├── BSFaceGenKeyframeMultiple.h
├── ConsoleCommands.cpp
├── ConsoleCommands.h
├── MfgConsoleFunc.cpp
├── MfgConsoleFunc.h
├── Offsets.h
├── Settings.cpp
├── Settings.h
├── SettingsPapyrus.cpp
├── SettingsPapyrus.h
├── SimpleIni.h
├── mfgfixinit.cpp
└── mfgfixinit.h
├── pch.cpp
├── pch.h
├── version.h
└── version.rc
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{h,cpp}]
2 | indent_style = tab
3 | indent_size = 4
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "ext/CommonLibSSE"]
2 | path = ext/CommonLibSSE
3 | url = https://github.com/Ryan-rsm-McKenzie/CommonLibSSE
4 | [submodule "ext/Detours"]
5 | path = ext/Detours
6 | url = https://github.com/microsoft/Detours
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 andrelo1
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mfgfix
2 |
3 | ## Dependencies
4 | - [CommonLibSSE](https://github.com/Ryan-rsm-McKenzie/CommonLibSSE)
5 | - [Detours](https://github.com/microsoft/Detours)
6 | ## Building
7 | Prerequisites:
8 | - Visual Studio 2022
9 | - [vcpkg](https://github.com/microsoft/vcpkg) (for CommonLibSSE)
10 |
11 | Open x64 Native Tools Command Prompt for VS 2022.
12 |
13 | Clone repository:
14 | ```
15 | git clone --recurse-submodules https://github.com/andrelo1/mfgfix
16 | ```
17 | Build CommonLibSSE:
18 |
19 | ```
20 | cd mfgfix/ext/CommonLibSSE
21 | cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
22 | cmake --build build --config Release
23 | ```
24 | Build Detours:
25 | ```
26 | cd ../Detours/
27 | nmake
28 | ```
29 | Build mfgfix:
30 |
31 | Open and build `mfgfix.sln` in Visual Studio.
32 |
--------------------------------------------------------------------------------
/mfgfix.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31911.196
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mfgfix", "mfgfix.vcxproj", "{6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}.Debug|x64.ActiveCfg = Debug|x64
17 | {6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}.Debug|x64.Build.0 = Debug|x64
18 | {6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}.Debug|x86.ActiveCfg = Debug|Win32
19 | {6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}.Debug|x86.Build.0 = Debug|Win32
20 | {6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}.Release|x64.ActiveCfg = Release|x64
21 | {6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}.Release|x64.Build.0 = Release|x64
22 | {6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}.Release|x86.ActiveCfg = Release|Win32
23 | {6C7E7079-990B-4EA3-89C4-A5BC4CA746A6}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {449BDA17-9D53-4A79-8F14-B22E41228791}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/mfgfix.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 |
23 | Use
24 | pch.h
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Create
35 | Create
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 16.0
57 | Win32Proj
58 | {6c7e7079-990b-4ea3-89c4-a5bc4ca746a6}
59 | mfgfix
60 |
61 |
62 |
63 |
64 |
65 | DynamicLibrary
66 | true
67 | v143
68 | Unicode
69 |
70 |
71 | DynamicLibrary
72 | false
73 | v143
74 | true
75 | Unicode
76 |
77 |
78 | DynamicLibrary
79 | true
80 | v143
81 | MultiByte
82 |
83 |
84 | DynamicLibrary
85 | false
86 | v143
87 | true
88 | MultiByte
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | true
112 |
113 |
114 | false
115 |
116 |
117 | true
118 |
119 |
120 | false
121 |
122 |
123 |
124 | Level3
125 | true
126 | WIN32;_DEBUG;MFGFIX_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
127 | true
128 | Use
129 | pch.h
130 |
131 |
132 | Windows
133 | true
134 | false
135 |
136 |
137 |
138 |
139 | Level3
140 | true
141 | true
142 | true
143 | WIN32;NDEBUG;MFGFIX_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
144 | true
145 | Use
146 | pch.h
147 |
148 |
149 | Windows
150 | true
151 | true
152 | true
153 | false
154 |
155 |
156 |
157 |
158 | Level3
159 | true
160 | _DEBUG;SPDLOG_COMPILED_LIB;SPDLOG_FMT_EXTERNAL;FMT_LOCALE;BOOST_STL_INTERFACES_DISABLE_CONCEPTS;%(PreprocessorDefinitions)
161 | true
162 | Use
163 | pch.h
164 | pch.h
165 | .\ext;.\ext\CommonLibSSE\include;.\ext\CommonLibSSE\build\vcpkg_installed\x64-windows-static-md\include;%(AdditionalIncludeDirectories)
166 | stdcpplatest
167 | MultiThreadedDebugDLL
168 | 4200;4251;4275
169 |
170 |
171 | Windows
172 | true
173 | false
174 | .\ext\CommonLibSSE\build\Debug\CommonLibSSE.lib;.\ext\CommonLibSSE\build\vcpkg_installed\x64-windows-static-md\debug\lib\spdlogd.lib;.\ext\CommonLibSSE\build\vcpkg_installed\x64-windows-static-md\debug\lib\fmtd.lib;.\ext\CommonLibSSE\build\vcpkg_installed\x64-windows-static-md\debug\lib\binary_iod.lib;.\ext\Detours\lib.X64\detours.lib;Version.lib;%(AdditionalDependencies)
175 |
176 |
177 |
178 |
179 | Level3
180 | true
181 | true
182 | true
183 | NDEBUG;BOOST_STL_INTERFACES_DISABLE_CONCEPTS;SPDLOG_COMPILED_LIB;SPDLOG_FMT_EXTERNAL;FMT_LOCALE;%(PreprocessorDefinitions)
184 | true
185 | Use
186 | pch.h
187 | pch.h
188 | .\ext;.\ext\CommonLibSSE\include;.\ext\CommonLibSSE\build\vcpkg_installed\x64-windows-static-md\include;%(AdditionalIncludeDirectories)
189 | stdcpplatest
190 | MultiThreadedDLL
191 |
192 |
193 | 4200;4251;4275
194 |
195 |
196 | Windows
197 | true
198 | true
199 | true
200 | false
201 | .\ext\CommonLibSSE\build\Release\CommonLibSSE.lib;.\ext\CommonLibSSE\build\vcpkg_installed\x64-windows-static-md\lib\spdlog.lib;.\ext\CommonLibSSE\build\vcpkg_installed\x64-windows-static-md\lib\fmt.lib;.\ext\CommonLibSSE\build\vcpkg_installed\x64-windows-static-md\lib\binary_io.lib;.\ext\Detours\lib.X64\detours.lib;Version.lib;%(AdditionalDependencies)
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/mfgfix.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {6ff6e8d5-3c13-49a6-bcff-bc96a449bed9}
18 |
19 |
20 | {3b7e0726-063b-4fd7-8e7b-52acd317fe92}
21 |
22 |
23 |
24 |
25 | src
26 |
27 |
28 | src
29 |
30 |
31 | src\mfgfix
32 |
33 |
34 | src\mfgfix
35 |
36 |
37 | src\mfgfix
38 |
39 |
40 | src\mfgfix
41 |
42 |
43 | src\mfgfix
44 |
45 |
46 | src\mfgfix
47 |
48 |
49 | src\mfgfix
50 |
51 |
52 |
53 |
54 | src
55 |
56 |
57 | src
58 |
59 |
60 | src\mfgfix
61 |
62 |
63 | src\mfgfix
64 |
65 |
66 | src\mfgfix
67 |
68 |
69 | src\mfgfix
70 |
71 |
72 | src\mfgfix
73 |
74 |
75 | src\mfgfix
76 |
77 |
78 | src\mfgfix
79 |
80 |
81 | src\mfgfix
82 |
83 |
84 | src\mfgfix
85 |
86 |
87 | src\mfgfix
88 |
89 |
90 |
91 |
92 | src
93 |
94 |
95 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mfgfix/mfgfixinit.h"
2 |
3 | namespace
4 | {
5 | constexpr SKSE::PluginVersionData GetPluginVersionData()
6 | {
7 | SKSE::PluginVersionData version;
8 |
9 | version.PluginVersion({ Version::MAJOR, Version::MINOR, Version::PATCH, 0 });
10 | version.PluginName(Version::PROJECT);
11 | version.UsesAddressLibrary(true);
12 |
13 | return version;
14 | }
15 | }
16 |
17 | extern "C" __declspec(dllexport) SKSE::PluginVersionData SKSEPlugin_Version{ GetPluginVersionData() };
18 |
19 | extern "C" __declspec(dllexport) bool SKSEAPI SKSEPlugin_Load(const SKSE::LoadInterface * a_skse)
20 | {
21 | auto path = SKSE::log::log_directory();
22 |
23 | if (path) {
24 | *path /= Version::PROJECT;
25 | *path += ".log";
26 | spdlog::set_default_logger(spdlog::basic_logger_mt("default", path->string(), true));
27 | }
28 |
29 | spdlog::set_level(spdlog::level::trace);
30 | spdlog::flush_on(spdlog::level::trace);
31 | spdlog::info("loaded");
32 |
33 | SKSE::Init(a_skse);
34 | MfgFix::Init();
35 |
36 | return true;
37 | }
--------------------------------------------------------------------------------
/src/mfgfix/BSFaceGenAnimationData.cpp:
--------------------------------------------------------------------------------
1 | #include "BSFaceGenAnimationData.h"
2 | #include "Offsets.h"
3 | #include "Settings.h"
4 |
5 | namespace MfgFix
6 | {
7 | namespace
8 | {
9 | constexpr float pi_180 = 0.0174532925f;
10 |
11 | float rand(float a_min, float a_max)
12 | {
13 | return a_min + (a_max - a_min) * (static_cast(std::rand()) / RAND_MAX);
14 | }
15 |
16 | float rand(float a_min, float a_max, float a_exp)
17 | {
18 | return a_min + (a_max - a_min) * pow(static_cast(std::rand()) / RAND_MAX, a_exp);
19 | }
20 |
21 | float deg2rad(float a_degrees)
22 | {
23 | return a_degrees * pi_180;
24 | }
25 | }
26 |
27 | void BSFaceGenAnimationData::SetExpressionOverride(std::uint32_t a_idx, float a_value)
28 | {
29 | using func_t = decltype(&BSFaceGenAnimationData::SetExpressionOverride);
30 | REL::Relocation func(Offsets::BSFaceGenAnimationData::SetExpressionOverride);
31 | func(this, a_idx, a_value);
32 | }
33 |
34 | void BSFaceGenAnimationData::ClearExpressionOverride()
35 | {
36 | expressionOverride = false;
37 | }
38 |
39 | void BSFaceGenAnimationData::Reset(float a_timer, bool a_resetExpression, bool a_resetModifierAndPhoneme, bool a_resetCustom, bool a_closeEyes)
40 | {
41 | using func_t = decltype(&BSFaceGenAnimationData::Reset);
42 | REL::Relocation func(Offsets::BSFaceGenAnimationData::Reset);
43 | func(this, a_timer, a_resetExpression, a_resetModifierAndPhoneme, a_resetCustom, a_closeEyes);
44 | }
45 |
46 | std::uint32_t BSFaceGenAnimationData::GetActiveExpression() const
47 | {
48 | std::uint32_t expression = Expression::MoodNeutral;
49 |
50 | for (std::uint32_t i = 0; i < expression3.count; ++i) {
51 | if (expression3.values[i] > expression3.values[expression]) {
52 | expression = i;
53 | }
54 | }
55 |
56 | return expression;
57 | }
58 |
59 | void BSFaceGenAnimationData::DialogueModifiersUpdate(float a_timeDelta)
60 | {
61 | if (!dialogueData || (((dialogueData->refCount & 0x70000000) + 0xD0000000) & 0xEFFFFFFF) != 0) {
62 | return;
63 | }
64 |
65 | REL::Relocation sub_1FCD10{ REL::ID(16267) };
66 |
67 | modifier1.timer += a_timeDelta;
68 | sub_1FCD10(dialogueData->unk28, modifier1.timer, modifier1.values);
69 | }
70 |
71 | void BSFaceGenAnimationData::DialoguePhonemesUpdate(float a_timeDelta)
72 | {
73 | if (!dialogueData || (((dialogueData->refCount & 0x70000000) + 0xD0000000) & 0xEFFFFFFF) != 0) {
74 | return;
75 | }
76 |
77 | REL::Relocation sub_1FC9B0{ REL::ID(16266) };
78 |
79 | phoneme1.timer += a_timeDelta;
80 | sub_1FC9B0(dialogueData->unk28, phoneme1.timer, phoneme1.values);
81 | }
82 |
83 | void BSFaceGenAnimationData::CheckAndReleaseDialogueData()
84 | {
85 | if (!dialogueData || (((dialogueData->refCount & 0x70000000) + 0xD0000000) & 0xEFFFFFFF) != 0) {
86 | return;
87 | }
88 |
89 | auto timer = (dialogueData->unk28->unk0 + (dialogueData->unk28->unk4 < 0 ? -dialogueData->unk28->unk4 : 0)) * 0.033f + 0.2f;
90 |
91 | if (phoneme1.timer <= timer) {
92 | return;
93 | }
94 |
95 | REL::Relocation ReleaseDialogueData{ REL::ID(16318) };
96 |
97 | ReleaseDialogueData(dialogueData);
98 |
99 | dialogueData = nullptr;
100 | }
101 |
102 | void BSFaceGenAnimationData::EyesBlinkingUpdate(float a_timeDelta)
103 | {
104 | auto& settings = Settings::Get();
105 |
106 | eyesBlinkingTimer = std::max(eyesBlinkingTimer - a_timeDelta, 0.0f);
107 | auto blinkValue = 0.0f;
108 |
109 | switch (eyesBlinkingStage) {
110 | case EyesBlinkingStage::BlinkDelay: {
111 | blinkValue = 0.0f;
112 |
113 | if (eyesBlinkingTimer == 0.0f) {
114 | eyesBlinkingStage = EyesBlinkingStage::BlinkDown;
115 | eyesBlinkingTimer = settings.eyesBlinking.fBlinkDownTime;
116 | }
117 |
118 | break;
119 | }
120 | case EyesBlinkingStage::BlinkDown: {
121 | blinkValue = settings.eyesBlinking.fBlinkDownTime != 0.0f ? 1.0f - eyesBlinkingTimer / settings.eyesBlinking.fBlinkDownTime : 1.0f;
122 |
123 | if (eyesBlinkingTimer == 0.0f) {
124 | eyesBlinkingStage = EyesBlinkingStage::BlinkUp;
125 | eyesBlinkingTimer = settings.eyesBlinking.fBlinkUpTime;
126 | }
127 |
128 | break;
129 | }
130 | case EyesBlinkingStage::BlinkUp: {
131 | blinkValue = settings.eyesBlinking.fBlinkUpTime != 0.0f ? eyesBlinkingTimer / settings.eyesBlinking.fBlinkUpTime : 0.0f;
132 |
133 | if (eyesBlinkingTimer == 0.0f) {
134 | eyesBlinkingStage = EyesBlinkingStage::BlinkDelay;
135 | eyesBlinkingTimer = rand(settings.eyesBlinking.fBlinkDelayMin, settings.eyesBlinking.fBlinkDelayMax, 2.0f);
136 | }
137 |
138 | break;
139 | }
140 | case EyesBlinkingStage::BlinkDownAndWait1: {
141 | if (unk21A) {
142 | blinkValue = settings.eyesBlinking.fBlinkDownTime != 0.0f ? 1.0f - eyesBlinkingTimer / settings.eyesBlinking.fBlinkDownTime : 1.0f;
143 | } else {
144 | blinkValue = 1.0f;
145 | eyesBlinkingStage = EyesBlinkingStage::BlinkUp;
146 | eyesBlinkingTimer = settings.eyesBlinking.fBlinkUpTime;
147 | }
148 |
149 | break;
150 | }
151 | case EyesBlinkingStage::BlinkDownAndWait2: {
152 | eyesBlinkingStage = EyesBlinkingStage::BlinkDownAndWait1;
153 |
154 | break;
155 | }
156 | default: {
157 | blinkValue = 0.0f;
158 | eyesBlinkingStage = EyesBlinkingStage::BlinkDelay;
159 | eyesBlinkingTimer = rand(settings.eyesBlinking.fBlinkDelayMin, settings.eyesBlinking.fBlinkDelayMax, 2.0f);
160 |
161 | break;
162 | }
163 | }
164 |
165 | blinkValue = std::clamp(blinkValue, 0.0f, 1.0f);
166 |
167 | modifier3.values[Modifier::BlinkLeft] = blinkValue;
168 | modifier3.values[Modifier::BlinkRight] = blinkValue;
169 | }
170 |
171 | void BSFaceGenAnimationData::EyesMovementUpdate(float a_timeDelta)
172 | {
173 | auto& settings = Settings::Get();
174 |
175 | eyesOffsetTimer = std::max(eyesOffsetTimer - a_timeDelta, 0.0f);
176 |
177 | if (eyesOffsetTimer > 0.0f) {
178 | return;
179 | }
180 |
181 | switch (GetActiveExpression()) {
182 | case Expression::DialogueAnger:
183 | case Expression::MoodAnger: {
184 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionAngry, settings.eyesMovement.fEyeOffsetDelayMaxEmotionAngry, 2.0f);
185 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionAngry, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionAngry);
186 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionAngry, settings.eyesMovement.fEyePitchMaxOffsetEmotionAngry);
187 |
188 | break;
189 | }
190 | case Expression::DialogueHappy:
191 | case Expression::MoodHappy: {
192 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionHappy, settings.eyesMovement.fEyeOffsetDelayMaxEmotionHappy, 0.5f);
193 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionHappy, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionHappy);
194 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionHappy, settings.eyesMovement.fEyePitchMaxOffsetEmotionHappy);
195 |
196 | break;
197 | }
198 | case Expression::DialogueSurprise:
199 | case Expression::MoodSurprise: {
200 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionSurprise, settings.eyesMovement.fEyeOffsetDelayMaxEmotionSurprise, 0.5f);
201 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionSurprise, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionSurprise);
202 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionSurprise, settings.eyesMovement.fEyePitchMaxOffsetEmotionSurprise);
203 |
204 | break;
205 | }
206 | case Expression::DialogueSad:
207 | case Expression::MoodSad: {
208 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionSad, settings.eyesMovement.fEyeOffsetDelayMaxEmotionSad);
209 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionSad, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionSad);
210 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionSad, settings.eyesMovement.fEyePitchMaxOffsetEmotionSad);
211 |
212 | break;
213 | }
214 | case Expression::DialogueFear:
215 | case Expression::MoodFear: {
216 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionFear, settings.eyesMovement.fEyeOffsetDelayMaxEmotionFear);
217 | eyesHeadingOffset = rand(0.0f, 1.0f) <= 0.5f ? 0.0f : rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionFear, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionFear);
218 | eyesPitchOffset = rand(0.0f, 1.0f) <= 0.5f ? 0.0f : rand(settings.eyesMovement.fEyePitchMinOffsetEmotionFear, settings.eyesMovement.fEyePitchMaxOffsetEmotionFear);
219 |
220 | break;
221 | }
222 | case Expression::DialoguePuzzled:
223 | case Expression::MoodPuzzled: {
224 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionPuzzled, settings.eyesMovement.fEyeOffsetDelayMaxEmotionPuzzled);
225 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionPuzzled, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionPuzzled);
226 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionPuzzled, settings.eyesMovement.fEyePitchMaxOffsetEmotionPuzzled);
227 |
228 | break;
229 | }
230 | case Expression::DialogueDisgusted:
231 | case Expression::MoodDisgusted: {
232 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionDisgusted, settings.eyesMovement.fEyeOffsetDelayMaxEmotionDisgusted);
233 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionDisgusted, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionDisgusted);
234 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionDisgusted, settings.eyesMovement.fEyePitchMaxOffsetEmotionDisgusted);
235 |
236 | break;
237 | }
238 | case Expression::CombatAnger: {
239 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionCombatAnger, settings.eyesMovement.fEyeOffsetDelayMaxEmotionCombatAnger);
240 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionCombatAnger, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionCombatAnger);
241 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionCombatAnger, settings.eyesMovement.fEyePitchMaxOffsetEmotionCombatAnger);
242 |
243 | break;
244 | }
245 | case Expression::CombatShout: {
246 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionCombatShout, settings.eyesMovement.fEyeOffsetDelayMaxEmotionCombatShout);
247 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionCombatShout, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionCombatShout);
248 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionCombatShout, settings.eyesMovement.fEyePitchMaxOffsetEmotionCombatShout);
249 |
250 | break;
251 | }
252 | default: {
253 | eyesOffsetTimer = rand(settings.eyesMovement.fEyeOffsetDelayMinEmotionNeutral, settings.eyesMovement.fEyeOffsetDelayMaxEmotionNeutral, 2.0f);
254 | eyesHeadingOffset = rand(settings.eyesMovement.fEyeHeadingMinOffsetEmotionNeutral, settings.eyesMovement.fEyeHeadingMaxOffsetEmotionNeutral);
255 | eyesPitchOffset = rand(settings.eyesMovement.fEyePitchMinOffsetEmotionNeutral, settings.eyesMovement.fEyePitchMaxOffsetEmotionNeutral);
256 |
257 | break;
258 | }
259 | }
260 | }
261 |
262 | void BSFaceGenAnimationData::EyesDirectionUpdate(float a_timeDelta)
263 | {
264 | auto& settings = Settings::Get();
265 |
266 | auto eyesHeadingMax = deg2rad(settings.eyesMovement.fTrackEyeXY);
267 | auto eyesPitchMax = deg2rad(settings.eyesMovement.fTrackEyeZ);
268 | auto eyesHeadingDeltaMax = settings.eyesMovement.fTrackSpeed * a_timeDelta;
269 | auto eyesPitchDeltaMax = settings.eyesMovement.fTrackSpeed * a_timeDelta;
270 |
271 | eyesHeading = std::clamp(eyesHeadingBase + eyesHeadingOffset, eyesHeading - eyesHeadingDeltaMax, eyesHeading + eyesHeadingDeltaMax);
272 | eyesPitch = std::clamp(eyesPitchBase + eyesPitchOffset, eyesPitch - eyesPitchDeltaMax, eyesPitch + eyesPitchDeltaMax);
273 | eyesHeading = std::clamp(eyesHeading, -eyesHeadingMax, eyesHeadingMax);
274 | eyesPitch = std::clamp(eyesPitch, -eyesPitchMax, eyesPitchMax);
275 |
276 | modifier3.values[Modifier::LookLeft] = eyesHeading < 0.0f ? (eyesHeadingMax != 0.0f ? -eyesHeading / eyesHeadingMax : 0.0f) : 0.0f;
277 | modifier3.values[Modifier::LookRight] = eyesHeading > 0.0f ? (eyesHeadingMax != 0.0f ? eyesHeading / eyesHeadingMax : 0.0f) : 0.0f;
278 | modifier3.values[Modifier::LookDown] = eyesPitch < 0.0f ? (eyesPitchMax != 0.0f ? -eyesPitch / eyesPitchMax : 0.0f) : 0.0f;
279 | modifier3.values[Modifier::LookUp] = eyesPitch > 0.0f ? (eyesPitchMax != 0.0f ? eyesPitch / eyesPitchMax : 0.0f) : 0.0f;
280 | }
281 |
282 | bool BSFaceGenAnimationData::KeyframesUpdateHook(float a_timeDelta, bool a_updateBlinking)
283 | {
284 | RE::BSSpinLockGuard locker(lock);
285 |
286 | // expressions
287 | {
288 | auto merge = [](Keyframe& a_src, Keyframe& a_dst) {
289 | if (!a_src.IsZero()) {
290 | a_dst.Copy(&a_src);
291 | }
292 | };
293 |
294 | expression3.Reset();
295 |
296 | expression1.TransitionUpdate(a_timeDelta, transitionTarget);
297 |
298 | merge(expression1, expression3);
299 | merge(expression2, expression3);
300 | }
301 |
302 | // modifiers
303 | {
304 | auto merge = [](Keyframe& a_src, Keyframe& a_dst) {
305 | auto count = std::min(a_src.count, a_dst.count);
306 | for (std::uint32_t i = 0; i < count; ++i) {
307 | if (a_src.values[i] != 0.0f) {
308 | a_dst.values[i] = a_src.values[i];
309 | }
310 | }
311 | if (a_src.values[Modifier::LookDown] != 0.0f || a_src.values[Modifier::LookLeft] != 0.0f || a_src.values[Modifier::LookRight] != 0.0f || a_src.values[Modifier::LookUp] != 0.0f) {
312 | a_dst.values[Modifier::LookDown] = a_src.values[Modifier::LookDown];
313 | a_dst.values[Modifier::LookLeft] = a_src.values[Modifier::LookLeft];
314 | a_dst.values[Modifier::LookRight] = a_src.values[Modifier::LookRight];
315 | a_dst.values[Modifier::LookUp] = a_src.values[Modifier::LookUp];
316 | }
317 | };
318 |
319 | modifier3.Reset();
320 |
321 | DialogueModifiersUpdate(a_timeDelta);
322 | EyesBlinkingUpdate(a_timeDelta);
323 |
324 | merge(modifier1, modifier3);
325 |
326 | if (!unk21A) {
327 | EyesMovementUpdate(a_timeDelta);
328 | EyesDirectionUpdate(a_timeDelta);
329 | }
330 |
331 | merge(modifier2, modifier3);
332 | }
333 |
334 | // phonemes
335 | {
336 | auto merge = [](Keyframe& a_src, Keyframe& a_dst) {
337 | auto count = std::min(a_src.count, a_dst.count);
338 | for (std::uint32_t i = 0; i < count; ++i) {
339 | if (a_src.values[i] != 0.0f) {
340 | a_dst.values[i] = a_src.values[i];
341 | }
342 | }
343 | };
344 |
345 | phoneme3.Reset();
346 |
347 | DialoguePhonemesUpdate(a_timeDelta);
348 |
349 | merge(phoneme1, phoneme3);
350 | merge(phoneme2, phoneme3);
351 | }
352 |
353 | // custom
354 | {
355 | auto merge = [](BSFaceGenKeyframeMultiple& a_src, BSFaceGenKeyframeMultiple& a_dst) {
356 | auto count = std::min(a_src.count, a_dst.count);
357 | for (std::uint32_t i = 0; i < count; ++i) {
358 | if (a_src.values[i] != 0.0f) {
359 | a_dst.values[i] = a_src.values[i];
360 | }
361 | }
362 | };
363 |
364 | custom3.Reset();
365 |
366 | merge(custom1, custom3);
367 | merge(custom2, custom3);
368 | }
369 |
370 | CheckAndReleaseDialogueData();
371 |
372 | unk217 = true;
373 |
374 | return unk217;
375 | }
376 |
377 | void BSFaceGenAnimationData::Init()
378 | {
379 | auto KeyframesUpdateAddr = Offsets::BSFaceGenAnimationData::KeyframesUpdate.address();
380 | auto KeyframesUpdateHookAddr = &KeyframesUpdateHook;
381 |
382 | DetourTransactionBegin();
383 | DetourUpdateThread(GetCurrentThread());
384 | DetourAttach(reinterpret_cast(&KeyframesUpdateAddr), reinterpret_cast(KeyframesUpdateHookAddr));
385 |
386 | if (DetourTransactionCommit() != NO_ERROR) {
387 | spdlog::error("failed to attach detour");
388 | }
389 |
390 | // remove eyes update from UpdateDownwardPass, it was moved to KeyframesUpdate
391 | REL::safe_write(Offsets::BSFaceGenNiNode::sub_3F1800.address() + 0x0139, static_cast(0x47EB));
392 | }
393 | }
--------------------------------------------------------------------------------
/src/mfgfix/BSFaceGenAnimationData.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "BSFaceGenKeyframeMultiple.h"
4 |
5 | namespace MfgFix
6 | {
7 | class BSFaceGenAnimationData: public RE::NiExtraData
8 | {
9 | public:
10 | using Keyframe = BSFaceGenKeyframeMultiple;
11 | using Expression = Keyframe::Expression;
12 | using Phoneme = Keyframe::Phoneme;
13 | using Modifier = Keyframe::Modifier;
14 |
15 | enum class EyesBlinkingStage : std::uint32_t
16 | {
17 | BlinkDelay = 0,
18 | BlinkDown,
19 | BlinkUp,
20 | WaitForLookDown,
21 | BlinkDownAndWait1,
22 | BlinkDownAndWait2
23 | };
24 |
25 | struct DialogueData
26 | {
27 | struct Unk28
28 | {
29 | std::int32_t unk0; // 00
30 | std::int32_t unk4; // 04
31 | std::uint8_t unk8[0x8]; // 08
32 | void* unk10; // 10
33 | void* unk18; // 18
34 | std::uint8_t unk20; // 20
35 | };
36 |
37 | std::uint8_t unk0[0xC]; // 00
38 | std::uint32_t refCount; // 0C
39 | std::uint8_t unk10[0x18]; // 10
40 | Unk28* unk28; // 28
41 | };
42 |
43 | Keyframe* transitionTarget; // 18 used to animate transition between expressions
44 | Keyframe expression1; // 20 used by console command and SetExpressionOverride
45 | Keyframe expression2; // 40 unused?
46 | Keyframe modifier2; // 60 used by console command
47 | Keyframe phoneme2; // 80 used by console command
48 | Keyframe custom2; // A0 used by console command
49 | Keyframe expression3; // C0 final values
50 | Keyframe modifier1; // E0 dialogue values
51 | Keyframe modifier3; // 100 final values
52 | Keyframe phoneme1; // 120 dialogue values
53 | Keyframe phoneme3; // 140 final values
54 | Keyframe custom1; // 160 unused?
55 | Keyframe custom3; // 180 final values
56 | float unk1A0; // 1A0
57 | float unk1A4; // 1A4
58 | float unk1A8; // 1A8
59 | std::uint32_t unk1AC; // 1AC
60 | std::uint32_t unk1B0; // 1B0
61 | std::uint32_t nk1B4; // 1B4
62 | std::uint32_t unk1B8; // 1B8
63 | float eyesHeading; // 1BC eyesHeadingBase + eyesHeadingOffset
64 | float eyesPitch; // 1C0 eyesPitchBase + eyesPitchOffset
65 | std::uint32_t pad1C4; // 1C4
66 | std::uint64_t unk1C8; // 1C8
67 | std::uint8_t unk1D0; // 1D0
68 | std::uint8_t unk1D1; // 1D1
69 | std::uint8_t nk1D2; // 1D2
70 | std::uint8_t unk1D3; // 1D3
71 | float eyesHeadingBase; // 1D4
72 | float eyesPitchBase; // 1D8
73 | std::uint32_t unk1DC; // 1DC
74 | std::uint32_t unk1E0; // 1E0
75 | std::uint32_t unk1E4; // 1E4
76 | std::uint32_t unk1E8; // 1E8
77 | std::uint32_t unk1EC; // 1EC
78 | std::uint32_t unk1F0; // 1F0
79 | std::uint32_t unk1F4; // 1F4
80 | std::uint32_t unk1F8; // 1F8
81 | std::uint32_t unk1FC; // 1FC
82 | EyesBlinkingStage eyesBlinkingStage; // 200
83 | float eyesBlinkingTimer; // 204
84 | float eyesOffsetTimer; // 208
85 | float eyesHeadingOffset; // 20C
86 | float eyesPitchOffset; // 210
87 | std::uint8_t unk214; // 214
88 | std::uint8_t unk215; // 215
89 | std::uint8_t unk216; // 216
90 | bool unk217; // 217
91 | std::uint8_t unk218; // 218
92 | std::uint8_t unk219; // 219
93 | std::uint8_t unk21A; // 21A
94 | std::uint8_t unk21B; // 21B
95 | std::uint8_t unk21C; // 21C
96 | std::uint8_t unk21D; // 21D
97 | bool expressionOverride; // 21E
98 | std::uint8_t unk21F; // 21F
99 | mutable RE::BSSpinLock lock; // 220
100 | DialogueData* dialogueData; // 228
101 |
102 |
103 | void SetExpressionOverride(std::uint32_t a_idx, float a_value);
104 | void ClearExpressionOverride();
105 | void Reset(float a_timer, bool a_resetExpression, bool a_resetModifierAndPhoneme, bool a_resetCustom, bool a_closeEyes);
106 | std::uint32_t GetActiveExpression() const;
107 | void DialogueModifiersUpdate(float a_timeDelta);
108 | void DialoguePhonemesUpdate(float a_timeDelta);
109 | void CheckAndReleaseDialogueData();
110 | void EyesBlinkingUpdate(float a_timeDelta);
111 | void EyesMovementUpdate(float a_timeDelta);
112 | void EyesDirectionUpdate(float a_timeDelta);
113 | bool KeyframesUpdateHook(float a_timeDelta, bool a_updateBlinking);
114 |
115 | static void Init();
116 | };
117 |
118 | static_assert(sizeof(BSFaceGenAnimationData) == 0x230);
119 | }
--------------------------------------------------------------------------------
/src/mfgfix/BSFaceGenKeyframe.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace MfgFix
4 | {
5 | class BSFaceGenKeyframe
6 | {
7 | public:
8 | virtual ~BSFaceGenKeyframe(); // 00
9 | virtual bool Unk_01(RE::BSTArray& a_arr) = 0; // 01
10 | // Linear interpolation between keyframes.
11 | virtual bool Interpolate(BSFaceGenKeyframe* a_keyframe1, BSFaceGenKeyframe* a_keyframe2, float a_k) = 0; // 02
12 | // Linear interpolation between keyframes.
13 | virtual bool Interpolate(BSFaceGenKeyframe* a_keyframe, float a_k, bool a_ignoreSmall, bool a_copyBig) = 0; // 03
14 | virtual void Reset(bool a_initToZero) = 0; // 04
15 | virtual BSFaceGenKeyframe* Clone() = 0; // 05
16 | virtual void Copy(BSFaceGenKeyframe* a_keyframe) = 0; // 06
17 | virtual bool NotEqual(BSFaceGenKeyframe* a_keyframe) = 0; // 07
18 | virtual float GetMaxValue() = 0; // 08
19 | virtual bool IsZero() = 0; // 09
20 | virtual bool TransitionUpdate(float a_timeDelta, BSFaceGenKeyframe* a_keyframe) = 0; // 0A
21 | virtual bool NotZero() = 0; // 0B
22 | virtual bool IsKeyframeMultiple(); // 0C { return false; };
23 | virtual bool IsKeyframeExclusive(); // 0D { return false; };
24 |
25 | std::int32_t type; // 08
26 | float timer; // 0C
27 | };
28 |
29 | static_assert(sizeof(BSFaceGenKeyframe) == 0x10);
30 | }
--------------------------------------------------------------------------------
/src/mfgfix/BSFaceGenKeyframeMultiple.cpp:
--------------------------------------------------------------------------------
1 | #include "BSFaceGenKeyframeMultiple.h"
2 | #include "Offsets.h"
3 |
4 | namespace MfgFix
5 | {
6 | namespace {
7 | const char* GetExpressionName(std::uint32_t a_expression)
8 | {
9 | using func_t = decltype(&GetExpressionName);
10 | REL::Relocation func(Offsets::GetExpressionName);
11 | return func(a_expression);
12 | }
13 |
14 | const char* GetModifierName(std::uint32_t a_modifier)
15 | {
16 | using func_t = decltype(&GetModifierName);
17 | REL::Relocation func(Offsets::GetModifierName);
18 | return func(a_modifier);
19 | }
20 |
21 | const char* GetPhonemeName(std::uint32_t a_phoneme)
22 | {
23 | using func_t = decltype(&GetPhonemeName);
24 | REL::Relocation func(Offsets::GetPhonemeName);
25 | return func(a_phoneme);
26 | }
27 |
28 | const char* GetCustomName(std::uint32_t a_custom)
29 | {
30 | using func_t = decltype(&GetCustomName);
31 | REL::Relocation func(Offsets::GetCustomName);
32 | return func(a_custom);
33 | }
34 | }
35 |
36 | void BSFaceGenKeyframeMultiple::SetValue(std::uint32_t a_idx, float a_value)
37 | {
38 | if (a_idx < count) {
39 | values[a_idx] = a_value;
40 | isUpdated = false;
41 | }
42 | }
43 |
44 | void BSFaceGenKeyframeMultiple::Reset()
45 | {
46 | std::fill_n(values, count, 0.0f);
47 | isUpdated = false;
48 | }
49 |
50 | std::string BSFaceGenKeyframeMultiple::GetValueName(Type a_type, std::uint32_t a_idx)
51 | {
52 | const char* name{ nullptr };
53 |
54 | switch (a_type) {
55 | case Type::Expression: {
56 | name = GetExpressionName(a_idx);
57 | break;
58 | }
59 | case Type::Modifier: {
60 | name = GetModifierName(a_idx);
61 | break;
62 | }
63 | case Type::Phoneme: {
64 | name = GetPhonemeName(a_idx);
65 | break;
66 | }
67 | case Type::Custom: {
68 | name = GetCustomName(a_idx);
69 | break;
70 | }
71 | }
72 |
73 | return name ? name : "";
74 | }
75 | }
--------------------------------------------------------------------------------
/src/mfgfix/BSFaceGenKeyframeMultiple.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "BSFaceGenKeyframe.h"
4 |
5 | namespace MfgFix
6 | {
7 | class BSFaceGenKeyframeMultiple: public BSFaceGenKeyframe
8 | {
9 | public:
10 | enum class Type : std::int32_t
11 | {
12 | Undefined = -1,
13 | Phoneme,
14 | Expression,
15 | Modifier,
16 | Custom
17 | };
18 |
19 | enum Expression : std::uint32_t
20 | {
21 | DialogueAnger = 0,
22 | DialogueFear,
23 | DialogueHappy,
24 | DialogueSad,
25 | DialogueSurprise,
26 | DialoguePuzzled,
27 | DialogueDisgusted,
28 | MoodNeutral,
29 | MoodAnger,
30 | MoodFear,
31 | MoodHappy,
32 | MoodSad,
33 | MoodSurprise,
34 | MoodPuzzled,
35 | MoodDisgusted,
36 | CombatAnger,
37 | CombatShout
38 | };
39 |
40 | enum Modifier : std::uint32_t
41 | {
42 | BlinkLeft = 0,
43 | BlinkRight,
44 | BrowDownLeft,
45 | BrowDownRight,
46 | BrowInLeft,
47 | BrowInRight,
48 | BrowUpLeft,
49 | BrowUpRight,
50 | LookDown,
51 | LookLeft,
52 | LookRight,
53 | LookUp,
54 | SquintLeft,
55 | SquintRight,
56 | HeadPitch,
57 | HeadRoll,
58 | HeadYaw
59 | };
60 |
61 | enum Phoneme : std::uint32_t
62 | {
63 | Aah = 0,
64 | BigAah,
65 | BMP,
66 | ChJSh,
67 | DST,
68 | Eee,
69 | Eh,
70 | FV,
71 | I,
72 | K,
73 | N,
74 | Oh,
75 | OohQ,
76 | R,
77 | Th,
78 | W
79 | };
80 |
81 | enum Custom : std::uint32_t
82 | {
83 | SkinnyMorph = 0
84 | };
85 |
86 | ~BSFaceGenKeyframeMultiple() override; // 00
87 | bool Unk_01(RE::BSTArray& a_arr) override; // 01
88 | bool Interpolate(BSFaceGenKeyframe* a_keyframe1, BSFaceGenKeyframe* a_keyframe2, float a_k) override; // 02
89 | bool Interpolate(BSFaceGenKeyframe* a_keyframe, float a_k, bool a_ignoreSmall, bool a_copyBig) override; // 03
90 | void Reset(bool a_initToZero) override; // 04
91 | BSFaceGenKeyframe* Clone() override; // 05
92 | void Copy(BSFaceGenKeyframe* a_keyframe) override; // 06
93 | bool NotEqual(BSFaceGenKeyframe* a_keyframe) override; // 07
94 | float GetMaxValue() override; // 08
95 | bool IsZero() override; // 09
96 | bool TransitionUpdate(float a_timeDelta, BSFaceGenKeyframe* a_keyframe) override; // 0A
97 | bool NotZero() override; // 0B
98 | bool IsKeyframeMultiple() override; // 0C { return true; };
99 | bool IsKeyframeExclusive() override; // 0D { return false; };
100 |
101 | // Is value in range [0, 1].
102 | virtual bool IsValueValid(std::uint32_t a_idx); // 0E
103 | virtual void Allocate(std::uint32_t a_count, bool a_initToZero); // 0F
104 |
105 | static std::string GetValueName(Type a_type, std::uint32_t a_idx);
106 |
107 | void SetValue(std::uint32_t a_idx, float a_value);
108 | void Reset();
109 |
110 | float* values; // 10
111 | std::uint32_t count; // 18
112 | bool isUpdated; // 1C
113 | std::uint8_t pad1D[3]; // 1D
114 | };
115 |
116 | static_assert(sizeof(BSFaceGenKeyframeMultiple) == 0x20);
117 | }
--------------------------------------------------------------------------------
/src/mfgfix/ConsoleCommands.cpp:
--------------------------------------------------------------------------------
1 | #include "ConsoleCommands.h"
2 | #include "BSFaceGenAnimationData.h"
3 | #include "Offsets.h"
4 |
5 | namespace MfgFix::ConsoleCommands
6 | {
7 | using Keyframe = BSFaceGenAnimationData::Keyframe;
8 |
9 | uintptr_t ModifyFaceGenCommandAddr{ 0 };
10 |
11 | void SetValue(RE::TESObjectREFR* a_ref, Keyframe::Type a_keyframeType, std::uint32_t a_idx, float a_value)
12 | {
13 | if (!a_ref) {
14 | return;
15 | }
16 |
17 | auto animData = reinterpret_cast(a_ref->GetFaceGenAnimationData());
18 |
19 | if (!animData) {
20 | return;
21 | }
22 |
23 | RE::BSSpinLockGuard locker(animData->lock);
24 |
25 | switch (a_keyframeType) {
26 | case Keyframe::Type::Phoneme: {
27 | animData->phoneme2.SetValue(a_idx, a_value);
28 | break;
29 | }
30 | case Keyframe::Type::Expression: {
31 | animData->expressionOverride = false;
32 | animData->SetExpressionOverride(a_idx, a_value);
33 | animData->expressionOverride = true;
34 | break;
35 | }
36 | case Keyframe::Type::Modifier: {
37 | animData->modifier2.SetValue(a_idx, a_value);
38 | break;
39 | }
40 | case Keyframe::Type::Custom: {
41 | animData->custom2.SetValue(a_idx, a_value);
42 | break;
43 | }
44 | }
45 | }
46 |
47 | void PrintInfo(RE::TESObjectREFR* a_ref, Keyframe::Type a_keyframeType)
48 | {
49 | if (!a_ref) {
50 | return;
51 | }
52 |
53 | auto animData = reinterpret_cast(a_ref->GetFaceGenAnimationData());
54 |
55 | if (!animData) {
56 | return;
57 | }
58 |
59 | auto console = RE::ConsoleLog::GetSingleton();
60 |
61 | if (!console) {
62 | return;
63 | }
64 |
65 | RE::BSSpinLockGuard locker(animData->lock);
66 |
67 | Keyframe* keyframe{ nullptr };
68 |
69 | switch (a_keyframeType) {
70 | case Keyframe::Type::Phoneme: {
71 | keyframe = &animData->phoneme2;
72 | break;
73 | }
74 | case Keyframe::Type::Expression: {
75 | keyframe = &animData->expression1;
76 | break;
77 | }
78 | case Keyframe::Type::Modifier: {
79 | keyframe = &animData->modifier2;
80 | break;
81 | }
82 | case Keyframe::Type::Custom: {
83 | keyframe = &animData->custom2;
84 | break;
85 | }
86 | }
87 |
88 | if (!keyframe) {
89 | return;
90 | }
91 |
92 | for (std::uint32_t i = 0; i < keyframe->count; ++i) {
93 | console->Print(fmt::format("{:2d} {:3.0f} {:s}", i, keyframe->values[i] * 100.0f, Keyframe::GetValueName(a_keyframeType, i)).c_str());
94 | }
95 | }
96 |
97 | void Reset(RE::TESObjectREFR* a_ref)
98 | {
99 | if (!a_ref) {
100 | return;
101 | }
102 |
103 | auto animData = reinterpret_cast(a_ref->GetFaceGenAnimationData());
104 |
105 | if (!animData) {
106 | return;
107 | }
108 |
109 | RE::BSSpinLockGuard locker(animData->lock);
110 |
111 | animData->ClearExpressionOverride();
112 | animData->Reset(0.0f, true, true, true, false);
113 | }
114 |
115 | bool ModifyFaceGenCommand(const RE::SCRIPT_PARAMETER* a_paramInfo, RE::SCRIPT_FUNCTION::ScriptData* a_scriptData, RE::TESObjectREFR* a_thisObj, RE::TESObjectREFR* a_containingObj, RE::Script* a_scriptObj, RE::ScriptLocals* a_locals, double& a_result, std::uint32_t& a_opcodeOffsetPtr)
116 | {
117 | using func_t = decltype(&ModifyFaceGenCommand);
118 | REL::Relocation func(ModifyFaceGenCommandAddr);
119 | return func(a_paramInfo, a_scriptData, a_thisObj, a_containingObj, a_scriptObj, a_locals, a_result, a_opcodeOffsetPtr);
120 | }
121 |
122 | bool ModifyFaceGenCommandHook(const RE::SCRIPT_PARAMETER* a_paramInfo, RE::SCRIPT_FUNCTION::ScriptData* a_scriptData, RE::TESObjectREFR* a_thisObj, RE::TESObjectREFR* a_containingObj, RE::Script* a_scriptObj, RE::ScriptLocals* a_locals, double& a_result, std::uint32_t& a_opcodeOffsetPtr)
123 | {
124 | auto thisObj = a_thisObj ? a_thisObj : RE::PlayerCharacter::GetSingleton();
125 |
126 | if (a_scriptData && a_paramInfo) {
127 | auto param1 = a_scriptData->numParams > 0 && a_paramInfo[0].paramType == RE::SCRIPT_PARAM_TYPE::kChar ? a_scriptData->GetChunk()->AsString() : nullptr;
128 | auto param2 = a_scriptData->numParams > 1 && a_paramInfo[1].paramType == RE::SCRIPT_PARAM_TYPE::kInt && param1 ? param1->GetNext()->AsInteger() : nullptr;
129 | auto param3 = a_scriptData->numParams > 2 && a_paramInfo[2].paramType == RE::SCRIPT_PARAM_TYPE::kInt && param2 ? param2->GetNext()->AsInteger() : nullptr;
130 |
131 | if (param1) {
132 | if (_strnicmp(param1->str, "expression", param1->length) == 0) {
133 | if (param2 && param3) {
134 | SetValue(thisObj, Keyframe::Type::Expression, param2->value, param3->value / 100.0f);
135 | } else if (!param2 && !param3) {
136 | PrintInfo(thisObj, Keyframe::Type::Expression);
137 | }
138 | return true;
139 | } else if (_strnicmp(param1->str, "modifier", param1->length) == 0) {
140 | if (param2 && param3) {
141 | SetValue(thisObj, Keyframe::Type::Modifier, param2->value, param3->value / 100.0f);
142 | } else if (!param2 && !param3) {
143 | PrintInfo(thisObj, Keyframe::Type::Modifier);
144 | }
145 | return true;
146 | } else if (_strnicmp(param1->str, "phoneme", param1->length) == 0) {
147 | if (param2 && param3) {
148 | SetValue(thisObj, Keyframe::Type::Phoneme, param2->value, param3->value / 100.0f);
149 | } else if (!param2 && !param3) {
150 | PrintInfo(thisObj, Keyframe::Type::Phoneme);
151 | }
152 | return true;
153 | } else if (_strnicmp(param1->str, "custom", param1->length) == 0) {
154 | if (param2 && param3) {
155 | SetValue(thisObj, Keyframe::Type::Custom, param2->value, param3->value / 100.0f);
156 | } else if (!param2 && !param3) {
157 | PrintInfo(thisObj, Keyframe::Type::Custom);
158 | }
159 | return true;
160 | } else if (_strnicmp(param1->str, "reset", param1->length) == 0) {
161 | Reset(thisObj);
162 | return true;
163 | }
164 | }
165 | }
166 |
167 | return ModifyFaceGenCommand(a_paramInfo, a_scriptData, a_thisObj, a_containingObj, a_scriptObj, a_locals, a_result, a_opcodeOffsetPtr);
168 | }
169 |
170 | void Init()
171 | {
172 | ModifyFaceGenCommandAddr = Offsets::ModifyFaceGenCommand.address();
173 |
174 | DetourTransactionBegin();
175 | DetourUpdateThread(GetCurrentThread());
176 | DetourAttach(reinterpret_cast(&ModifyFaceGenCommandAddr), reinterpret_cast(ModifyFaceGenCommandHook));
177 |
178 | if (DetourTransactionCommit() != NO_ERROR) {
179 | spdlog::error("failed to attach detour");
180 | }
181 | }
182 |
183 | }
--------------------------------------------------------------------------------
/src/mfgfix/ConsoleCommands.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 |
4 | namespace MfgFix::ConsoleCommands
5 | {
6 | void Init();
7 | }
--------------------------------------------------------------------------------
/src/mfgfix/MfgConsoleFunc.cpp:
--------------------------------------------------------------------------------
1 | #include "MfgConsoleFunc.h"
2 | #include "BSFaceGenAnimationData.h"
3 |
4 | namespace MfgFix::MfgConsoleFunc
5 | {
6 | namespace
7 | {
8 | enum Mode : std::int32_t
9 | {
10 | Reset = -1,
11 | Phoneme,
12 | Modifier,
13 | ExpressionValue,
14 | ExpressionId
15 | };
16 | }
17 |
18 | std::uint32_t GetActiveExpression(const BSFaceGenAnimationData& a_animData)
19 | {
20 | std::uint32_t expression = BSFaceGenAnimationData::Expression::MoodNeutral;
21 |
22 | for (std::uint32_t i = 0; i < a_animData.expression1.count; ++i) {
23 | if (a_animData.expression1.values[i] > a_animData.expression1.values[expression]) {
24 | expression = i;
25 | }
26 | }
27 |
28 | return expression;
29 | }
30 |
31 | bool SetPhonemeModifier(RE::StaticFunctionTag*, RE::Actor* a_actor, std::int32_t a_mode, std::uint32_t a_id, std::int32_t a_value)
32 | {
33 | if (!a_actor) {
34 | return false;
35 | }
36 |
37 | auto animData = reinterpret_cast(a_actor->GetFaceGenAnimationData());
38 |
39 | if (!animData) {
40 | return false;
41 | }
42 |
43 | RE::BSSpinLockGuard locker(animData->lock);
44 |
45 | switch (a_mode) {
46 | case Mode::Reset: {
47 | animData->ClearExpressionOverride();
48 | animData->Reset(0.0f, true, true, true, false);
49 | return true;
50 | }
51 | case Mode::Phoneme: {
52 | animData->phoneme2.SetValue(a_id, std::clamp(a_value, 0, 100) / 100.0f);
53 | return true;
54 | }
55 | case Mode::Modifier: {
56 | animData->modifier2.SetValue(a_id, std::clamp(a_value, 0, 100) / 100.0f);
57 | return true;
58 | }
59 | }
60 |
61 | return false;
62 | }
63 |
64 | std::int32_t GetPhonemeModifier(RE::StaticFunctionTag*, RE::Actor* a_actor, std::int32_t a_mode, std::uint32_t a_id)
65 | {
66 | if (!a_actor) {
67 | return -1;
68 | }
69 |
70 | auto animData = reinterpret_cast(a_actor->GetFaceGenAnimationData());
71 |
72 | if (!animData) {
73 | return -1;
74 | }
75 |
76 | RE::BSSpinLockGuard locker(animData->lock);
77 |
78 | switch(a_mode) {
79 | case Mode::Phoneme: {
80 | return a_id < animData->phoneme2.count ? std::lround(animData->phoneme2.values[a_id] * 100.0f) : 0;
81 | }
82 | case Mode::Modifier: {
83 | return a_id < animData->modifier2.count ? std::lround(animData->modifier2.values[a_id] * 100.0f) : 0;
84 | }
85 | case Mode::ExpressionValue: {
86 | return a_id < animData->expression1.count ? std::lround(animData->expression1.values[a_id] * 100.0f) : 0;
87 | }
88 | case Mode::ExpressionId: {
89 | return GetActiveExpression(*animData);
90 | }
91 | }
92 |
93 | return -1;
94 | }
95 |
96 | void Register()
97 | {
98 | SKSE::GetPapyrusInterface()->Register([](RE::BSScript::IVirtualMachine* a_vm) {
99 | a_vm->RegisterFunction("SetPhonemeModifier", "MfgConsoleFunc", SetPhonemeModifier);
100 | a_vm->RegisterFunction("GetPhonemeModifier", "MfgConsoleFunc", GetPhonemeModifier);
101 |
102 | return true;
103 | });
104 | }
105 | }
--------------------------------------------------------------------------------
/src/mfgfix/MfgConsoleFunc.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace MfgFix::MfgConsoleFunc
4 | {
5 | void Register();
6 | }
--------------------------------------------------------------------------------
/src/mfgfix/Offsets.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 |
4 | namespace MfgFix::Offsets
5 | {
6 |
7 | namespace
8 | {
9 | static constexpr REL::ID ModifyFaceGenCommand(static_cast(23017));
10 | static constexpr REL::ID GetExpressionName(static_cast(27007));
11 | static constexpr REL::ID GetModifierName(static_cast(27008));
12 | static constexpr REL::ID GetPhonemeName(static_cast(27009));
13 | static constexpr REL::ID GetCustomName(static_cast(27010));
14 | }
15 |
16 | namespace BSFaceGenAnimationData
17 | {
18 | static constexpr REL::ID KeyframesUpdate(static_cast(26598));
19 | static constexpr REL::ID SetExpressionOverride(static_cast(26594));
20 | static constexpr REL::ID sub_3DB770(static_cast(26593));
21 | static constexpr REL::ID Reset(static_cast(26586));
22 | }
23 |
24 | namespace BSFaceGenNiNode
25 | {
26 | static constexpr REL::ID sub_3F1800(static_cast(26998));
27 | static constexpr REL::ID sub_3F0C90(static_cast(26988));
28 | }
29 |
30 | namespace Papyrus
31 | {
32 | namespace Actor
33 | {
34 | static constexpr REL::ID SetExpressionOverride(static_cast(54748));
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/mfgfix/Settings.cpp:
--------------------------------------------------------------------------------
1 | #include "Settings.h"
2 | #include "SimpleIni.h"
3 |
4 | namespace MfgFix
5 | {
6 | namespace
7 | {
8 | std::filesystem::path GetIniPath()
9 | {
10 | wchar_t buf[4096] = L"";
11 |
12 | std::uint32_t size = GetModuleFileNameW(NULL, buf, static_cast(std::size(buf)));
13 |
14 | if (size == 0 || size == std::size(buf)) {
15 | return "";
16 | }
17 |
18 | std::filesystem::path path{ buf };
19 |
20 | return path.replace_filename(L"Data\\SKSE\\Plugins\\mfgfix.ini");
21 | }
22 | }
23 |
24 | Settings& Settings::Get()
25 | {
26 | static Settings settings;
27 |
28 | return settings;
29 | }
30 |
31 | void Settings::Read()
32 | {
33 | CSimpleIniA ini;
34 | auto path = GetIniPath();
35 |
36 | if (ini.LoadFile(path.c_str()) != SI_Error::SI_OK) {
37 | return;
38 | }
39 |
40 | eyesBlinking.fBlinkDownTime = static_cast(ini.GetDoubleValue("EyesBlinking", "fBlinkDownTime", eyesBlinking.fBlinkDownTime));
41 | eyesBlinking.fBlinkUpTime = static_cast(ini.GetDoubleValue("EyesBlinking", "fBlinkUpTime", eyesBlinking.fBlinkUpTime));
42 | eyesBlinking.fBlinkDelayMin = static_cast(ini.GetDoubleValue("EyesBlinking", "fBlinkDelayMin", eyesBlinking.fBlinkDelayMin));
43 | eyesBlinking.fBlinkDelayMax = static_cast(ini.GetDoubleValue("EyesBlinking", "fBlinkDelayMax", eyesBlinking.fBlinkDelayMax));
44 | eyesMovement.fTrackSpeed = static_cast(ini.GetDoubleValue("EyesMovement", "fTrackSpeed", eyesMovement.fTrackSpeed));
45 | eyesMovement.fTrackEyeXY = static_cast(ini.GetDoubleValue("EyesMovement", "fTrackEyeXY", eyesMovement.fTrackEyeXY));
46 | eyesMovement.fTrackEyeZ = static_cast(ini.GetDoubleValue("EyesMovement", "fTrackEyeZ", eyesMovement.fTrackEyeZ));
47 | eyesMovement.fEyeHeadingMinOffsetEmotionAngry = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionAngry", eyesMovement.fEyeHeadingMinOffsetEmotionAngry));
48 | eyesMovement.fEyeHeadingMaxOffsetEmotionAngry = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionAngry", eyesMovement.fEyeHeadingMaxOffsetEmotionAngry));
49 | eyesMovement.fEyePitchMinOffsetEmotionAngry = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionAngry", eyesMovement.fEyePitchMinOffsetEmotionAngry));
50 | eyesMovement.fEyePitchMaxOffsetEmotionAngry = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionAngry", eyesMovement.fEyePitchMaxOffsetEmotionAngry));
51 | eyesMovement.fEyeOffsetDelayMinEmotionAngry = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionAngry", eyesMovement.fEyeOffsetDelayMinEmotionAngry));
52 | eyesMovement.fEyeOffsetDelayMaxEmotionAngry = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionAngry", eyesMovement.fEyeOffsetDelayMaxEmotionAngry));
53 | eyesMovement.fEyeHeadingMinOffsetEmotionHappy = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionHappy", eyesMovement.fEyeHeadingMinOffsetEmotionHappy));
54 | eyesMovement.fEyeHeadingMaxOffsetEmotionHappy = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionHappy", eyesMovement.fEyeHeadingMaxOffsetEmotionHappy));
55 | eyesMovement.fEyePitchMinOffsetEmotionHappy = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionHappy", eyesMovement.fEyePitchMinOffsetEmotionHappy));
56 | eyesMovement.fEyePitchMaxOffsetEmotionHappy = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionHappy", eyesMovement.fEyePitchMaxOffsetEmotionHappy));
57 | eyesMovement.fEyeOffsetDelayMinEmotionHappy = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionHappy", eyesMovement.fEyeOffsetDelayMinEmotionHappy));
58 | eyesMovement.fEyeOffsetDelayMaxEmotionHappy = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionHappy", eyesMovement.fEyeOffsetDelayMaxEmotionHappy));
59 | eyesMovement.fEyeHeadingMinOffsetEmotionSurprise = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionSurprise", eyesMovement.fEyeHeadingMinOffsetEmotionSurprise));
60 | eyesMovement.fEyeHeadingMaxOffsetEmotionSurprise = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionSurprise", eyesMovement.fEyeHeadingMaxOffsetEmotionSurprise));
61 | eyesMovement.fEyePitchMinOffsetEmotionSurprise = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionSurprise", eyesMovement.fEyePitchMinOffsetEmotionSurprise));
62 | eyesMovement.fEyePitchMaxOffsetEmotionSurprise = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionSurprise", eyesMovement.fEyePitchMaxOffsetEmotionSurprise));
63 | eyesMovement.fEyeOffsetDelayMinEmotionSurprise = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionSurprise", eyesMovement.fEyeOffsetDelayMinEmotionSurprise));
64 | eyesMovement.fEyeOffsetDelayMaxEmotionSurprise = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionSurprise", eyesMovement.fEyeOffsetDelayMaxEmotionSurprise));
65 | eyesMovement.fEyeHeadingMinOffsetEmotionSad = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionSad", eyesMovement.fEyeHeadingMinOffsetEmotionSad));
66 | eyesMovement.fEyeHeadingMaxOffsetEmotionSad = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionSad", eyesMovement.fEyeHeadingMaxOffsetEmotionSad));
67 | eyesMovement.fEyePitchMinOffsetEmotionSad = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionSad", eyesMovement.fEyePitchMinOffsetEmotionSad));
68 | eyesMovement.fEyePitchMaxOffsetEmotionSad = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionSad", eyesMovement.fEyePitchMaxOffsetEmotionSad));
69 | eyesMovement.fEyeOffsetDelayMinEmotionSad = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionSad", eyesMovement.fEyeOffsetDelayMinEmotionSad));
70 | eyesMovement.fEyeOffsetDelayMaxEmotionSad = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionSad", eyesMovement.fEyeOffsetDelayMaxEmotionSad));
71 | eyesMovement.fEyeHeadingMinOffsetEmotionFear = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionFear", eyesMovement.fEyeHeadingMinOffsetEmotionFear));
72 | eyesMovement.fEyeHeadingMaxOffsetEmotionFear = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionFear", eyesMovement.fEyeHeadingMaxOffsetEmotionFear));
73 | eyesMovement.fEyePitchMinOffsetEmotionFear = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionFear", eyesMovement.fEyePitchMinOffsetEmotionFear));
74 | eyesMovement.fEyePitchMaxOffsetEmotionFear = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionFear", eyesMovement.fEyePitchMaxOffsetEmotionFear));
75 | eyesMovement.fEyeOffsetDelayMinEmotionFear = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionFear", eyesMovement.fEyeOffsetDelayMinEmotionFear));
76 | eyesMovement.fEyeOffsetDelayMaxEmotionFear = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionFear", eyesMovement.fEyeOffsetDelayMaxEmotionFear));
77 | eyesMovement.fEyeHeadingMinOffsetEmotionNeutral = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionNeutral", eyesMovement.fEyeHeadingMinOffsetEmotionNeutral));
78 | eyesMovement.fEyeHeadingMaxOffsetEmotionNeutral = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionNeutral", eyesMovement.fEyeHeadingMaxOffsetEmotionNeutral));
79 | eyesMovement.fEyePitchMinOffsetEmotionNeutral = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionNeutral", eyesMovement.fEyePitchMinOffsetEmotionNeutral));
80 | eyesMovement.fEyePitchMaxOffsetEmotionNeutral = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionNeutral", eyesMovement.fEyePitchMaxOffsetEmotionNeutral));
81 | eyesMovement.fEyeOffsetDelayMinEmotionNeutral = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionNeutral", eyesMovement.fEyeOffsetDelayMinEmotionNeutral));
82 | eyesMovement.fEyeOffsetDelayMaxEmotionNeutral = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionNeutral", eyesMovement.fEyeOffsetDelayMaxEmotionNeutral));
83 | eyesMovement.fEyeHeadingMinOffsetEmotionPuzzled = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionPuzzled", eyesMovement.fEyeHeadingMinOffsetEmotionPuzzled));
84 | eyesMovement.fEyeHeadingMaxOffsetEmotionPuzzled = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionPuzzled", eyesMovement.fEyeHeadingMaxOffsetEmotionPuzzled));
85 | eyesMovement.fEyePitchMinOffsetEmotionPuzzled = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionPuzzled", eyesMovement.fEyePitchMinOffsetEmotionPuzzled));
86 | eyesMovement.fEyePitchMaxOffsetEmotionPuzzled = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionPuzzled", eyesMovement.fEyePitchMaxOffsetEmotionPuzzled));
87 | eyesMovement.fEyeOffsetDelayMinEmotionPuzzled = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionPuzzled", eyesMovement.fEyeOffsetDelayMinEmotionPuzzled));
88 | eyesMovement.fEyeOffsetDelayMaxEmotionPuzzled = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionPuzzled", eyesMovement.fEyeOffsetDelayMaxEmotionPuzzled));
89 | eyesMovement.fEyeHeadingMinOffsetEmotionDisgusted = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionDisgusted", eyesMovement.fEyeHeadingMinOffsetEmotionDisgusted));
90 | eyesMovement.fEyeHeadingMaxOffsetEmotionDisgusted = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionDisgusted", eyesMovement.fEyeHeadingMaxOffsetEmotionDisgusted));
91 | eyesMovement.fEyePitchMinOffsetEmotionDisgusted = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionDisgusted", eyesMovement.fEyePitchMinOffsetEmotionDisgusted));
92 | eyesMovement.fEyePitchMaxOffsetEmotionDisgusted = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionDisgusted", eyesMovement.fEyePitchMaxOffsetEmotionDisgusted));
93 | eyesMovement.fEyeOffsetDelayMinEmotionDisgusted = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionDisgusted", eyesMovement.fEyeOffsetDelayMinEmotionDisgusted));
94 | eyesMovement.fEyeOffsetDelayMaxEmotionDisgusted = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionDisgusted", eyesMovement.fEyeOffsetDelayMaxEmotionDisgusted));
95 | eyesMovement.fEyeHeadingMinOffsetEmotionCombatAnger = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionCombatAnger", eyesMovement.fEyeHeadingMinOffsetEmotionCombatAnger));
96 | eyesMovement.fEyeHeadingMaxOffsetEmotionCombatAnger = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionCombatAnger", eyesMovement.fEyeHeadingMaxOffsetEmotionCombatAnger));
97 | eyesMovement.fEyePitchMinOffsetEmotionCombatAnger = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionCombatAnger", eyesMovement.fEyePitchMinOffsetEmotionCombatAnger));
98 | eyesMovement.fEyePitchMaxOffsetEmotionCombatAnger = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionCombatAnger", eyesMovement.fEyePitchMaxOffsetEmotionCombatAnger));
99 | eyesMovement.fEyeOffsetDelayMinEmotionCombatAnger = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionCombatAnger", eyesMovement.fEyeOffsetDelayMinEmotionCombatAnger));
100 | eyesMovement.fEyeOffsetDelayMaxEmotionCombatAnger = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionCombatAnger", eyesMovement.fEyeOffsetDelayMaxEmotionCombatAnger));
101 | eyesMovement.fEyeHeadingMinOffsetEmotionCombatShout = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionCombatShout", eyesMovement.fEyeHeadingMinOffsetEmotionCombatShout));
102 | eyesMovement.fEyeHeadingMaxOffsetEmotionCombatShout = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionCombatShout", eyesMovement.fEyeHeadingMaxOffsetEmotionCombatShout));
103 | eyesMovement.fEyePitchMinOffsetEmotionCombatShout = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionCombatShout", eyesMovement.fEyePitchMinOffsetEmotionCombatShout));
104 | eyesMovement.fEyePitchMaxOffsetEmotionCombatShout = static_cast(ini.GetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionCombatShout", eyesMovement.fEyePitchMaxOffsetEmotionCombatShout));
105 | eyesMovement.fEyeOffsetDelayMinEmotionCombatShout = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionCombatShout", eyesMovement.fEyeOffsetDelayMinEmotionCombatShout));
106 | eyesMovement.fEyeOffsetDelayMaxEmotionCombatShout = static_cast(ini.GetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionCombatShout", eyesMovement.fEyeOffsetDelayMaxEmotionCombatShout));
107 | }
108 |
109 | void Settings::Write()
110 | {
111 | CSimpleIniA ini;
112 | auto path = GetIniPath();
113 |
114 | ini.LoadFile(path.c_str());
115 |
116 | ini.SetDoubleValue("EyesBlinking", "fBlinkDownTime", eyesBlinking.fBlinkDownTime);
117 | ini.SetDoubleValue("EyesBlinking", "fBlinkUpTime", eyesBlinking.fBlinkUpTime);
118 | ini.SetDoubleValue("EyesBlinking", "fBlinkDelayMin", eyesBlinking.fBlinkDelayMin);
119 | ini.SetDoubleValue("EyesBlinking", "fBlinkDelayMax", eyesBlinking.fBlinkDelayMax);
120 | ini.SetDoubleValue("EyesMovement", "fTrackSpeed", eyesMovement.fTrackSpeed);
121 | ini.SetDoubleValue("EyesMovement", "fTrackEyeXY", eyesMovement.fTrackEyeXY);
122 | ini.SetDoubleValue("EyesMovement", "fTrackEyeZ", eyesMovement.fTrackEyeZ);
123 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionAngry", eyesMovement.fEyeHeadingMinOffsetEmotionAngry);
124 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionAngry", eyesMovement.fEyeHeadingMaxOffsetEmotionAngry);
125 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionAngry", eyesMovement.fEyePitchMinOffsetEmotionAngry);
126 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionAngry", eyesMovement.fEyePitchMaxOffsetEmotionAngry);
127 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionAngry", eyesMovement.fEyeOffsetDelayMinEmotionAngry);
128 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionAngry", eyesMovement.fEyeOffsetDelayMaxEmotionAngry);
129 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionHappy", eyesMovement.fEyeHeadingMinOffsetEmotionHappy);
130 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionHappy", eyesMovement.fEyeHeadingMaxOffsetEmotionHappy);
131 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionHappy", eyesMovement.fEyePitchMinOffsetEmotionHappy);
132 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionHappy", eyesMovement.fEyePitchMaxOffsetEmotionHappy);
133 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionHappy", eyesMovement.fEyeOffsetDelayMinEmotionHappy);
134 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionHappy", eyesMovement.fEyeOffsetDelayMaxEmotionHappy);
135 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionSurprise", eyesMovement.fEyeHeadingMinOffsetEmotionSurprise);
136 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionSurprise", eyesMovement.fEyeHeadingMaxOffsetEmotionSurprise);
137 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionSurprise", eyesMovement.fEyePitchMinOffsetEmotionSurprise);
138 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionSurprise", eyesMovement.fEyePitchMaxOffsetEmotionSurprise);
139 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionSurprise", eyesMovement.fEyeOffsetDelayMinEmotionSurprise);
140 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionSurprise", eyesMovement.fEyeOffsetDelayMaxEmotionSurprise);
141 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionSad", eyesMovement.fEyeHeadingMinOffsetEmotionSad);
142 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionSad", eyesMovement.fEyeHeadingMaxOffsetEmotionSad);
143 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionSad", eyesMovement.fEyePitchMinOffsetEmotionSad);
144 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionSad", eyesMovement.fEyePitchMaxOffsetEmotionSad);
145 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionSad", eyesMovement.fEyeOffsetDelayMinEmotionSad);
146 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionSad", eyesMovement.fEyeOffsetDelayMaxEmotionSad);
147 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionFear", eyesMovement.fEyeHeadingMinOffsetEmotionFear);
148 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionFear", eyesMovement.fEyeHeadingMaxOffsetEmotionFear);
149 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionFear", eyesMovement.fEyePitchMinOffsetEmotionFear);
150 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionFear", eyesMovement.fEyePitchMaxOffsetEmotionFear);
151 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionFear", eyesMovement.fEyeOffsetDelayMinEmotionFear);
152 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionFear", eyesMovement.fEyeOffsetDelayMaxEmotionFear);
153 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionNeutral", eyesMovement.fEyeHeadingMinOffsetEmotionNeutral);
154 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionNeutral", eyesMovement.fEyeHeadingMaxOffsetEmotionNeutral);
155 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionNeutral", eyesMovement.fEyePitchMinOffsetEmotionNeutral);
156 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionNeutral", eyesMovement.fEyePitchMaxOffsetEmotionNeutral);
157 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionNeutral", eyesMovement.fEyeOffsetDelayMinEmotionNeutral);
158 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionNeutral", eyesMovement.fEyeOffsetDelayMaxEmotionNeutral);
159 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionPuzzled", eyesMovement.fEyeHeadingMinOffsetEmotionPuzzled);
160 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionPuzzled", eyesMovement.fEyeHeadingMaxOffsetEmotionPuzzled);
161 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionPuzzled", eyesMovement.fEyePitchMinOffsetEmotionPuzzled);
162 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionPuzzled", eyesMovement.fEyePitchMaxOffsetEmotionPuzzled);
163 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionPuzzled", eyesMovement.fEyeOffsetDelayMinEmotionPuzzled);
164 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionPuzzled", eyesMovement.fEyeOffsetDelayMaxEmotionPuzzled);
165 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionDisgusted", eyesMovement.fEyeHeadingMinOffsetEmotionDisgusted);
166 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionDisgusted", eyesMovement.fEyeHeadingMaxOffsetEmotionDisgusted);
167 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionDisgusted", eyesMovement.fEyePitchMinOffsetEmotionDisgusted);
168 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionDisgusted", eyesMovement.fEyePitchMaxOffsetEmotionDisgusted);
169 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionDisgusted", eyesMovement.fEyeOffsetDelayMinEmotionDisgusted);
170 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionDisgusted", eyesMovement.fEyeOffsetDelayMaxEmotionDisgusted);
171 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionCombatAnger", eyesMovement.fEyeHeadingMinOffsetEmotionCombatAnger);
172 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionCombatAnger", eyesMovement.fEyeHeadingMaxOffsetEmotionCombatAnger);
173 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionCombatAnger", eyesMovement.fEyePitchMinOffsetEmotionCombatAnger);
174 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionCombatAnger", eyesMovement.fEyePitchMaxOffsetEmotionCombatAnger);
175 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionCombatAnger", eyesMovement.fEyeOffsetDelayMinEmotionCombatAnger);
176 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionCombatAnger", eyesMovement.fEyeOffsetDelayMaxEmotionCombatAnger);
177 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMinOffsetEmotionCombatShout", eyesMovement.fEyeHeadingMinOffsetEmotionCombatShout);
178 | ini.SetDoubleValue("EyesMovement", "fEyeHeadingMaxOffsetEmotionCombatShout", eyesMovement.fEyeHeadingMaxOffsetEmotionCombatShout);
179 | ini.SetDoubleValue("EyesMovement", "fEyePitchMinOffsetEmotionCombatShout", eyesMovement.fEyePitchMinOffsetEmotionCombatShout);
180 | ini.SetDoubleValue("EyesMovement", "fEyePitchMaxOffsetEmotionCombatShout", eyesMovement.fEyePitchMaxOffsetEmotionCombatShout);
181 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMinEmotionCombatShout", eyesMovement.fEyeOffsetDelayMinEmotionCombatShout);
182 | ini.SetDoubleValue("EyesMovement", "fEyeOffsetDelayMaxEmotionCombatShout", eyesMovement.fEyeOffsetDelayMaxEmotionCombatShout);
183 |
184 | ini.SaveFile(path.c_str());
185 | }
186 | }
--------------------------------------------------------------------------------
/src/mfgfix/Settings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace MfgFix
4 | {
5 | struct Settings
6 | {
7 | struct EyesBlinking
8 | {
9 | float fBlinkDownTime{ 0.04f };
10 | float fBlinkUpTime{ 0.14f };
11 | float fBlinkDelayMin{ 0.5f };
12 | float fBlinkDelayMax{ 8.0f };
13 | };
14 |
15 | struct EyesMovement
16 | {
17 | float fTrackSpeed{ 5.0f };
18 | float fTrackEyeXY{ 28.0f };
19 | float fTrackEyeZ{ 20.0f };
20 | float fEyeHeadingMinOffsetEmotionAngry{ -0.05f };
21 | float fEyeHeadingMaxOffsetEmotionAngry{ 0.05f };
22 | float fEyePitchMinOffsetEmotionAngry{ -0.05f };
23 | float fEyePitchMaxOffsetEmotionAngry{ 0.1f };
24 | float fEyeOffsetDelayMinEmotionAngry{ 0.5f };
25 | float fEyeOffsetDelayMaxEmotionAngry{ 3.0f };
26 | float fEyeHeadingMinOffsetEmotionHappy{ -0.1f };
27 | float fEyeHeadingMaxOffsetEmotionHappy{ 0.1f };
28 | float fEyePitchMinOffsetEmotionHappy{ -0.05f };
29 | float fEyePitchMaxOffsetEmotionHappy{ 0.1f };
30 | float fEyeOffsetDelayMinEmotionHappy{ 0.5f };
31 | float fEyeOffsetDelayMaxEmotionHappy{ 4.0f };
32 | float fEyeHeadingMinOffsetEmotionSurprise{ -0.1f };
33 | float fEyeHeadingMaxOffsetEmotionSurprise{ 0.1f };
34 | float fEyePitchMinOffsetEmotionSurprise{ -0.05f };
35 | float fEyePitchMaxOffsetEmotionSurprise{ 0.1f };
36 | float fEyeOffsetDelayMinEmotionSurprise{ 0.5f };
37 | float fEyeOffsetDelayMaxEmotionSurprise{ 4.0f };
38 | float fEyeHeadingMinOffsetEmotionSad{ -0.1f };
39 | float fEyeHeadingMaxOffsetEmotionSad{ 0.1f };
40 | float fEyePitchMinOffsetEmotionSad{ -0.05f };
41 | float fEyePitchMaxOffsetEmotionSad{ -0.015f };
42 | float fEyeOffsetDelayMinEmotionSad{ 2.0f };
43 | float fEyeOffsetDelayMaxEmotionSad{ 3.0f };
44 | float fEyeHeadingMinOffsetEmotionFear{ -0.1f };
45 | float fEyeHeadingMaxOffsetEmotionFear{ 0.1f };
46 | float fEyePitchMinOffsetEmotionFear{ 0.01f };
47 | float fEyePitchMaxOffsetEmotionFear{ 0.01f };
48 | float fEyeOffsetDelayMinEmotionFear{ 0.5f };
49 | float fEyeOffsetDelayMaxEmotionFear{ 1.5f };
50 | float fEyeHeadingMinOffsetEmotionNeutral{ -0.1f };
51 | float fEyeHeadingMaxOffsetEmotionNeutral{ 0.1f };
52 | float fEyePitchMinOffsetEmotionNeutral{ -0.025f };
53 | float fEyePitchMaxOffsetEmotionNeutral{ 0.1f };
54 | float fEyeOffsetDelayMinEmotionNeutral{ 0.5f };
55 | float fEyeOffsetDelayMaxEmotionNeutral{ 4.0f };
56 | float fEyeHeadingMinOffsetEmotionPuzzled{ 0.0f };
57 | float fEyeHeadingMaxOffsetEmotionPuzzled{ 0.0f };
58 | float fEyePitchMinOffsetEmotionPuzzled{ 0.0f };
59 | float fEyePitchMaxOffsetEmotionPuzzled{ 0.0f };
60 | float fEyeOffsetDelayMinEmotionPuzzled{ 3.0f };
61 | float fEyeOffsetDelayMaxEmotionPuzzled{ 3.0f };
62 | float fEyeHeadingMinOffsetEmotionDisgusted{ 0.0f };
63 | float fEyeHeadingMaxOffsetEmotionDisgusted{ 0.0f };
64 | float fEyePitchMinOffsetEmotionDisgusted{ 0.0f };
65 | float fEyePitchMaxOffsetEmotionDisgusted{ 0.0f };
66 | float fEyeOffsetDelayMinEmotionDisgusted{ 3.0f };
67 | float fEyeOffsetDelayMaxEmotionDisgusted{ 3.0f };
68 | float fEyeHeadingMinOffsetEmotionCombatAnger{ 0.0f };
69 | float fEyeHeadingMaxOffsetEmotionCombatAnger{ 0.0f };
70 | float fEyePitchMinOffsetEmotionCombatAnger{ 0.0f };
71 | float fEyePitchMaxOffsetEmotionCombatAnger{ 0.0f };
72 | float fEyeOffsetDelayMinEmotionCombatAnger{ 3.0f };
73 | float fEyeOffsetDelayMaxEmotionCombatAnger{ 3.0f };
74 | float fEyeHeadingMinOffsetEmotionCombatShout{ 0.0f };
75 | float fEyeHeadingMaxOffsetEmotionCombatShout{ 0.0f };
76 | float fEyePitchMinOffsetEmotionCombatShout{ 0.0f };
77 | float fEyePitchMaxOffsetEmotionCombatShout{ 0.0f };
78 | float fEyeOffsetDelayMinEmotionCombatShout{ 3.0f };
79 | float fEyeOffsetDelayMaxEmotionCombatShout{ 3.0f };
80 | };
81 |
82 | static Settings& Get();
83 |
84 | void Read();
85 | void Write();
86 |
87 | EyesBlinking eyesBlinking;
88 | EyesMovement eyesMovement;
89 | };
90 | }
--------------------------------------------------------------------------------
/src/mfgfix/SettingsPapyrus.cpp:
--------------------------------------------------------------------------------
1 | #include "SettingsPapyrus.h"
2 | #include "Settings.h"
3 |
4 | namespace MfgFix::SettingsPapyrus
5 | {
6 | void Save(RE::StaticFunctionTag*)
7 | {
8 | Settings::Get().Write();
9 | }
10 |
11 | float GetFBlinkDownTime(RE::StaticFunctionTag*)
12 | {
13 | return Settings::Get().eyesBlinking.fBlinkDownTime;
14 | }
15 |
16 | void SetFBlinkDownTime(RE::StaticFunctionTag*, float a_value)
17 | {
18 | Settings::Get().eyesBlinking.fBlinkDownTime = a_value;
19 | }
20 |
21 | float GetFBlinkUpTime(RE::StaticFunctionTag*)
22 | {
23 | return Settings::Get().eyesBlinking.fBlinkUpTime;
24 | }
25 |
26 | void SetFBlinkUpTime(RE::StaticFunctionTag*, float a_value)
27 | {
28 | Settings::Get().eyesBlinking.fBlinkUpTime = a_value;
29 | }
30 |
31 | float GetFBlinkDelayMin(RE::StaticFunctionTag*)
32 | {
33 | return Settings::Get().eyesBlinking.fBlinkDelayMin;
34 | }
35 |
36 | void SetFBlinkDelayMin(RE::StaticFunctionTag*, float a_value)
37 | {
38 | Settings::Get().eyesBlinking.fBlinkDelayMin = a_value;
39 | }
40 |
41 | float GetFBlinkDelayMax(RE::StaticFunctionTag*)
42 | {
43 | return Settings::Get().eyesBlinking.fBlinkDelayMax;
44 | }
45 |
46 | void SetFBlinkDelayMax(RE::StaticFunctionTag*, float a_value)
47 | {
48 | Settings::Get().eyesBlinking.fBlinkDelayMax = a_value;
49 | }
50 |
51 | float GetFTrackSpeed(RE::StaticFunctionTag*)
52 | {
53 | return Settings::Get().eyesMovement.fTrackSpeed;
54 | }
55 |
56 | void SetFTrackSpeed(RE::StaticFunctionTag*, float a_value)
57 | {
58 | Settings::Get().eyesMovement.fTrackSpeed = a_value;
59 | }
60 |
61 | float GetFTrackEyeXY(RE::StaticFunctionTag*)
62 | {
63 | return Settings::Get().eyesMovement.fTrackEyeXY;
64 | }
65 |
66 | void SetFTrackEyeXY(RE::StaticFunctionTag*, float a_value)
67 | {
68 | Settings::Get().eyesMovement.fTrackEyeXY = a_value;
69 | }
70 |
71 | float GetFTrackEyeZ(RE::StaticFunctionTag*)
72 | {
73 | return Settings::Get().eyesMovement.fTrackEyeZ;
74 | }
75 |
76 | void SetFTrackEyeZ(RE::StaticFunctionTag*, float a_value)
77 | {
78 | Settings::Get().eyesMovement.fTrackEyeZ = a_value;
79 | }
80 |
81 | float GetFEyeHeadingMinOffsetEmotionAngry(RE::StaticFunctionTag*)
82 | {
83 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionAngry;
84 | }
85 |
86 | void SetFEyeHeadingMinOffsetEmotionAngry(RE::StaticFunctionTag*, float a_value)
87 | {
88 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionAngry = a_value;
89 | }
90 |
91 | float GetFEyeHeadingMaxOffsetEmotionAngry(RE::StaticFunctionTag*)
92 | {
93 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionAngry;
94 | }
95 |
96 | void SetFEyeHeadingMaxOffsetEmotionAngry(RE::StaticFunctionTag*, float a_value)
97 | {
98 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionAngry = a_value;
99 | }
100 |
101 | float GetFEyePitchMinOffsetEmotionAngry(RE::StaticFunctionTag*)
102 | {
103 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionAngry;
104 | }
105 |
106 | void SetFEyePitchMinOffsetEmotionAngry(RE::StaticFunctionTag*, float a_value)
107 | {
108 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionAngry = a_value;
109 | }
110 |
111 | float GetFEyePitchMaxOffsetEmotionAngry(RE::StaticFunctionTag*)
112 | {
113 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionAngry;
114 | }
115 |
116 | void SetFEyePitchMaxOffsetEmotionAngry(RE::StaticFunctionTag*, float a_value)
117 | {
118 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionAngry = a_value;
119 | }
120 |
121 | float GetFEyeOffsetDelayMinEmotionAngry(RE::StaticFunctionTag*)
122 | {
123 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionAngry;
124 | }
125 |
126 | void SetFEyeOffsetDelayMinEmotionAngry(RE::StaticFunctionTag*, float a_value)
127 | {
128 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionAngry = a_value;
129 | }
130 |
131 | float GetFEyeOffsetDelayMaxEmotionAngry(RE::StaticFunctionTag*)
132 | {
133 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionAngry;
134 | }
135 |
136 | void SetFEyeOffsetDelayMaxEmotionAngry(RE::StaticFunctionTag*, float a_value)
137 | {
138 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionAngry = a_value;
139 | }
140 |
141 | float GetFEyeHeadingMinOffsetEmotionHappy(RE::StaticFunctionTag*)
142 | {
143 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionHappy;
144 | }
145 |
146 | void SetFEyeHeadingMinOffsetEmotionHappy(RE::StaticFunctionTag*, float a_value)
147 | {
148 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionHappy = a_value;
149 | }
150 |
151 | float GetFEyeHeadingMaxOffsetEmotionHappy(RE::StaticFunctionTag*)
152 | {
153 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionHappy;
154 | }
155 |
156 | void SetFEyeHeadingMaxOffsetEmotionHappy(RE::StaticFunctionTag*, float a_value)
157 | {
158 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionHappy = a_value;
159 | }
160 |
161 | float GetFEyePitchMinOffsetEmotionHappy(RE::StaticFunctionTag*)
162 | {
163 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionHappy;
164 | }
165 |
166 | void SetFEyePitchMinOffsetEmotionHappy(RE::StaticFunctionTag*, float a_value)
167 | {
168 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionHappy = a_value;
169 | }
170 |
171 | float GetFEyePitchMaxOffsetEmotionHappy(RE::StaticFunctionTag*)
172 | {
173 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionHappy;
174 | }
175 |
176 | void SetFEyePitchMaxOffsetEmotionHappy(RE::StaticFunctionTag*, float a_value)
177 | {
178 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionHappy = a_value;
179 | }
180 |
181 | float GetFEyeOffsetDelayMinEmotionHappy(RE::StaticFunctionTag*)
182 | {
183 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionHappy;
184 | }
185 |
186 | void SetFEyeOffsetDelayMinEmotionHappy(RE::StaticFunctionTag*, float a_value)
187 | {
188 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionHappy = a_value;
189 | }
190 |
191 | float GetFEyeOffsetDelayMaxEmotionHappy(RE::StaticFunctionTag*)
192 | {
193 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionHappy;
194 | }
195 |
196 | void SetFEyeOffsetDelayMaxEmotionHappy(RE::StaticFunctionTag*, float a_value)
197 | {
198 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionHappy = a_value;
199 | }
200 |
201 | float GetFEyeHeadingMinOffsetEmotionSurprise(RE::StaticFunctionTag*)
202 | {
203 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionSurprise;
204 | }
205 |
206 | void SetFEyeHeadingMinOffsetEmotionSurprise(RE::StaticFunctionTag*, float a_value)
207 | {
208 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionSurprise = a_value;
209 | }
210 |
211 | float GetFEyeHeadingMaxOffsetEmotionSurprise(RE::StaticFunctionTag*)
212 | {
213 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionSurprise;
214 | }
215 |
216 | void SetFEyeHeadingMaxOffsetEmotionSurprise(RE::StaticFunctionTag*, float a_value)
217 | {
218 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionSurprise = a_value;
219 | }
220 |
221 | float GetFEyePitchMinOffsetEmotionSurprise(RE::StaticFunctionTag*)
222 | {
223 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionSurprise;
224 | }
225 |
226 | void SetFEyePitchMinOffsetEmotionSurprise(RE::StaticFunctionTag*, float a_value)
227 | {
228 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionSurprise = a_value;
229 | }
230 |
231 | float GetFEyePitchMaxOffsetEmotionSurprise(RE::StaticFunctionTag*)
232 | {
233 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionSurprise;
234 | }
235 |
236 | void SetFEyePitchMaxOffsetEmotionSurprise(RE::StaticFunctionTag*, float a_value)
237 | {
238 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionSurprise = a_value;
239 | }
240 |
241 | float GetFEyeOffsetDelayMinEmotionSurprise(RE::StaticFunctionTag*)
242 | {
243 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionSurprise;
244 | }
245 |
246 | void SetFEyeOffsetDelayMinEmotionSurprise(RE::StaticFunctionTag*, float a_value)
247 | {
248 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionSurprise = a_value;
249 | }
250 |
251 | float GetFEyeOffsetDelayMaxEmotionSurprise(RE::StaticFunctionTag*)
252 | {
253 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionSurprise;
254 | }
255 |
256 | void SetFEyeOffsetDelayMaxEmotionSurprise(RE::StaticFunctionTag*, float a_value)
257 | {
258 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionSurprise = a_value;
259 | }
260 |
261 | float GetFEyeHeadingMinOffsetEmotionSad(RE::StaticFunctionTag*)
262 | {
263 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionSad;
264 | }
265 |
266 | void SetFEyeHeadingMinOffsetEmotionSad(RE::StaticFunctionTag*, float a_value)
267 | {
268 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionSad = a_value;
269 | }
270 |
271 | float GetFEyeHeadingMaxOffsetEmotionSad(RE::StaticFunctionTag*)
272 | {
273 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionSad;
274 | }
275 |
276 | void SetFEyeHeadingMaxOffsetEmotionSad(RE::StaticFunctionTag*, float a_value)
277 | {
278 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionSad = a_value;
279 | }
280 |
281 | float GetFEyePitchMinOffsetEmotionSad(RE::StaticFunctionTag*)
282 | {
283 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionSad;
284 | }
285 |
286 | void SetFEyePitchMinOffsetEmotionSad(RE::StaticFunctionTag*, float a_value)
287 | {
288 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionSad = a_value;
289 | }
290 |
291 | float GetFEyePitchMaxOffsetEmotionSad(RE::StaticFunctionTag*)
292 | {
293 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionSad;
294 | }
295 |
296 | void SetFEyePitchMaxOffsetEmotionSad(RE::StaticFunctionTag*, float a_value)
297 | {
298 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionSad = a_value;
299 | }
300 |
301 | float GetFEyeOffsetDelayMinEmotionSad(RE::StaticFunctionTag*)
302 | {
303 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionSad;
304 | }
305 |
306 | void SetFEyeOffsetDelayMinEmotionSad(RE::StaticFunctionTag*, float a_value)
307 | {
308 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionSad = a_value;
309 | }
310 |
311 | float GetFEyeOffsetDelayMaxEmotionSad(RE::StaticFunctionTag*)
312 | {
313 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionSad;
314 | }
315 |
316 | void SetFEyeOffsetDelayMaxEmotionSad(RE::StaticFunctionTag*, float a_value)
317 | {
318 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionSad = a_value;
319 | }
320 |
321 | float GetFEyeHeadingMinOffsetEmotionFear(RE::StaticFunctionTag*)
322 | {
323 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionFear;
324 | }
325 |
326 | void SetFEyeHeadingMinOffsetEmotionFear(RE::StaticFunctionTag*, float a_value)
327 | {
328 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionFear = a_value;
329 | }
330 |
331 | float GetFEyeHeadingMaxOffsetEmotionFear(RE::StaticFunctionTag*)
332 | {
333 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionFear;
334 | }
335 |
336 | void SetFEyeHeadingMaxOffsetEmotionFear(RE::StaticFunctionTag*, float a_value)
337 | {
338 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionFear = a_value;
339 | }
340 |
341 | float GetFEyePitchMinOffsetEmotionFear(RE::StaticFunctionTag*)
342 | {
343 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionFear;
344 | }
345 |
346 | void SetFEyePitchMinOffsetEmotionFear(RE::StaticFunctionTag*, float a_value)
347 | {
348 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionFear = a_value;
349 | }
350 |
351 | float GetFEyePitchMaxOffsetEmotionFear(RE::StaticFunctionTag*)
352 | {
353 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionFear;
354 | }
355 |
356 | void SetFEyePitchMaxOffsetEmotionFear(RE::StaticFunctionTag*, float a_value)
357 | {
358 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionFear = a_value;
359 | }
360 |
361 | float GetFEyeOffsetDelayMinEmotionFear(RE::StaticFunctionTag*)
362 | {
363 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionFear;
364 | }
365 |
366 | void SetFEyeOffsetDelayMinEmotionFear(RE::StaticFunctionTag*, float a_value)
367 | {
368 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionFear = a_value;
369 | }
370 |
371 | float GetFEyeOffsetDelayMaxEmotionFear(RE::StaticFunctionTag*)
372 | {
373 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionFear;
374 | }
375 |
376 | void SetFEyeOffsetDelayMaxEmotionFear(RE::StaticFunctionTag*, float a_value)
377 | {
378 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionFear = a_value;
379 | }
380 |
381 | float GetFEyeHeadingMinOffsetEmotionNeutral(RE::StaticFunctionTag*)
382 | {
383 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionNeutral;
384 | }
385 |
386 | void SetFEyeHeadingMinOffsetEmotionNeutral(RE::StaticFunctionTag*, float a_value)
387 | {
388 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionNeutral = a_value;
389 | }
390 |
391 | float GetFEyeHeadingMaxOffsetEmotionNeutral(RE::StaticFunctionTag*)
392 | {
393 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionNeutral;
394 | }
395 |
396 | void SetFEyeHeadingMaxOffsetEmotionNeutral(RE::StaticFunctionTag*, float a_value)
397 | {
398 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionNeutral = a_value;
399 | }
400 |
401 | float GetFEyePitchMinOffsetEmotionNeutral(RE::StaticFunctionTag*)
402 | {
403 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionNeutral;
404 | }
405 |
406 | void SetFEyePitchMinOffsetEmotionNeutral(RE::StaticFunctionTag*, float a_value)
407 | {
408 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionNeutral = a_value;
409 | }
410 |
411 | float GetFEyePitchMaxOffsetEmotionNeutral(RE::StaticFunctionTag*)
412 | {
413 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionNeutral;
414 | }
415 |
416 | void SetFEyePitchMaxOffsetEmotionNeutral(RE::StaticFunctionTag*, float a_value)
417 | {
418 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionNeutral = a_value;
419 | }
420 |
421 | float GetFEyeOffsetDelayMinEmotionNeutral(RE::StaticFunctionTag*)
422 | {
423 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionNeutral;
424 | }
425 |
426 | void SetFEyeOffsetDelayMinEmotionNeutral(RE::StaticFunctionTag*, float a_value)
427 | {
428 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionNeutral = a_value;
429 | }
430 |
431 | float GetFEyeOffsetDelayMaxEmotionNeutral(RE::StaticFunctionTag*)
432 | {
433 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionNeutral;
434 | }
435 |
436 | void SetFEyeOffsetDelayMaxEmotionNeutral(RE::StaticFunctionTag*, float a_value)
437 | {
438 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionNeutral = a_value;
439 | }
440 |
441 | float GetFEyeHeadingMinOffsetEmotionPuzzled(RE::StaticFunctionTag*)
442 | {
443 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionPuzzled;
444 | }
445 |
446 | void SetFEyeHeadingMinOffsetEmotionPuzzled(RE::StaticFunctionTag*, float a_value)
447 | {
448 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionPuzzled = a_value;
449 | }
450 |
451 | float GetFEyeHeadingMaxOffsetEmotionPuzzled(RE::StaticFunctionTag*)
452 | {
453 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionPuzzled;
454 | }
455 |
456 | void SetFEyeHeadingMaxOffsetEmotionPuzzled(RE::StaticFunctionTag*, float a_value)
457 | {
458 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionPuzzled = a_value;
459 | }
460 |
461 | float GetFEyePitchMinOffsetEmotionPuzzled(RE::StaticFunctionTag*)
462 | {
463 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionPuzzled;
464 | }
465 |
466 | void SetFEyePitchMinOffsetEmotionPuzzled(RE::StaticFunctionTag*, float a_value)
467 | {
468 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionPuzzled = a_value;
469 | }
470 |
471 | float GetFEyePitchMaxOffsetEmotionPuzzled(RE::StaticFunctionTag*)
472 | {
473 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionPuzzled;
474 | }
475 |
476 | void SetFEyePitchMaxOffsetEmotionPuzzled(RE::StaticFunctionTag*, float a_value)
477 | {
478 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionPuzzled = a_value;
479 | }
480 |
481 | float GetFEyeOffsetDelayMinEmotionPuzzled(RE::StaticFunctionTag*)
482 | {
483 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionPuzzled;
484 | }
485 |
486 | void SetFEyeOffsetDelayMinEmotionPuzzled(RE::StaticFunctionTag*, float a_value)
487 | {
488 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionPuzzled = a_value;
489 | }
490 |
491 | float GetFEyeOffsetDelayMaxEmotionPuzzled(RE::StaticFunctionTag*)
492 | {
493 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionPuzzled;
494 | }
495 |
496 | void SetFEyeOffsetDelayMaxEmotionPuzzled(RE::StaticFunctionTag*, float a_value)
497 | {
498 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionPuzzled = a_value;
499 | }
500 |
501 | float GetFEyeHeadingMinOffsetEmotionDisgusted(RE::StaticFunctionTag*)
502 | {
503 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionDisgusted;
504 | }
505 |
506 | void SetFEyeHeadingMinOffsetEmotionDisgusted(RE::StaticFunctionTag*, float a_value)
507 | {
508 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionDisgusted = a_value;
509 | }
510 |
511 | float GetFEyeHeadingMaxOffsetEmotionDisgusted(RE::StaticFunctionTag*)
512 | {
513 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionDisgusted;
514 | }
515 |
516 | void SetFEyeHeadingMaxOffsetEmotionDisgusted(RE::StaticFunctionTag*, float a_value)
517 | {
518 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionDisgusted = a_value;
519 | }
520 |
521 | float GetFEyePitchMinOffsetEmotionDisgusted(RE::StaticFunctionTag*)
522 | {
523 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionDisgusted;
524 | }
525 |
526 | void SetFEyePitchMinOffsetEmotionDisgusted(RE::StaticFunctionTag*, float a_value)
527 | {
528 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionDisgusted = a_value;
529 | }
530 |
531 | float GetFEyePitchMaxOffsetEmotionDisgusted(RE::StaticFunctionTag*)
532 | {
533 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionDisgusted;
534 | }
535 |
536 | void SetFEyePitchMaxOffsetEmotionDisgusted(RE::StaticFunctionTag*, float a_value)
537 | {
538 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionDisgusted = a_value;
539 | }
540 |
541 | float GetFEyeOffsetDelayMinEmotionDisgusted(RE::StaticFunctionTag*)
542 | {
543 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionDisgusted;
544 | }
545 |
546 | void SetFEyeOffsetDelayMinEmotionDisgusted(RE::StaticFunctionTag*, float a_value)
547 | {
548 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionDisgusted = a_value;
549 | }
550 |
551 | float GetFEyeOffsetDelayMaxEmotionDisgusted(RE::StaticFunctionTag*)
552 | {
553 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionDisgusted;
554 | }
555 |
556 | void SetFEyeOffsetDelayMaxEmotionDisgusted(RE::StaticFunctionTag*, float a_value)
557 | {
558 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionDisgusted = a_value;
559 | }
560 |
561 | float GetFEyeHeadingMinOffsetEmotionCombatAnger(RE::StaticFunctionTag*)
562 | {
563 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionCombatAnger;
564 | }
565 |
566 | void SetFEyeHeadingMinOffsetEmotionCombatAnger(RE::StaticFunctionTag*, float a_value)
567 | {
568 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionCombatAnger = a_value;
569 | }
570 |
571 | float GetFEyeHeadingMaxOffsetEmotionCombatAnger(RE::StaticFunctionTag*)
572 | {
573 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionCombatAnger;
574 | }
575 |
576 | void SetFEyeHeadingMaxOffsetEmotionCombatAnger(RE::StaticFunctionTag*, float a_value)
577 | {
578 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionCombatAnger = a_value;
579 | }
580 |
581 | float GetFEyePitchMinOffsetEmotionCombatAnger(RE::StaticFunctionTag*)
582 | {
583 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionCombatAnger;
584 | }
585 |
586 | void SetFEyePitchMinOffsetEmotionCombatAnger(RE::StaticFunctionTag*, float a_value)
587 | {
588 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionCombatAnger = a_value;
589 | }
590 |
591 | float GetFEyePitchMaxOffsetEmotionCombatAnger(RE::StaticFunctionTag*)
592 | {
593 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionCombatAnger;
594 | }
595 |
596 | void SetFEyePitchMaxOffsetEmotionCombatAnger(RE::StaticFunctionTag*, float a_value)
597 | {
598 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionCombatAnger = a_value;
599 | }
600 |
601 | float GetFEyeOffsetDelayMinEmotionCombatAnger(RE::StaticFunctionTag*)
602 | {
603 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionCombatAnger;
604 | }
605 |
606 | void SetFEyeOffsetDelayMinEmotionCombatAnger(RE::StaticFunctionTag*, float a_value)
607 | {
608 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionCombatAnger = a_value;
609 | }
610 |
611 | float GetFEyeOffsetDelayMaxEmotionCombatAnger(RE::StaticFunctionTag*)
612 | {
613 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionCombatAnger;
614 | }
615 |
616 | void SetFEyeOffsetDelayMaxEmotionCombatAnger(RE::StaticFunctionTag*, float a_value)
617 | {
618 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionCombatAnger = a_value;
619 | }
620 |
621 | float GetFEyeHeadingMinOffsetEmotionCombatShout(RE::StaticFunctionTag*)
622 | {
623 | return Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionCombatShout;
624 | }
625 |
626 | void SetFEyeHeadingMinOffsetEmotionCombatShout(RE::StaticFunctionTag*, float a_value)
627 | {
628 | Settings::Get().eyesMovement.fEyeHeadingMinOffsetEmotionCombatShout = a_value;
629 | }
630 |
631 | float GetFEyeHeadingMaxOffsetEmotionCombatShout(RE::StaticFunctionTag*)
632 | {
633 | return Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionCombatShout;
634 | }
635 |
636 | void SetFEyeHeadingMaxOffsetEmotionCombatShout(RE::StaticFunctionTag*, float a_value)
637 | {
638 | Settings::Get().eyesMovement.fEyeHeadingMaxOffsetEmotionCombatShout = a_value;
639 | }
640 |
641 | float GetFEyePitchMinOffsetEmotionCombatShout(RE::StaticFunctionTag*)
642 | {
643 | return Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionCombatShout;
644 | }
645 |
646 | void SetFEyePitchMinOffsetEmotionCombatShout(RE::StaticFunctionTag*, float a_value)
647 | {
648 | Settings::Get().eyesMovement.fEyePitchMinOffsetEmotionCombatShout = a_value;
649 | }
650 |
651 | float GetFEyePitchMaxOffsetEmotionCombatShout(RE::StaticFunctionTag*)
652 | {
653 | return Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionCombatShout;
654 | }
655 |
656 | void SetFEyePitchMaxOffsetEmotionCombatShout(RE::StaticFunctionTag*, float a_value)
657 | {
658 | Settings::Get().eyesMovement.fEyePitchMaxOffsetEmotionCombatShout = a_value;
659 | }
660 |
661 | float GetFEyeOffsetDelayMinEmotionCombatShout(RE::StaticFunctionTag*)
662 | {
663 | return Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionCombatShout;
664 | }
665 |
666 | void SetFEyeOffsetDelayMinEmotionCombatShout(RE::StaticFunctionTag*, float a_value)
667 | {
668 | Settings::Get().eyesMovement.fEyeOffsetDelayMinEmotionCombatShout = a_value;
669 | }
670 |
671 | float GetFEyeOffsetDelayMaxEmotionCombatShout(RE::StaticFunctionTag*)
672 | {
673 | return Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionCombatShout;
674 | }
675 |
676 | void SetFEyeOffsetDelayMaxEmotionCombatShout(RE::StaticFunctionTag*, float a_value)
677 | {
678 | Settings::Get().eyesMovement.fEyeOffsetDelayMaxEmotionCombatShout = a_value;
679 | }
680 |
681 | void Register()
682 | {
683 | SKSE::GetPapyrusInterface()->Register([](RE::BSScript::IVirtualMachine* a_vm) {
684 | a_vm->RegisterFunction("Save", "MFGFIX_Settings", Save);
685 | a_vm->RegisterFunction("GetFBlinkDownTime", "MFGFIX_Settings", GetFBlinkDownTime);
686 | a_vm->RegisterFunction("SetFBlinkDownTime", "MFGFIX_Settings", SetFBlinkDownTime);
687 | a_vm->RegisterFunction("GetFBlinkUpTime", "MFGFIX_Settings", GetFBlinkUpTime);
688 | a_vm->RegisterFunction("SetFBlinkUpTime", "MFGFIX_Settings", SetFBlinkUpTime);
689 | a_vm->RegisterFunction("GetFBlinkDelayMin", "MFGFIX_Settings", GetFBlinkDelayMin);
690 | a_vm->RegisterFunction("SetFBlinkDelayMin", "MFGFIX_Settings", SetFBlinkDelayMin);
691 | a_vm->RegisterFunction("GetFBlinkDelayMax", "MFGFIX_Settings", GetFBlinkDelayMax);
692 | a_vm->RegisterFunction("SetFBlinkDelayMax", "MFGFIX_Settings", SetFBlinkDelayMax);
693 | a_vm->RegisterFunction("GetFTrackSpeed", "MFGFIX_Settings", GetFTrackSpeed);
694 | a_vm->RegisterFunction("SetFTrackSpeed", "MFGFIX_Settings", SetFTrackSpeed);
695 | a_vm->RegisterFunction("GetFTrackEyeXY", "MFGFIX_Settings", GetFTrackEyeXY);
696 | a_vm->RegisterFunction("SetFTrackEyeXY", "MFGFIX_Settings", SetFTrackEyeXY);
697 | a_vm->RegisterFunction("GetFTrackEyeZ", "MFGFIX_Settings", GetFTrackEyeZ);
698 | a_vm->RegisterFunction("SetFTrackEyeZ", "MFGFIX_Settings", SetFTrackEyeZ);
699 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionAngry", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionAngry);
700 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionAngry", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionAngry);
701 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionAngry", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionAngry);
702 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionAngry", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionAngry);
703 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionAngry", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionAngry);
704 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionAngry", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionAngry);
705 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionAngry", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionAngry);
706 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionAngry", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionAngry);
707 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionAngry", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionAngry);
708 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionAngry", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionAngry);
709 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionAngry", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionAngry);
710 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionAngry", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionAngry);
711 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionHappy", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionHappy);
712 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionHappy", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionHappy);
713 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionHappy", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionHappy);
714 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionHappy", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionHappy);
715 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionHappy", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionHappy);
716 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionHappy", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionHappy);
717 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionHappy", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionHappy);
718 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionHappy", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionHappy);
719 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionHappy", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionHappy);
720 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionHappy", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionHappy);
721 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionHappy", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionHappy);
722 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionHappy", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionHappy);
723 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionSurprise", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionSurprise);
724 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionSurprise", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionSurprise);
725 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionSurprise", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionSurprise);
726 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionSurprise", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionSurprise);
727 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionSurprise", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionSurprise);
728 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionSurprise", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionSurprise);
729 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionSurprise", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionSurprise);
730 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionSurprise", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionSurprise);
731 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionSurprise", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionSurprise);
732 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionSurprise", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionSurprise);
733 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionSurprise", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionSurprise);
734 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionSurprise", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionSurprise);
735 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionSad", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionSad);
736 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionSad", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionSad);
737 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionSad", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionSad);
738 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionSad", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionSad);
739 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionSad", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionSad);
740 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionSad", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionSad);
741 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionSad", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionSad);
742 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionSad", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionSad);
743 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionSad", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionSad);
744 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionSad", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionSad);
745 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionSad", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionSad);
746 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionSad", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionSad);
747 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionFear", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionFear);
748 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionFear", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionFear);
749 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionFear", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionFear);
750 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionFear", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionFear);
751 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionFear", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionFear);
752 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionFear", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionFear);
753 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionFear", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionFear);
754 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionFear", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionFear);
755 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionFear", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionFear);
756 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionFear", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionFear);
757 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionFear", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionFear);
758 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionFear", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionFear);
759 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionNeutral", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionNeutral);
760 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionNeutral", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionNeutral);
761 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionNeutral", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionNeutral);
762 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionNeutral", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionNeutral);
763 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionNeutral", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionNeutral);
764 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionNeutral", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionNeutral);
765 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionNeutral", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionNeutral);
766 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionNeutral", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionNeutral);
767 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionNeutral", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionNeutral);
768 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionNeutral", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionNeutral);
769 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionNeutral", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionNeutral);
770 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionNeutral", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionNeutral);
771 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionPuzzled", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionPuzzled);
772 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionPuzzled", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionPuzzled);
773 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionPuzzled", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionPuzzled);
774 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionPuzzled", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionPuzzled);
775 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionPuzzled", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionPuzzled);
776 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionPuzzled", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionPuzzled);
777 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionPuzzled", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionPuzzled);
778 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionPuzzled", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionPuzzled);
779 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionPuzzled", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionPuzzled);
780 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionPuzzled", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionPuzzled);
781 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionPuzzled", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionPuzzled);
782 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionPuzzled", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionPuzzled);
783 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionDisgusted", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionDisgusted);
784 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionDisgusted", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionDisgusted);
785 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionDisgusted", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionDisgusted);
786 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionDisgusted", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionDisgusted);
787 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionDisgusted", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionDisgusted);
788 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionDisgusted", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionDisgusted);
789 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionDisgusted", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionDisgusted);
790 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionDisgusted", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionDisgusted);
791 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionDisgusted", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionDisgusted);
792 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionDisgusted", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionDisgusted);
793 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionDisgusted", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionDisgusted);
794 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionDisgusted", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionDisgusted);
795 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionCombatAnger", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionCombatAnger);
796 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionCombatAnger", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionCombatAnger);
797 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionCombatAnger", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionCombatAnger);
798 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionCombatAnger", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionCombatAnger);
799 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionCombatAnger", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionCombatAnger);
800 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionCombatAnger", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionCombatAnger);
801 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionCombatAnger", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionCombatAnger);
802 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionCombatAnger", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionCombatAnger);
803 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionCombatAnger", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionCombatAnger);
804 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionCombatAnger", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionCombatAnger);
805 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionCombatAnger", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionCombatAnger);
806 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionCombatAnger", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionCombatAnger);
807 | a_vm->RegisterFunction("GetFEyeHeadingMinOffsetEmotionCombatShout", "MFGFIX_Settings", GetFEyeHeadingMinOffsetEmotionCombatShout);
808 | a_vm->RegisterFunction("SetFEyeHeadingMinOffsetEmotionCombatShout", "MFGFIX_Settings", SetFEyeHeadingMinOffsetEmotionCombatShout);
809 | a_vm->RegisterFunction("GetFEyeHeadingMaxOffsetEmotionCombatShout", "MFGFIX_Settings", GetFEyeHeadingMaxOffsetEmotionCombatShout);
810 | a_vm->RegisterFunction("SetFEyeHeadingMaxOffsetEmotionCombatShout", "MFGFIX_Settings", SetFEyeHeadingMaxOffsetEmotionCombatShout);
811 | a_vm->RegisterFunction("GetFEyePitchMinOffsetEmotionCombatShout", "MFGFIX_Settings", GetFEyePitchMinOffsetEmotionCombatShout);
812 | a_vm->RegisterFunction("SetFEyePitchMinOffsetEmotionCombatShout", "MFGFIX_Settings", SetFEyePitchMinOffsetEmotionCombatShout);
813 | a_vm->RegisterFunction("GetFEyePitchMaxOffsetEmotionCombatShout", "MFGFIX_Settings", GetFEyePitchMaxOffsetEmotionCombatShout);
814 | a_vm->RegisterFunction("SetFEyePitchMaxOffsetEmotionCombatShout", "MFGFIX_Settings", SetFEyePitchMaxOffsetEmotionCombatShout);
815 | a_vm->RegisterFunction("GetFEyeOffsetDelayMinEmotionCombatShout", "MFGFIX_Settings", GetFEyeOffsetDelayMinEmotionCombatShout);
816 | a_vm->RegisterFunction("SetFEyeOffsetDelayMinEmotionCombatShout", "MFGFIX_Settings", SetFEyeOffsetDelayMinEmotionCombatShout);
817 | a_vm->RegisterFunction("GetFEyeOffsetDelayMaxEmotionCombatShout", "MFGFIX_Settings", GetFEyeOffsetDelayMaxEmotionCombatShout);
818 | a_vm->RegisterFunction("SetFEyeOffsetDelayMaxEmotionCombatShout", "MFGFIX_Settings", SetFEyeOffsetDelayMaxEmotionCombatShout);
819 |
820 | return true;
821 | });
822 | }
823 | }
--------------------------------------------------------------------------------
/src/mfgfix/SettingsPapyrus.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace MfgFix::SettingsPapyrus
4 | {
5 | void Register();
6 | }
--------------------------------------------------------------------------------
/src/mfgfix/mfgfixinit.cpp:
--------------------------------------------------------------------------------
1 | #include "mfgfixinit.h"
2 | #include "Settings.h"
3 | #include "BSFaceGenAnimationData.h"
4 | #include "ConsoleCommands.h"
5 | #include "SettingsPapyrus.h"
6 | #include "MfgConsoleFunc.h"
7 | #include "Offsets.h"
8 |
9 |
10 | namespace MfgFix
11 | {
12 | void Init()
13 | {
14 | Settings::Get().Read();
15 |
16 | BSFaceGenAnimationData::Init();
17 | ConsoleCommands::Init();
18 |
19 | // Papyrus
20 | SettingsPapyrus::Register();
21 | MfgConsoleFunc::Register();
22 |
23 | // Misc
24 |
25 | // allow expression change for dead npcs
26 | REL::safe_fill(Offsets::BSFaceGenAnimationData::sub_3DB770.address() + 0x004A, 0x90, 0x0D);
27 | // fix papyrus function SetExpressionOverride that didn't work with aiMood 0
28 | REL::safe_write(Offsets::Papyrus::Actor::SetExpressionOverride.address() + 0x001A, static_cast(0x9001));
29 | REL::safe_write(Offsets::Papyrus::Actor::SetExpressionOverride.address() + 0x002A, static_cast(0x10));
30 | // disable code that sometimes cause ctd because of missing check for null parent node
31 | REL::safe_fill(Offsets::BSFaceGenNiNode::sub_3F0C90.address() + 0x0395, 0x90, 0x0F);
32 | }
33 | }
--------------------------------------------------------------------------------
/src/mfgfix/mfgfixinit.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace MfgFix
4 | {
5 | void Init();
6 | }
--------------------------------------------------------------------------------
/src/pch.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrelo1/mfgfix/270485ce10cbe20047b06abf27bb68553a454cff/src/pch.cpp
--------------------------------------------------------------------------------
/src/pch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "RE/Skyrim.h"
4 | #include "SKSE/SKSE.h"
5 | #include
6 |
7 | #define NOMINMAX
8 | #include
9 | #include "Detours/include/detours.h"
10 |
11 | using namespace std::literals;
12 |
13 | #include "version.h"
--------------------------------------------------------------------------------
/src/version.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Version
4 | {
5 | inline constexpr std::size_t MAJOR = 1;
6 | inline constexpr std::size_t MINOR = 6;
7 | inline constexpr std::size_t PATCH = 1;
8 | inline constexpr auto NAME = "1.6.1"sv;
9 | inline constexpr auto PROJECT = "mfgfix"sv;
10 | }
--------------------------------------------------------------------------------
/src/version.rc:
--------------------------------------------------------------------------------
1 | #include "winres.h"
2 |
3 | VS_VERSION_INFO VERSIONINFO
4 | FILEVERSION 1,6,1,0
5 | PRODUCTVERSION 1,6,1,0
6 | FILEFLAGSMASK 0x3fL
7 | #ifdef _DEBUG
8 | FILEFLAGS 0x1L
9 | #else
10 | FILEFLAGS 0x0L
11 | #endif
12 | FILEOS 0x40004L
13 | FILETYPE 0x2L
14 | FILESUBTYPE 0x0L
15 | BEGIN
16 | BLOCK "StringFileInfo"
17 | BEGIN
18 | BLOCK "040904b0"
19 | BEGIN
20 | VALUE "FileVersion", "1.6.1.0"
21 | VALUE "InternalName", "mfgfix.dll"
22 | VALUE "LegalCopyright", "MIT License"
23 | VALUE "OriginalFilename", "mfgfix.dll"
24 | VALUE "ProductName", "mfgfix"
25 | VALUE "ProductVersion", "1.6.1.0"
26 | END
27 | END
28 | BLOCK "VarFileInfo"
29 | BEGIN
30 | VALUE "Translation", 0x409, 1200
31 | END
32 | END
--------------------------------------------------------------------------------