Updated DLL for compatibility with SSE 1.7.99
This commit is contained in:
parent
579239e4f4
commit
3939ba1daa
BIN
SKSE/Plugins/versionlib-1-7-99-0.bin
(Stored with Git LFS)
Normal file
BIN
SKSE/Plugins/versionlib-1-7-99-0.bin
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -145,8 +145,9 @@ set(BUILD_TESTS OFF CACHE BOOL " " FORCE)
|
||||
message(STATUS "Fetching CommonLibSSE-NG...")
|
||||
FetchContent_Declare(
|
||||
CommonLibSSE
|
||||
GIT_REPOSITORY https://github.com/alandtse/CommonLibVR
|
||||
GIT_TAG aacbd76c01bff9381e253ffdfcb4f9d5f263f1df
|
||||
GIT_REPOSITORY https://github.com/alandtse/CommonLibSSE-NG
|
||||
GIT_TAG 8b48fb1b76d6ce9353af138d86037b4246c73527
|
||||
PATCH_COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/patch_commonlibsse.cmake"
|
||||
)
|
||||
FetchContent_MakeAvailable(CommonLibSSE)
|
||||
|
||||
|
||||
80
source/Enderal DLL/cmake/patch_commonlibsse.cmake
Normal file
80
source/Enderal DLL/cmake/patch_commonlibsse.cmake
Normal file
@ -0,0 +1,80 @@
|
||||
# Patch applied to CommonLibSSE-NG via FetchContent PATCH_COMMAND.
|
||||
#
|
||||
# Skyrim AE 1.7.99 inserts two event sink bases into RE::SkyrimVM at 0x180 and
|
||||
# 0x188, so every member from 0x180 onwards moves up by 0x10. CommonLibSSE-NG
|
||||
# 6.5.0 modelled most of that shift (handlePolicy, the runtime data blocks and
|
||||
# the tail block all get version aware accessors), but it left the pointer block
|
||||
# that starts at "impl" declared at its pre-1.7.99 offsets.
|
||||
#
|
||||
# "impl" holds the BSScript::IVirtualMachine the whole Papyrus layer runs on:
|
||||
#
|
||||
# RE::BSScript::Internal::VirtualMachine::GetSingleton()
|
||||
# -> SkyrimVM::GetSingleton()->impl.get()
|
||||
#
|
||||
# On 1.7.99 that reads offset 0x200, which now lands inside the preceding
|
||||
# BSTEventSource, so the singleton is null or garbage. The visible effects are
|
||||
# "Failed to get vm type id for class <n>!" for every object typed Papyrus
|
||||
# parameter (RE::BSScript::GetRawTypeFromVMType null checks the pointer) and a
|
||||
# crash in any caller that does not (Papyrus argument marshalling in
|
||||
# PackUnpack.cpp, and this plugin's own script checks).
|
||||
#
|
||||
# The patch adds a version aware GetImpl() and routes the two in tree consumers
|
||||
# through it. It deliberately leaves the member declarations alone, so every
|
||||
# layout static_assert still holds.
|
||||
#
|
||||
# Verification: 61 call sites in SkyrimSE.exe 1.6.1170 read the field at
|
||||
# [SkyrimVM + 0x200], and the matching 61 sites in 1.7.99 read [SkyrimVM + 0x210].
|
||||
#
|
||||
# Remove this file, its two PATCH_COMMAND entries and this note once upstream
|
||||
# fixes the offset. The script is idempotent, and it fails the configure step if
|
||||
# any of the three anchors is missing, so a bump that changes or fixes this code
|
||||
# is reported instead of silently producing an unpatched build.
|
||||
|
||||
set(_clib_header "include/RE/S/SkyrimVM.h")
|
||||
set(_clib_vm "src/RE/V/VirtualMachine.cpp")
|
||||
set(_clib_skvm "src/RE/S/SkyrimVM.cpp")
|
||||
|
||||
set(_clib_marker "GetImpl")
|
||||
|
||||
set(_clib_accessor
|
||||
" // AE 1.7.99 shifts every member from 0x180 onwards by +0x10, and impl is
|
||||
// declared at its pre-1.7.99 offset. Read it through here, never directly.
|
||||
[[nodiscard]] inline BSTSmartPointer<BSScript::IVirtualMachine>& GetImpl() noexcept
|
||||
{
|
||||
// Only AE reaches 1.7.99, so the version test alone selects the runtime.
|
||||
return REL::RelocateMemberIfNewer<BSTSmartPointer<BSScript::IVirtualMachine>>(
|
||||
SKSE::RUNTIME_SSE_1_7_99, this, 0x200, 0x210);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const BSTSmartPointer<BSScript::IVirtualMachine>& GetImpl() const noexcept
|
||||
{
|
||||
return const_cast<SkyrimVM*>(this)->GetImpl();
|
||||
}
|
||||
|
||||
static SkyrimVM* GetSingleton();")
|
||||
|
||||
function(_clib_patch_file path from to)
|
||||
if(NOT EXISTS "${path}")
|
||||
message(FATAL_ERROR "CommonLibSSE patch: ${path} is missing.")
|
||||
endif()
|
||||
file(READ "${path}" _content)
|
||||
string(FIND "${_content}" "${_clib_marker}" _found)
|
||||
if(_found GREATER_EQUAL 0)
|
||||
return() # already patched
|
||||
endif()
|
||||
string(FIND "${_content}" "${from}" _anchor)
|
||||
if(_anchor LESS 0)
|
||||
message(FATAL_ERROR
|
||||
"CommonLibSSE patch: anchor not found in ${path}.\n"
|
||||
"Check whether upstream fixed SkyrimVM::impl for AE 1.7.99. If it did, "
|
||||
"delete cmake/patch_commonlibsse.cmake and its PATCH_COMMAND entries.")
|
||||
endif()
|
||||
string(REPLACE "${from}" "${to}" _content "${_content}")
|
||||
file(WRITE "${path}" "${_content}")
|
||||
endfunction()
|
||||
|
||||
_clib_patch_file("${_clib_header}" " static SkyrimVM* GetSingleton();" "${_clib_accessor}")
|
||||
_clib_patch_file("${_clib_vm}" "vm->impl.get()" "vm->GetImpl().get()")
|
||||
_clib_patch_file("${_clib_skvm}" "impl.get()->SendEvent" "GetImpl().get()->SendEvent")
|
||||
|
||||
message(STATUS "Patched CommonLibSSE-NG SkyrimVM::impl for AE 1.7.99.")
|
||||
@ -9,7 +9,7 @@ namespace AchievementFix
|
||||
if (REL::Module::IsVR()) {
|
||||
target = REL::Offset(0x17FB90);
|
||||
} else if (REL::Module::get().version() >= REL::Version(1, 6, 1130, 0)) {
|
||||
// Checked: 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
target = REL::ID(441528);
|
||||
} else {
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659
|
||||
|
||||
@ -35,7 +35,7 @@ namespace BinkInterruptPatch
|
||||
|
||||
void Install()
|
||||
{
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
REL::Relocation<std::uintptr_t> target{ REL::RelocationID(87890, 90259), REL::Relocate(0x22, 0x21) };
|
||||
SKSE::AllocTrampoline(14);
|
||||
BinkListener::func = SKSE::GetTrampoline().write_call<5>(target.address(), BinkListener::thunk);
|
||||
|
||||
@ -89,7 +89,7 @@ private:
|
||||
// A failsafe when Goodbye does not close the dialogue menu.
|
||||
if (bTabBlocked) {
|
||||
auto* mtm = RE::MenuTopicManager::GetSingleton();
|
||||
if (mtm && mtm->isSayingGoodbye && !mtm->currentTopicInfo && RE::UI::GetSingleton()->IsMenuOpen(MENU_NAME)) {
|
||||
if (mtm && mtm->forceGoodbye && !mtm->currentTopicInfo && RE::UI::GetSingleton()->IsMenuOpen(MENU_NAME)) {
|
||||
BlockTab(false);
|
||||
}
|
||||
}
|
||||
@ -121,7 +121,7 @@ private:
|
||||
void static OpenJournal(bool a_bool)
|
||||
{
|
||||
using func_t = decltype(&OpenJournal);
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
REL::Relocation<func_t> func{ REL::VariantID(52428, 53327, 0x92F0F0) };
|
||||
func(a_bool);
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ namespace FlatMapMarkers
|
||||
|
||||
inline void Install()
|
||||
{
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
REL::Relocation<std::uintptr_t> offset{ REL::RelocationID(52224, 53111), REL::Relocate(0x22F, 0x21F) };
|
||||
SKSE::AllocTrampoline(14);
|
||||
SKSE::GetTrampoline().write_call<5>(offset.address(), &Hook_WorldPtToScreenPt3);
|
||||
|
||||
@ -3,6 +3,12 @@
|
||||
// Bink playback is prone to freezing in bordered window, we enforce borderless mode here
|
||||
namespace ForceBorderless
|
||||
{
|
||||
// The patched instruction reads the fullscreen flag the window style is built from, and is
|
||||
// "movzx eax, byte ptr [rip+disp32]" on every runtime checked so far. Only the three opcode
|
||||
// bytes are compared: the displacement moves with every build, while the opcode alone already
|
||||
// pins the instruction length at 7 bytes, which is exactly what the replacement occupies.
|
||||
constexpr std::uint8_t FULLSCREEN_READ[]{ 0x0F, 0xB6, 0x05 };
|
||||
|
||||
void Install()
|
||||
{
|
||||
if (REL::Module::IsVR()) {
|
||||
@ -11,20 +17,31 @@ namespace ForceBorderless
|
||||
|
||||
std::uint8_t code[] = { 0xB8, 0x01, 0x00, 0x00, 0x00, REL::NOP, REL::NOP }; // mov eax,0x1
|
||||
auto version = REL::Module::get().version();
|
||||
std::uintptr_t target = 0;
|
||||
|
||||
if (version >= REL::Version(1, 6, 1130, 0) && version <= REL::Version(1, 6, 1179, 0)) {
|
||||
logger::info("Initializing borderless mode...");
|
||||
REL::Relocation<std::uintptr_t> target{ REL::ID(36547), 0xBEA };
|
||||
REL::safe_write(target.address(), code, sizeof(code));
|
||||
// Checked: 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
if (version >= REL::Version(1, 6, 1130, 0)) {
|
||||
target = REL::Relocation<std::uintptr_t>{ REL::ID(36547), 0xBEA }.address();
|
||||
|
||||
} else if (version >= REL::Version(1, 5, 97, 0) && version < REL::Version(1, 6, 1130, 0)) {
|
||||
logger::info("Initializing borderless mode...");
|
||||
REL::Relocation<std::uintptr_t> target{ REL::RelocationID(35548, 36547), REL::Relocate(0x83A, version >= REL::Version(1, 6, 342, 0) ? version >= REL::Version(1, 6, 629, 0) ? 0xCFA : 0xCDA : 0xCBB) };
|
||||
REL::safe_write(target.address(), code, sizeof(code));
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659
|
||||
} else if (version >= REL::Version(1, 5, 97, 0)) {
|
||||
target = REL::Relocation<std::uintptr_t>{ REL::RelocationID(35548, 36547), REL::Relocate(0x83A, version >= REL::Version(1, 6, 342, 0) ? version >= REL::Version(1, 6, 629, 0) ? 0xCFA : 0xCDA : 0xCBB) }.address();
|
||||
|
||||
} else {
|
||||
logger::info("Untested version of Skyrim, skipping borderless mode...");
|
||||
return;
|
||||
}
|
||||
|
||||
// The branch above is open ended, so a future build resolves an offset nobody checked.
|
||||
// Confirm the instruction is the expected read before overwriting it. A build that moved
|
||||
// the read loses borderless mode, instead of getting seven bytes written into the middle
|
||||
// of whatever landed there.
|
||||
if (!target || std::memcmp(reinterpret_cast<const void*>(target), FULLSCREEN_READ, sizeof(FULLSCREEN_READ)) != 0) {
|
||||
logger::error("Unexpected instruction at the fullscreen check, skipping borderless mode...");
|
||||
return;
|
||||
}
|
||||
|
||||
logger::info("Initializing borderless mode...");
|
||||
REL::safe_write(target, code, sizeof(code));
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,15 +8,15 @@ namespace GogVramLeakFix
|
||||
{
|
||||
static void thunk(RE::BSGraphics::Renderer* a_renderer, RE::BSGraphics::Texture* a_texture)
|
||||
{
|
||||
if (_InterlockedExchangeAdd(&a_texture->unk20, 0xFFFFFFFF) == 1) {
|
||||
if (_InterlockedExchangeAdd(&a_texture->refCount, 0xFFFFFFFF) == 1) {
|
||||
if (a_texture->resourceView) {
|
||||
a_texture->resourceView->Release();
|
||||
}
|
||||
if (a_texture->texture) {
|
||||
a_texture->texture->Release();
|
||||
}
|
||||
if (a_texture->unk08) {
|
||||
reinterpret_cast<ID3D11UnorderedAccessView*>(a_texture->unk08)->Release();
|
||||
if (a_texture->UAV) {
|
||||
a_texture->UAV->Release();
|
||||
}
|
||||
|
||||
REL::Relocation<void(void*, int)> NiMemFree{ REL::RelocationID(102158, 109588) };
|
||||
|
||||
@ -38,7 +38,7 @@ void HeroMenuPatch::Install(bool aAutoScaleHeroMenu)
|
||||
}
|
||||
|
||||
// Patch the Quick Stats hotkey to open the menu
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
REL::Relocation<std::uintptr_t> target{ REL::RelocationID(51400, 52249), REL::Relocate(0x41E, 0x421) };
|
||||
REL::safe_fill(target.address(), REL::NOP, 45);
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ namespace MapMarkerPlacement
|
||||
void InstallPlacementDiscoveredFix()
|
||||
{
|
||||
// Place a marker, if a location has been discovered and fast travel is disabled
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
REL::Relocation<std::uintptr_t> target{ REL::RelocationID(52208, 53095), REL::Relocate(0x2C5, 0x328, 0x358) };
|
||||
SKSE::AllocTrampoline(14);
|
||||
IsFastTravelEnabled::func = SKSE::GetTrampoline().write_call<5>(target.address(), IsFastTravelEnabled::thunk);
|
||||
@ -32,7 +32,7 @@ namespace MapMarkerPlacement
|
||||
void InstallPlacementUndiscoveredFix()
|
||||
{
|
||||
// Place a marker without asking, if a location isn't discovered yet
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
REL::Relocation<std::uintptr_t> target2{ REL::RelocationID(52208, 53095), REL::Relocate(0x17A, 0x183) };
|
||||
std::uint8_t code[] = { 0xB0, 0x01, REL::NOP, REL::NOP, REL::NOP }; // mov al,0x1
|
||||
REL::safe_write(target2.address(), code, sizeof(code));
|
||||
|
||||
@ -110,7 +110,7 @@ namespace MenuAspectRatioFix
|
||||
{
|
||||
g_restoreScaleModes = REL::Module::get().version() >= REL::Version(1, 6, 1130, 0);
|
||||
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
const auto target = REL::RelocationID(80302, 82325).address();
|
||||
|
||||
// mov rax,rsp followed by one argument spill - 7 bytes of position-independent code, which
|
||||
|
||||
@ -11,7 +11,7 @@ private:
|
||||
static void OpenMenu(RE::IMenu* tweenMenu, std::int32_t index)
|
||||
{
|
||||
using func_t = decltype(&OpenMenu);
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
REL::Relocation<func_t> func{ REL::VariantID(51845, 52718, 0x8FE7E0) };
|
||||
return func(tweenMenu, index);
|
||||
}
|
||||
|
||||
@ -237,7 +237,7 @@ inline void CloseTweenMenu()
|
||||
{
|
||||
if (RE::UI::GetSingleton()->IsMenuOpen(RE::TweenMenu::MENU_NAME)) {
|
||||
using func_t = decltype(&CloseTweenMenu);
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179
|
||||
// Checked: 1.5.97, 1.6.640, 1.6.659, 1.6.1130, 1.6.1170, 1.6.1179, 1.7.99
|
||||
REL::Relocation<func_t> func{ REL::VariantID(51839, 52711, 0x8FE180) };
|
||||
func();
|
||||
}
|
||||
|
||||
@ -140,8 +140,9 @@ set(BUILD_TESTS OFF CACHE BOOL " " FORCE)
|
||||
message(STATUS "Fetching CommonLibSSE-NG...")
|
||||
FetchContent_Declare(
|
||||
CommonLibSSE
|
||||
GIT_REPOSITORY https://github.com/alandtse/CommonLibVR
|
||||
GIT_TAG aacbd76c01bff9381e253ffdfcb4f9d5f263f1df
|
||||
GIT_REPOSITORY https://github.com/alandtse/CommonLibSSE-NG
|
||||
GIT_TAG 8b48fb1b76d6ce9353af138d86037b4246c73527
|
||||
PATCH_COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/patch_commonlibsse.cmake"
|
||||
)
|
||||
FetchContent_MakeAvailable(CommonLibSSE)
|
||||
|
||||
|
||||
80
source/Steam DLL/cmake/patch_commonlibsse.cmake
Normal file
80
source/Steam DLL/cmake/patch_commonlibsse.cmake
Normal file
@ -0,0 +1,80 @@
|
||||
# Patch applied to CommonLibSSE-NG via FetchContent PATCH_COMMAND.
|
||||
#
|
||||
# Skyrim AE 1.7.99 inserts two event sink bases into RE::SkyrimVM at 0x180 and
|
||||
# 0x188, so every member from 0x180 onwards moves up by 0x10. CommonLibSSE-NG
|
||||
# 6.5.0 modelled most of that shift (handlePolicy, the runtime data blocks and
|
||||
# the tail block all get version aware accessors), but it left the pointer block
|
||||
# that starts at "impl" declared at its pre-1.7.99 offsets.
|
||||
#
|
||||
# "impl" holds the BSScript::IVirtualMachine the whole Papyrus layer runs on:
|
||||
#
|
||||
# RE::BSScript::Internal::VirtualMachine::GetSingleton()
|
||||
# -> SkyrimVM::GetSingleton()->impl.get()
|
||||
#
|
||||
# On 1.7.99 that reads offset 0x200, which now lands inside the preceding
|
||||
# BSTEventSource, so the singleton is null or garbage. The visible effects are
|
||||
# "Failed to get vm type id for class <n>!" for every object typed Papyrus
|
||||
# parameter (RE::BSScript::GetRawTypeFromVMType null checks the pointer) and a
|
||||
# crash in any caller that does not (Papyrus argument marshalling in
|
||||
# PackUnpack.cpp, and this plugin's own script checks).
|
||||
#
|
||||
# The patch adds a version aware GetImpl() and routes the two in tree consumers
|
||||
# through it. It deliberately leaves the member declarations alone, so every
|
||||
# layout static_assert still holds.
|
||||
#
|
||||
# Verification: 61 call sites in SkyrimSE.exe 1.6.1170 read the field at
|
||||
# [SkyrimVM + 0x200], and the matching 61 sites in 1.7.99 read [SkyrimVM + 0x210].
|
||||
#
|
||||
# Remove this file, its two PATCH_COMMAND entries and this note once upstream
|
||||
# fixes the offset. The script is idempotent, and it fails the configure step if
|
||||
# any of the three anchors is missing, so a bump that changes or fixes this code
|
||||
# is reported instead of silently producing an unpatched build.
|
||||
|
||||
set(_clib_header "include/RE/S/SkyrimVM.h")
|
||||
set(_clib_vm "src/RE/V/VirtualMachine.cpp")
|
||||
set(_clib_skvm "src/RE/S/SkyrimVM.cpp")
|
||||
|
||||
set(_clib_marker "GetImpl")
|
||||
|
||||
set(_clib_accessor
|
||||
" // AE 1.7.99 shifts every member from 0x180 onwards by +0x10, and impl is
|
||||
// declared at its pre-1.7.99 offset. Read it through here, never directly.
|
||||
[[nodiscard]] inline BSTSmartPointer<BSScript::IVirtualMachine>& GetImpl() noexcept
|
||||
{
|
||||
// Only AE reaches 1.7.99, so the version test alone selects the runtime.
|
||||
return REL::RelocateMemberIfNewer<BSTSmartPointer<BSScript::IVirtualMachine>>(
|
||||
SKSE::RUNTIME_SSE_1_7_99, this, 0x200, 0x210);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const BSTSmartPointer<BSScript::IVirtualMachine>& GetImpl() const noexcept
|
||||
{
|
||||
return const_cast<SkyrimVM*>(this)->GetImpl();
|
||||
}
|
||||
|
||||
static SkyrimVM* GetSingleton();")
|
||||
|
||||
function(_clib_patch_file path from to)
|
||||
if(NOT EXISTS "${path}")
|
||||
message(FATAL_ERROR "CommonLibSSE patch: ${path} is missing.")
|
||||
endif()
|
||||
file(READ "${path}" _content)
|
||||
string(FIND "${_content}" "${_clib_marker}" _found)
|
||||
if(_found GREATER_EQUAL 0)
|
||||
return() # already patched
|
||||
endif()
|
||||
string(FIND "${_content}" "${from}" _anchor)
|
||||
if(_anchor LESS 0)
|
||||
message(FATAL_ERROR
|
||||
"CommonLibSSE patch: anchor not found in ${path}.\n"
|
||||
"Check whether upstream fixed SkyrimVM::impl for AE 1.7.99. If it did, "
|
||||
"delete cmake/patch_commonlibsse.cmake and its PATCH_COMMAND entries.")
|
||||
endif()
|
||||
string(REPLACE "${from}" "${to}" _content "${_content}")
|
||||
file(WRITE "${path}" "${_content}")
|
||||
endfunction()
|
||||
|
||||
_clib_patch_file("${_clib_header}" " static SkyrimVM* GetSingleton();" "${_clib_accessor}")
|
||||
_clib_patch_file("${_clib_vm}" "vm->impl.get()" "vm->GetImpl().get()")
|
||||
_clib_patch_file("${_clib_skvm}" "impl.get()->SendEvent" "GetImpl().get()->SendEvent")
|
||||
|
||||
message(STATUS "Patched CommonLibSSE-NG SkyrimVM::impl for AE 1.7.99.")
|
||||
@ -15,7 +15,7 @@ namespace Papyrus::PapyrusFunctions
|
||||
}
|
||||
return steam->setAchievementUnlocked(achievement.c_str());
|
||||
} else {
|
||||
RE::DebugNotification(std::format("Achievement unlocked: {}", achievement.c_str()).c_str());
|
||||
RE::SendHUDMessage::ShowHUDMessage(std::format("Achievement unlocked: {}", achievement.c_str()).c_str());
|
||||
logger::info("{}", std::format("Achievement unlocked: {}", achievement.c_str()).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user