Below is a breakdown of the compiler diagnostics you reported, together with concrete edits to your three uploaded files (logger.h , PCH.h , and plugin.cpp ) that will resolve them.

1. Suppressing or replacing stdext::checked_array_iterator warnings

Warning (repeated)
'stdext::checked_array_iterator<T *>': warning STL4043: stdext::checked_array_iterator, stdext::unchecked_array_iterator, and related factory functions are non-Standard extensions and will be removed in the future. std::span (since C++20) and gsl::span can be used instead. You can define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING or _SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS to suppress this warning.

These warnings originate from Visual Studio’s use of deprecated “checked_array_iterator” in combination with <algorithm>/<iterator> calls. You have two options:

  1. Suppress the warnings globally by adding a preprocessor define (_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING) before any STL include.

  2. Migrate to std::span or gsl::span in any place that uses stdext::checked_array_iterator, if you explicitly use it. In your code, you don’t appear to be invoking stdext::checked_array_iterator manually; they are usually pulled in transitively via old versions of GSL or some other header. The quickest fix is to suppress the warning.

Recommended Fix: Suppress the warning

Insert the following line at the very top of PCH.h (so that it precedes all standard headers):

PCH.h :contentReference[oaicite:3]{index=3} ───────────────────────────────────────────────────────────────────────────────── +#define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #pragma once // SKSE first (it has its own windows includes) #include "RE/Skyrim.h" ...

By defining _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING before any standard‐library include, you will suppress all those STL4043 messages in Visual Studio 2020. If you prefer to silence all Microsoft extension deprecation warnings, use _SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS instead.

2. “logger: a symbol with this name already exists in the current scope”

Error
'logger': a symbol with this name already exists in the current scope

In logger.h you have:

namespace logger = SKSE::log; // :contentReference[oaicite:4]{index=4}

and then in plugin.cpp you do:

#include "PCH.h" // already includes logger.h #include "logger.h" // redundant (guarded by #pragma once) ... logger::error("Error: {}", msg); // :contentReference[oaicite:5]{index=5}

Because PCH.h already pulls in logger.h, Visual Studio sometimes picks up two “logger” aliases (once from precompiled headers and once from the direct include), leading to a duplicate‐symbol error. To fix this, simply remove the second #include "logger.h" from plugin.cpp, and rely on the PCH include instead.

Edit in plugin.cpp

// plugin.cpp -#include "PCH.h" -#include "logger.h" // SKSE logging setup +#include "PCH.h" // <― PCH.h already does #include "logger.h" // Remove the redundant #include "logger.h" #include <DirectXTK/DDSTextureLoader.h> #include <comdef.h> // for _com_error

After this change, the alias namespace logger = SKSE::log; (from logger.h via PCH.h) is introduced only once, eliminating the “symbol already exists” error.

3. Missing/undeclared Papyrus‐related types (BSFixedString, StaticFunctionTag, VMClassRegistry, etc.)

Errors (examples)

missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before identifier 'CheckPath' syntax error: missing ')' before '*' 'BSFixedString': redefinition 'StaticFunctionTag': redefinition 'VMClassRegistry': undeclared identifier ...

All of these errors stem from the fact that the compiler does not yet know what BSFixedString, StaticFunctionTag, VMClassRegistry, etc. mean. In SKSE 2.2.6 (and CommonLibSSE-NG 3.7), these types are defined in the RE namespace (or via SKSE’s Papyrus interface headers). In your plugin.cpp you wrote:

static BSFixedString CheckPath(StaticFunctionTag*, BSFixedString basePath) { ... } static BSFixedString Cancel(StaticFunctionTag*) { ... } static BSFixedString GetResult(StaticFunctionTag*) { ... } static bool Papyrus_TakePhoto(StaticFunctionTag*, BSFixedString basePath, BSFixedString imageType, float GIF_Duration, float Compression, BSFixedString DDS_Mode) { ... } static bool RegisterPapyrusFunctions(VMClassRegistry* registry) { registry->RegisterFunction("CheckPath", "Printscreen_Formula_script", CheckPath); ... }

But since you never introduced the RE:: namespace (nor did you include the specific Papyrus headers), the compiler sees BSFixedString and StaticFunctionTag as unknown identifiers. It then falls back to “default‐int” assumptions, cascades a bunch of syntax errors, and ends up thinking you’re redefining “int BSFixedString” multiple times.

What to do

  1. Include the Papyrus interface header from SKSE so that the types RE::BSFixedString, RE::StaticFunctionTag, and RE::VMClassRegistry are visible. Typically, this is:

    #include "SKSE/PapyrusInterface.h" // <― defines Papyrus::Interface, but not always the types #include "SKSE/PapyrusNativeFunctions.h"

    In CommonLibSSE-NG, you may also see:

    #include "SKSE/ReversibleScopedLock.h" #include "SKSE/Papyrus.h"

    But the most crucial include is PapyrusNativeFunctions.h, which lives under your SKSE include path.

  2. Either qualify all Papyrus‐exposed types with RE:: (e.g. RE::BSFixedString) or add a using namespace RE; after your includes. The latter is more concise but imports everything from RE.

Recommended Fix: Add using namespace RE; and ensure Papyrus includes

In plugin.cpp (immediately after the PCH include) insert:

plugin.cpp :contentReference[oaicite:7]{index=7} ──────────────────────────────────────────────────────────────────────────────── #include "PCH.h" // already brings in SKSE/SKSE.h etc. -#include <DirectXTK/DDSTextureLoader.h> +#include "SKSE/PapyrusNativeFunctions.h" // <― makes BSFixedString, StaticFunctionTag, VMClassRegistry visible +#include <DirectXTK/DDSTextureLoader.h> #include <comdef.h> // for _com_error +using namespace RE; // <― so that BSFixedString, StaticFunctionTag, VMClassRegistry resolve + static std::atomic<bool> g_stopFlag{ false }; static std::atomic<bool> g_isRunning{ false }; ...

Explanation:

  • By including "SKSE/PapyrusNativeFunctions.h", you pull in the definitions for RE::BSFixedString, RE::StaticFunctionTag, and RE::VMClassRegistry.

  • By adding using namespace RE;, you allow unqualified usage of BSFixedString, StaticFunctionTag, and VMClassRegistry exactly as you wrote them.

  • If you would rather keep your code “fully qualified,” you can remove using namespace RE; and change every occurrence of BSFixedStringRE::BSFixedString, StaticFunctionTagRE::StaticFunctionTag, and VMClassRegistryRE::VMClassRegistry.

4. Wrong function name passed to RegisterFunction for the “TakePhoto” entry

Error

'TakePhoto': undeclared identifier

In your call to register Papyrus functions, you wrote:

registry->RegisterFunction("TakePhoto", "Printscreen_Formula_script", TakePhoto);

but your actual C++ function is named Papyrus_TakePhoto(...). Because there is no free‐standing TakePhoto symbol, the compiler complains. You must pass the exact C++ function pointer, not just the intended Papyrus name. In other words, change TakePhoto to Papyrus_TakePhoto.

Edit in plugin.cpp

static bool RegisterPapyrusFunctions(VMClassRegistry* registry) { - registry->RegisterFunction("CheckPath", "Printscreen_Formula_script", CheckPath); - registry->RegisterFunction("TakePhoto", "Printscreen_Formula_script", TakePhoto); - registry->RegisterFunction("GetResult", "Printscreen_Formula_script", GetResult); - registry->RegisterFunction("Cancel", "Printscreen_Formula_script", Cancel); + registry->RegisterFunction("CheckPath", "Printscreen_Formula_script", CheckPath); + registry->RegisterFunction("TakePhoto", "Printscreen_Formula_script", Papyrus_TakePhoto); + registry->RegisterFunction("GetResult", "Printscreen_Formula_script", GetResult); + registry->RegisterFunction("Cancel", "Printscreen_Formula_script", Cancel); return true; }

After this change, the compiler will find Papyrus_TakePhoto (because you defined it at top) and correctly bind it to “TakePhoto” in Papyrus.

5. Undefined DirectX compression constant TEX_COMPRESS_BC6H_DITHER

Errors

'TEX_COMPRESS_BC6H_DITHER': is not a member of 'DirectX' 'TEX_COMPRESS_BC6H_DITHER': undeclared identifier

These stem from code in your “omitted” capture loop, where you attempt to use something like:

DirectX::TEX_COMPRESS_BC6H_DITHER // or simply TEX_COMPRESS_BC6H_DITHER

But your installed version of DirectXTex (as surfaced in VS2020) does not define that particular compression flag. In DirectXTex 3.x (the one VS2020 shipped with), BC6H dithering constants may be named differently (e.g. TEX_COMPRESS_BC6H or TEX_COMPRESS_BC6H | TEX_COMPRESS_DITHER).

Two possible remedies:

  1. Use the existing constant that your version supports. For example, if you only need BC6H without dithering, switch to:

    DirectX::TEX_COMPRESS_BC6H

    or combine flags manually:

    DirectX::TEX_COMPRESS_BC6H | DirectX::TEX_COMPRESS_DITHER

    depending on whether your version defines TEX_COMPRESS_DITHER.

  2. Upgrade to a newer DirectXTex (e.g. DirectXTex-2021 or later), which does define TEX_COMPRESS_BC6H_DITHER. If you choose this route, make sure your include path (and library binaries) point to the updated DirectXTex.

Below is an example edit assuming you only need plain BC6H compression (no dithering). Find and replace every occurrence of TEX_COMPRESS_BC6H_DITHER in plugin.cpp with TEX_COMPRESS_BC6H (or another valid constant). For example:

// Somewhere in the omitted capture‐loop code in plugin.cpp :contentReference[oaicite:9]{index=9} - // old (fails in VS2020): - flags = DirectX::TEX_COMPRESS_BC6H_DITHER; + // new (supported by DirectXTex shipped with VS2020): + flags = DirectX::TEX_COMPRESS_BC6H;

If your version also provides a separate dithering flag (e.g. TEX_COMPRESS_DITHER), you can write:

flags = DirectX::TEX_COMPRESS_BC6H | DirectX::TEX_COMPRESS_DITHER;

But in any case, remove references to TEX_COMPRESS_BC6H_DITHER if it does not exist in your DirectXTex headers.

6. Remaining “syntax error: missing …” diagnostics & default‐int assumptions

Errors

missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before identifier 'CheckPath' syntax error: missing ')' before '*' syntax error: missing ';' before '*' 'int BSFixedString': redefinition syntax error: missing ';' before identifier 'Cancel' ...

Once you fix points 3 (Papyrus includes + using namespace RE;) and 4 (correct function name Papyrus_TakePhoto), these syntax errors will all vanish. They were cascading side‐effects of the compiler not recognizing BSFixedString, StaticFunctionTag, TakePhoto, etc.

7. Summary of all required edits

Below is a concise checklist of every change to apply:

  1. PCH.h

    #define _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING #pragma once // SKSE first (it has its own windows includes) #include "RE/Skyrim.h" #include "SKSE/SKSE.h" // ... rest unchanged ... #include "logger.h"

  2. plugin.cpp

    // plugin.cpp

-#include "PCH.h"
-#include "logger.h" // SKSE logging setup (redundant)
+#include "PCH.h" // PCH.h already pulls in logger.h
+#include "SKSE/PapyrusNativeFunctions.h" // <― pull in BSFixedString, StaticFunctionTag, VMClassRegistry, etc.
#include <DirectXTK/DDSTextureLoader.h>
#include <comdef.h> // for _com_error

+using namespace RE; // <― allow BSFixedString, StaticFunctionTag, VMClassRegistry unqualified

static std::atomic g_stopFlag{ false };
static std::atomic g_isRunning{ false };
static std::mutex g_resultMutex;
static std::string g_lastResult = "Success";

// … rest of CaptureLoop & helper code …

// Papyrus‐exposed: TakePhoto(...) → bool (latent)
-static bool Papyrus_TakePhoto(StaticFunctionTag*, BSFixedString basePath,
+static bool Papyrus_TakePhoto(StaticFunctionTag*, BSFixedString basePath,
BSFixedString imageType, float GIF_Duration,
float Compression, BSFixedString DDS_Mode) {
// … unchanged …
}

// Register Papyrus functions
static bool RegisterPapyrusFunctions(VMClassRegistry* registry) {

  • registry->RegisterFunction("CheckPath", "Printscreen_Formula_script", CheckPath);

  • registry->RegisterFunction("TakePhoto", "Printscreen_Formula_script", TakePhoto);

  • registry->RegisterFunction("GetResult", "Printscreen_Formula_script", GetResult);

  • registry->RegisterFunction("Cancel", "Printscreen_Formula_script", Cancel);

  • registry->RegisterFunction("CheckPath", "Printscreen_Formula_script", CheckPath);

  • registry->RegisterFunction("TakePhoto", "Printscreen_Formula_script", Papyrus_TakePhoto);

  • registry->RegisterFunction("GetResult", "Printscreen_Formula_script", GetResult);

  • registry->RegisterFunction("Cancel", "Printscreen_Formula_script", Cancel);

    return true;
    }

extern "C" DLLEXPORT bool SKSEAPI SKSEPlugin_Load(const SKSE::LoadInterface* skse) {
SKSE::Init(skse);
// Setup SKSE‐based logging; fallback on exception
try {
SetupLog();
logger::info("Logger initialized successfully");
} catch (...) {
FallbackEventLog("Failed to initialize SKSE logger, using Windows Event Log");
}
SKSE::GetPapyrusInterface()->Register(RegisterPapyrusFunctions);
return true;
}

3. **Replace any use of** `TEX_COMPRESS_BC6H_DITHER` **in the capture loop** with a valid, supported flag—e.g.: ```diff // Inside the CaptureLoop (omitted for brevity) :contentReference[oaicite:12]{index=12} - flags = DirectX::TEX_COMPRESS_BC6H_DITHER; + flags = DirectX::TEX_COMPRESS_BC6H;

or, if dithering is supported separately:

flags = DirectX::TEX_COMPRESS_BC6H | DirectX::TEX_COMPRESS_DITHER;

depending on which constants your DirectXTex version provides.

  1. Remove the redundant #include "logger.h" from plugin.cpp so that the alias namespace logger = SKSE::log; (inside logger.h) is introduced only once via the PCH.

After applying all of the above:

  • The STD4043 warnings will be silenced by _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING in PCH.h.

  • The duplicate “logger” symbol will go away since you no longer include logger.h twice.

  • The Papyrus native types (BSFixedString, StaticFunctionTag, VMClassRegistry, etc.) will be known because you added #include "SKSE/PapyrusNativeFunctions.h" and using namespace RE;.

  • The “TakePhoto” undeclared‐identifier error will be fixed because you now pass the correct function pointer Papyrus_TakePhoto to RegisterFunction.

  • The TEX_COMPRESS_BC6H_DITHER errors will vanish after replacing that constant with a name that actually exists in your DirectXTex.

  • All remaining “missing type specifier” or “syntax error” diagnostics will disappear once the above two root causes (Papyrus types unknown + wrong function name) are corrected.

With those edits in place, your plugin should compile cleanly under Visual Studio 2020.