You said:
This set of Papyrus scripts and C++ code is a skyrim Mod designed to provide a screengrabber functions thru a SKSE plugin based on SKSE 2.02.06 and Commoinlibsse-ng 3.6 Everything seems to compile with no errors. These exists a major problem in that the SKSE functions will not register and gie unbound function errors. Please review the files and determine any errors or changes tha are needed.
Thought for 27 seconds
ChatGPT said:
Here are the key things I spotted that will prevent your Papyrus natives from ever binding—and how to fix them:
1. You aren’t registering your latent function as latent
In your RegisterFunctions you do:
cpp
CopyEdit
vm->RegisterFunction("TakePhoto", scriptName, TakePhoto);
but your .psc declares TakePhoto as native global latent. In CommonLibSSE-NG you must pass the latent flag:
diff
CopyEdit
// Before: - vm->RegisterFunction("TakePhoto", scriptName, TakePhoto); + // Register latent function: + vm->RegisterFunction("TakePhoto", scriptName, TakePhoto, /* isLatent = */ true);
Without that fourth boolean, the VM treats it as a normal (non-latent) function and will never match your script’s latent signature.
2. Make sure your scriptName exactly matches the Papyrus script
In PapyrusInterface.cpp you have:
cpp
CopyEdit
const char* scriptName = "Printscreen_Formula_script";
That string must be byte-for-byte identical to your .psc header:
papyrus
CopyEdit
ScriptName Printscreen_Formula_script extends Quest
Even a single uppercase/lowercase difference—or an extra “.psc” suffix—will cause “unbound function” errors. Double-check the .psc filename, the ScriptName statement, and this C++ literal.
3. Verify your Papyrus function names and signatures match
You register:
C++ registrationExpected Papyrus declaration
"TakePhoto"String Function TakePhoto(... ) native global latent
"Get_Result"String Function Get_Result() native global
"Cancel"Bool Function Cancel() native global
"CheckPath"Bool Function CheckPath(String path) native global
If your .psc calls it e.g. GetResult (no underscore) or uses a different case, the VM won’t bind it. Make them match exactly.
4. Be sure your .psc is compiled into a .pex and deployed
Papyrus functions only bind if the script is actually loaded by the game. After editing your .psc, run the Creation Kit’s Papyrus compiler so you get Printscreen_Formula_script.pex in Data/Scripts. If the .pex never lands there (or your esp doesn’t reference that script), your native registration never even fires in-game.
5. Add some logging to confirm what actually happened
Your logger::info calls around registration are great. After load, open
bash
CopyEdit
Data\SKSE\Plugins\PrintScreen.log
and look for lines like:
pgsql
CopyEdit
Attempting to register Papyrus functions for script: 'Printscreen_Formula_script' TakePhoto registered successfully …
If you never see “registered successfully,” there’s still a mismatch or an exception—track it down in that log.
Revised RegisterFunctions snippet
cpp
CopyEdit
bool RegisterFunctions(RE::BSScript::IVirtualMachine* vm) { const char* scriptName = "Printscreen_Formula_script"; logger::info("Attempting to register Papyrus functions for script: '{}'", scriptName); // Normal (non-latent) functions: vm->RegisterFunction("Get_Result", scriptName, Get_Result); vm->RegisterFunction("Cancel", scriptName, Cancel); vm->RegisterFunction("CheckPath", scriptName, CheckPath); // Latent function must be flagged: vm->RegisterFunction("TakePhoto", scriptName, TakePhoto, /* isLatent= */ true); logger::info("All Papyrus functions registered for script: '{}'", scriptName); return true; }
TL;DR:
-
Pass
truewhen registering your latentTakePhoto. -
Make sure
scriptNameand every function name exactly match your.psc. -
Compile and deploy the
.pscto a.pex. -
Check your
PrintScreen.logto verify registration succeeded.
Once those are in sync, your “unbound function” errors should go away.
Sources
You said:
I can not compile the papyrus function with the latent flag errors with unknown flag
ChatGPT said:
Thought for 30 seconds
The error you’re seeing when you try to simply tack a fourth “ true ” boolean onto your existing
cpp
CopyEdit
vm->RegisterFunction("TakePhoto", scriptName, TakePhoto, /*true*/);
is because CommonLibSSE-NG 3.6’s IVirtualMachine::RegisterFunction does not yet expose that bool‐overload. That overload only landed in a later CommonLibSSE-NG version.
You have two paths forward:
1) Upgrade CommonLibSSE-NG to ≥ 3.7
If you update your vcpkg (or your local CMake submodule) to at least CommonLibSSE-NG 3.7, then the simpler overload will exist:
cpp
CopyEdit
// (in your existing RegisterFunctions) vm->RegisterFunction("TakePhoto", scriptName, TakePhoto, /* isLatent = */ true);
and it will compile out-of-the-box.
2) Use the NativeFunction::Create API (works in 3.6)
Without upgrading, you can still register a latent native by constructing a NativeFunction object yourself.
Here’s how you’d change your RegisterFunctions:
cpp
CopyEdit
#include "RE/BSScript/NativeFunction.h" // make sure this is in your include path bool RegisterFunctions(RE::BSScript::IVirtualMachine* vm) { const char* scriptName = "Printscreen_Formula_script"; logger::info("Registering Papyrus natives for '{}'", scriptName); // — non-latent registrations stay the same — vm->RegisterFunction("Get_Result", scriptName, Get_Result); vm->RegisterFunction("Cancel", scriptName, Cancel); vm->RegisterFunction("CheckPath", scriptName, CheckPath); // — latent registration via NativeFunction::Create — { using FN = RE::BSScript::NativeFunction< RE::StaticFunctionTag, // static function std::string, // return type: Papyrus String std::string, // Arg1: basePath std::string, // Arg2: imageType float, // Arg3: jpgCompression std::string, // Arg4: compressionMode float // Arg5: gifMultiFrameDuration >; auto takePhotoFn = FN::Create( scriptName, // your script "TakePhoto", // Papyrus name TakePhoto, // C++ function pointer /* isLatent = */ true // mark as latent ); vm->RegisterFunction(takePhotoFn); } logger::info("All Papyrus functions registered."); return true; }
Why this works
-
NativeFunction<…>::Create(...)is templated on your signature, returns an object you can flag latent, and -
IVirtualMachine::RegisterFunctionhas an overload that takes aNativeFunctionBase*.
Next steps
-
Rebuild with one of the above approaches.
-
Drop a
PrintScreen.logintoData/SKSE/Pluginsand look fornginx
CopyEdit
TakePhoto registered successfullyto confirm the VM actually bound the latent call.
-
Re-compile your
.pscto a.pexand make sure it lives inData/Scriptsso Skyrim will load your script.
Once you’re either on a CommonLibSSE-NG that supports the bool overload, or you’ve switched to the NativeFunction::Create approach, the “unknown flag” error will disappear and your latent TakePhoto will finally bind.
You said:
to move to a commonlibsse-ng >=3.7 what do I need to change in vcpakg jaon files
ChatGPT said:
Thought for 5 seconds
To pull in the 3.7-series of CommonLibSSE-NG instead of 3.6, you need to bump the version requirement in your vcpkg manifest (or remove any pin that’s holding you on 3.6). Here’s how:
-
Edit your
vcpkg.json(manifest) file
Find the entry forcommonlibsse-ngunder"dependencies"and change the version constraint. For example, if you currently have:diff
CopyEdit
{ "name": "PrintScreen", "version-string": "2.0.0", "dependencies": [ - { "name": "commonlibsse-ng", "version>=": "3.6.0" }, + { "name": "commonlibsse-ng", "version>=": "3.7.0" }, { "name": "skse64", "default-features": false }, { "name": "fmt", "default-features": false }, … ] }This tells vcpkg “I need at least version 3.7.0.”
-
Update your ports baseline (if you’re pinning by baseline)
If you have aversions/<your-baseline>.jsonthat pins ports, make sure the entry forcommonlibsse-ngis bumped to a commit or version that contains 3.7.0. If you’re not using a custom baseline, you can skip this. -
Remove any local port overrides
If you have an overlay port folder with an older copy of CommonLibSSE-NG, either delete it or update it to the 3.7.x port from the vcpkg registry. -
Re-install via vcpkg
bat
CopyEdit
cd <your-repo-root> vcpkg update # updates port versions vcpkg install --triplet x64-windowsor, if you want to force a fresh pull of the 3.7 series:
bat
CopyEdit
vcpkg remove commonlibsse-ng --recurse vcpkg install commonlibsse-ng -
Re-generate your build
Clean your CMake cache/VS sln, then re-run CMake so it picks up CommonLibSSE-NG 3.7. Now theRegisterFunction(..., true)overload should compile.
That’s all: bump the version>="3.7.0" in your vcpkg.json, ensure no older overrides are in play, and reinstall via vcpkg so that CMake finds CommonLibSSE-NG 3.7 or newer.
Tools
ChatGPT can make mistakes. Check important info.