You said:

 

logger.h

File

 

PapyrusInterface.cpp

File

 

PapyrusInterface.h

File

 

pch.h

File

 

plugin.cpp

File

 

printscreen.rc

File

 

ScreenCapture.cpp

File

 

ScreenCapture.h

File

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:

  1. Pass true when registering your latent TakePhoto.

  2. Make sure scriptName and every function name exactly match your .psc.

  3. Compile and deploy the .psc to a .pex.

  4. Check your PrintScreen.log to 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::RegisterFunction has an overload that takes a NativeFunctionBase*.

Next steps

  1. Rebuild with one of the above approaches.

  2. Drop a PrintScreen.log into Data/SKSE/Plugins and look for

    nginx

    CopyEdit

    TakePhoto registered successfully

    to confirm the VM actually bound the latent call.

  3. Re-compile your .psc to a .pex and make sure it lives in Data/Scripts so 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:

  1. Edit your vcpkg.json (manifest) file

    Find the entry for commonlibsse-ng under "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.”

  2. Update your ports baseline (if you’re pinning by baseline)

    If you have a versions/<your-baseline>.json that pins ports, make sure the entry for commonlibsse-ng is bumped to a commit or version that contains 3.7.0. If you’re not using a custom baseline, you can skip this.

  3. 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.

  4. Re-install via vcpkg

    bat

    CopyEdit

    cd <your-repo-root> vcpkg update # updates port versions vcpkg install --triplet x64-windows

    or, if you want to force a fresh pull of the 3.7 series:

    bat

    CopyEdit

    vcpkg remove commonlibsse-ng --recurse vcpkg install commonlibsse-ng

  5. Re-generate your build

    Clean your CMake cache/VS sln, then re-run CMake so it picks up CommonLibSSE-NG 3.7. Now the RegisterFunction(..., 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.