View plansUnlimited access, team features, and more

ChatGPT o4-mini-high

Share

User

PLUS

You said:

The attached files are papyrus scripts for use in moding skyrim. They interface with a SKSE plugin. However the apear to have a reference Printscreen.checkpath which is invalid can you determine what the propper reference shouuld be and if there are any other obnious errord

ChatGPT said:

Thought for 21 seconds

In Papyrus every script‐ and function‐name is case‑sensitive, and you must import exactly the same name that your SKSE plugin registered. From what you describe, your scripts are calling:

papyrus

CopyEdit

Printscreen.checkpath(...)

but your plugin almost certainly registered a function called CheckPath in a script whose name is capitalized differently — for example:

  • Script name: PrintScreen (with a capital “S”)

  • Function name: CheckPath (camel‑case)

So your call should look like:

papyrus

CopyEdit

Import PrintScreen ; … later … Bool ok = PrintScreen.CheckPath(someString)

(or, if your plugin’s script really is named Printscreen, then Import Printscreen and Printscreen.CheckPath(...) — but always with Capital P in “Path” and matching the exact script name).

Other things to look for

  1. Import statement

    Make sure at the very top of your .psc you have:

    papyrus

    CopyEdit

    Import PrintScreen ; ← exact script name

  2. Function declarations must match

    If your SKSE plugin exposed

    cpp

    CopyEdit

    bool CheckPath(StaticFunctionTag, string path)

    then in Papyrus you should have no wrapper function of your own; you just call the static:

    papyrus

    CopyEdit

    Bool canWrite = PrintScreen.CheckPath(pathToCheck)

  3. Semicolons & End-function markers

    Papyrus requires every statement to end with a semicolon, and every function to be closed:

    papyrus

    CopyEdit

    Function MyFunc() ; … EndFunction

  4. Script/file name alignment

    The filename (PrintScreen.psc) must match the script name inside. If you’ve renamed the file, open it and verify:

    papyrus

    CopyEdit

    ScriptName PrintScreen ; ← this must match what you import

  5. Auto on properties

    Any Property definition you intend to have autogenerated getters/setters should include Auto:

    papyrus

    CopyEdit

    String Property BasePath Auto

If after renaming your import and call to exactly match your plugin’s generated .psc you still see errors, please paste the header of your Papyrus script (the ScriptName line, Import lines, and the call site) so we can verify the exact casing and signatures.

You said:

 

plugin.cpp

File

given the plugin code in pligin.cpp can you see what is not matchin in the registrations? I also note the I get errors stating the PrinScreen is undefined. I assume it needs to be imported smewhere but I don't kn ow which script of import it into. Please advise

ChatGPT said:

Thought for 10 seconds

The two things that are tripping you up are:

  1. Case‑sensitive name mismatches

  2. Latent vs. non‑latent flag swapped in your RegisterFunction calls

1. Matching the Papyrus script name and function names

In your C++ you have:

cpp

CopyEdit

vm->RegisterFunction("CheckPath", "PrintScreen", CheckPath, true); vm->RegisterFunction("TakeScreenshot","PrintScreen", TakeScreenshot, false);

That means Papyrus is looking for a script called exactly PrintScreen (capital “P” and “S”), with two static functions:

papyrus

CopyEdit

String function CheckPath (String filePath) Bool function TakeScreenshot(String basePath, String imageType, Float compression, String ddsCompressionType) latent

Your Papyrus needs to:

  1. Live in a file named PrintScreen.psc

  2. Begin with:

    papyrus

    CopyEdit

    ScriptName PrintScreen

  3. Any other script that calls into it must have at its top:

    papyrus

    CopyEdit

    Import PrintScreen

  4. And when you call the functions, you must match casing exactly:

    papyrus

    CopyEdit

    ; synchronous path check String result = PrintScreen.CheckPath("C:\MyScreenshots\") ; latent screenshot (will fire PrintScreenComplete when done) Bool ok = PrintScreen.TakeScreenshot("C:\MyScreenshots\", "png", 0.85, "none")

If you’re currently calling Printscreen.checkpath (lower‑case “s” or “c”), or your script is named Printscreen.psc or Printscreen inside, Papyrus simply won’t find it.

2. Swapping your latent flags

The fourth argument to RegisterFunction(...) is whether the function is latent (i.e. returns immediately and completes later via callback). You have:

  • CheckPath → true

  • TakeScreenshot → false

But CheckPath is a synchronous directory‑validation, while TakeScreenshot is your multi‑step latent. You need:

cpp

CopyEdit

papyrus->Register([](RE::BSScript::IVirtualMachine* vm) { // non‑latent vm->RegisterFunction("CheckPath", "PrintScreen", CheckPath, false); // latent vm->RegisterFunction("TakeScreenshot", "PrintScreen", TakeScreenshot, true); SKSE::log::info("Papyrus functions registered successfully"); return true; });

Checklist to get rid of “PrintScreen undefined” errors

  • File namePrintScreen.psc

  • Script header:

    papyrus

    CopyEdit

    ScriptName PrintScreen

  • Other scripts that call it must include:

    papyrus

    CopyEdit

    Import PrintScreen

  • Calls must match exact casing:

    papyrus

    CopyEdit

    ; not Printscreen.checkpath! String msg = PrintScreen.CheckPath(pathToTest) Bool ok = PrintScreen.TakeScreenshot(path, type, quality, ddsType)

Once you’ve got the casing consistent and swapped that latent flag, Papyrus will be able to find and bind both of your functions.

You said:

OK my formuls are defined in printscreenNS and PrintSCreen_formula_Script so I am thinking It would be better to changge the plugin.cpp registration to ,atch either the printScreenNS or Printscreen_formula_Script. Am Icorrent in this

ChatGPT said:

Thought for a few seconds

You’re absolutely on the right track: the second parameter of RegisterFunction(…, scriptName, …) must exactly match the ScriptName declared in your .psc file. If your formulas live in two separate scripts—

  • PrintscreenNS.psc (with ScriptName PrintscreenNS)

  • PrintScreen_formula_Script.psc (with ScriptName PrintScreen_formula_Script)

—you have two basic options:

1. Register under each of those script names

Simply call RegisterFunction once for each script you want to expose a given native function to. For example, if you want CheckPath available in both scripts:

cpp

CopyEdit

papyrus->Register([](RE::BSScript::IVirtualMachine* vm) { // non‑latent path checker in both scripts: vm->RegisterFunction("CheckPath", "PrintscreenNS", CheckPath, false); vm->RegisterFunction("CheckPath", "PrintScreen_formula_Script", CheckPath, false); // latent screenshot only in PrintScreen_formula_Script, for example: vm->RegisterFunction("TakeScreenshot","PrintScreen_formula_Script", TakeScreenshot, true); return true; });

That way, Papyrus scripts named either “PrintscreenNS” or “PrintScreen_formula_Script” can do:

papyrus

CopyEdit

Import PrintscreenNS String ok = PrintscreenNS.CheckPath(thePath) Import PrintScreen_formula_Script Bool done = PrintScreen_formula_Script.TakeScreenshot(basePath, type, quality, ddsType)

2. Rename your Papyrus script(s) to a single shared name

If it makes organizational sense, you can unify everything under one script, say PrintScreen. Then:

  1. Change the top of both .psc files to:

    papyrus

    CopyEdit

    ScriptName PrintScreen

  2. Alter any other script that imported the old names to do:

    papyrus

    CopyEdit

    Import PrintScreen

  3. In plugin.cpp, register once:

    cpp

    CopyEdit

    vm->RegisterFunction("CheckPath", "PrintScreen", CheckPath, false); vm->RegisterFunction("TakeScreenshot","PrintScreen", TakeScreenshot, true);

Key point

Whatever you choose, the second argument to RegisterFunction must exactly (case‑sensitively) match the ScriptName in your .psc. If Papyrus is still complaining “undefined,” double‑check:

  1. The .psc’s filename matches (e.g. PrintscreenNS.psc for ScriptName PrintscreenNS).

  2. The case of every letter in the script name.

  3. That you’ve recompiled and placed the updated .pex in your Data/Scripts/ folder before testing in‑game.

Once the names line up, your native functions will bind correctly and the “undefined” errors will vanish.

You said:

ok so check path is called by Printscreen_mainQuest and PrintScreen_MCM while takePhoto is only called by the Printscreen_mainquest. At present there is no Printscreen script and I don't want to create one. I propose to register Printscreen_Fornula since I think it contains both functions. is this possible? Am confused about the necessity for both PrintscreenNS and Printscreen_Formula. They appear to be quite convluted. I only need a checkpath function and a takephoto function. It looks like these files needlessly generate wrapper functions. I would like to simplify the code if possible

ChatGPT said:

Thought for 24 seconds

You absolutely can point both native calls at your existing Printscreen_Formula_Script—but there are two things you must get exactly right:

  1. The script‐name string in your C++ registration must match the ScriptName in your .psc

  2. The “latent” flag (fourth argument) must reflect whether the call is synchronous or not

1. Update your plugin.cpp registrations

Right now you have (via ):

cpp

CopyEdit

vm->RegisterFunction("CheckPath", "PrintScreen", CheckPath, true); vm->RegisterFunction("TakeScreenshot", "PrintScreen", TakeScreenshot, false);

To instead target your Printscreen_Formula_Script (assuming your Papyrus file begins with ScriptName Printscreen_Formula_Script), change it to:

cpp

CopyEdit

papyrus->Register([](RE::BSScript::IVirtualMachine* vm) { // non‑latent directory check vm->RegisterFunction("CheckPath", "Printscreen_Formula_Script", CheckPath, false); // latent snapshot capture vm->RegisterFunction("TakeScreenshot", "Printscreen_Formula_Script", TakeScreenshot, true); SKSE::log::info("Papyrus functions registered under Printscreen_Formula_Script"); return true; });

  • Script name "Printscreen_Formula_Script" must exactly match the name declared in your .psc (case‑sensitive).

  • CheckPath is non‑latent (→ false) because it returns immediately.

  • TakeScreenshot is latent (→ true) because it does its work over multiple frames. 

2. Adjust your Papyrus imports and calls

In every Papyrus script that invokes these functions (e.g. Printscreen_mainQuest and PrintScreen_MCM), replace any old import/call with:

papyrus

CopyEdit

Import Printscreen_Formula_Script ; Synchronous path check String result = Printscreen_Formula_Script.CheckPath(myPath) ; Latent screenshot Bool ok = Printscreen_Formula_Script.TakeScreenshot(basePath, fileType, compression, ddsType)

3. Simplify your wrapper scripts

  • Drop the separate PrintscreenNS wrapper entirely if it only forwarded arguments to Printscreen_Formula_Script.

  • Consolidate any remaining Papyrus wrapper functions into one script (Printscreen_Formula_Script) that declares the native signatures:

    papyrus

    CopyEdit

    ScriptName Printscreen_Formula_Script Function CheckPath(String path) Global Native EndFunction Function TakeScreenshot(String basePath, String imageType, Float compression, String ddsCompressionType) Global Native Latent EndFunction

    Then your game’s other scripts just import and call these natives directly, with no extra stubs.

Why this works

  • SKSE’s RegisterFunction(…, scriptName, …) makes your C++ routines appear as static methods on the named Papyrus script.

  • Papyrus will only bind them if the script name and function name exactly match.

  • By consolidating to a single Printscreen_Formula_Script, you avoid juggling multiple wrappers—and you only need to maintain one import in your quest/MCM scripts.

Once you’ve rebuilt and dropped the updated .pex into Data/Scripts/, reload Skyrim, and your calls to Printscreen_Formula_Script.CheckPath and .TakeScreenshot will resolve cleanly.

Sources

 

Tools

ChatGPT can make mistakes. Check important info.