So would this not be compatible with the SE version of Skyrim? I get an SKSE dll loader warning saying that the homproj.dll: LE plugin can't be used with SE.
I myself tried recompiling and updating the le source code with no luck using CLion ai asisstant. If anyone can do better or give me pointers have at it. either way i dont care anymore. homproj.cpp #include <string> #include <cmath> #include <cfloat> #include <map> #include "fud.h" #include "skse64/PluginAPI.h" #include "skse64_common/Relocation.h" #include "skse64_common/Utilities.h" #include "skse64/GameAPI.h" #include "skse64/GameObjects.h" #include "skse64/GameReferences.h" #include "skse64/GameCamera.h" #include "skse64/NiObjects.h"
using UInt8 = uint8_t; using UInt16 = uint16_t; using UInt32 = uint32_t; using UInt64 = uint64_t; using SInt8 = int8_t; using SInt16 = int16_t; using SInt32 = int32_t;
constexpr int DEBUG_STRING_SIZE = 256;
#define ASSERT(...) #define STATIC_ASSERT(...) #define _MESSAGE(...) #define __MACRO_JOIN__(a, b) __MACRO_JOIN_2__(a, b) #define __MACRO_JOIN_2__(a, b) __MACRO_JOIN_3__(a, b) #define __MACRO_JOIN_3__(a, b) a##b
This would be dope as a series of side-grade spells. Lower damage than equal tier missiles but obviously homing. Or a salvo of stingers with even lower damage.
9 comments
homproj.cpp
#include <string>
#include <cmath>
#include <cfloat>
#include <map>
#include "fud.h"
#include "skse64/PluginAPI.h"
#include "skse64_common/Relocation.h"
#include "skse64_common/Utilities.h"
#include "skse64/GameAPI.h"
#include "skse64/GameObjects.h"
#include "skse64/GameReferences.h"
#include "skse64/GameCamera.h"
#include "skse64/NiObjects.h"
static const int BUFFER_SIZE = 512;
static PluginHandle pluginHandle = kPluginHandle_Invalid;
static wchar_t moduleFileName[BUFFER_SIZE], iniFileName[BUFFER_SIZE], folderName[BUFFER_SIZE];
static TESForm* (*GetFormById)(UInt32) = nullptr; // Replace with correct address
static bool (*GetObjectByHandle2)(UInt32* refHandle, TESObjectREFR**) = nullptr; // Replace with correct address
static bool (*GetRefObjectByHandle)(UInt32* refHandle, BSHandleRefObject**) = nullptr; // Replace with correct address
static double casterZAdjust, npcSpringMult, pcSpringMult, npcBonusRate, pcBonusRate, npcMagnetMult, pcMagnetMult, pcDragMult, macularArea;
static int forceNpcGuided, forcePcGuided, aimingPeriod, cellScanner, useLock;
static CRITICAL_SECTION handleLock, projectileLock, targetLock;
#define USELOCK
#ifdef USELOCK
#define EnterCriticalSectionIfUsed(x) if(useLock) EnterCriticalSection(x)
#define LeaveCriticalSectionIfUsed(x) if(useLock) LeaveCriticalSection(x)
#else
#define EnterCriticalSectionIfUsed(x)
#define LeaveCriticalSectionIfUsed(x)
#endif
extern "C" {
int __stdcall DllMain(HMODULE baseAddr, unsigned reason, unsigned reserved) {
if (reason == DLL_PROCESS_ATTACH) {
GetModuleFileNameW(baseAddr, moduleFileName, BUFFER_SIZE);
wcsncpy(iniFileName, moduleFileName, BUFFER_SIZE);
wcsncpy(folderName, moduleFileName, BUFFER_SIZE);
int len = wcslen(iniFileName);
iniFileName[len - 1] = L'i';
iniFileName[len - 2] = L'n';
iniFileName[len - 3] = L'i';
while (len-- > 0 && folderName[len] != L'\\');
folderName[len] = L'\0';
}
return 1;
}
void ReadINIFile() {
forceNpcGuided = GetPrivateProfileIntW(L"Main", L"ForceNPCGuided", 0, iniFileName);
forcePcGuided = GetPrivateProfileIntW(L"Main", L"ForcePCGuided", 0, iniFileName);
casterZAdjust = static_cast<double>(GetPrivateProfileIntW(L"Main", L"CasterZAdjust", 0, iniFileName));
npcSpringMult = 0.01 * GetPrivateProfileIntW(L"Main", L"NPCSpringMult", 100, iniFileName);
pcSpringMult = 0.01 * GetPrivateProfileIntW(L"Main", L"PCSpringMult", 50, iniFileName);
npcBonusRate = 0.0001 * GetPrivateProfileIntW(L"Main", L"NPCBonusRate", 1000, iniFileName);
pcBonusRate = 0.0001 * GetPrivateProfileIntW(L"Main", L"PCBonusRate", 100, iniFileName);
npcMagnetMult = static_cast<double>(GetPrivateProfileIntW(L"Main", L"NPCMagnetMult", 64, iniFileName));
pcMagnetMult = static_cast<double>(GetPrivateProfileIntW(L"Main", L"PCMagnetMult", 32, iniFileName));
pcDragMult = 0.01 * static_cast<double>(GetPrivateProfileIntW(L"Main", L"PCDragMult", 100, iniFileName));
macularArea = 0.001 * static_cast<double>(GetPrivateProfileIntW(L"Main", L"MacularArea", 10, iniFileName));
aimingPeriod = GetPrivateProfileIntW(L"Main", L"AimingPeriod", 768, iniFileName);
cellScanner = GetPrivateProfileIntW(L"Main", L"CellScanner", 0, iniFileName);
useLock = GetPrivateProfileIntW(L"Main", L"UseLock", 0, iniFileName);
}
DWORD WINAPI IniReaderThreadProc(LPVOID param) {
HANDLE handle = FindFirstChangeNotificationW(folderName, FALSE, 0x00000010);
do {
ReadINIFile();
WaitForSingleObject(handle, INFINITE);
} while (FindNextChangeNotification(handle));
FindCloseChangeNotification(handle);
return 0;
}
bool __attribute__((dllexport)) SKSEPlugin_Query(const SKSEInterface * skse, PluginInfo * info) {
info->infoVersion = PluginInfo::kInfoVersion;
info->name = "homproj";
info->version = 1;
pluginHandle = skse->GetPluginHandle();
CloseHandle(CreateThread(0, 0, IniReaderThreadProc, 0, 0, 0));
return true;
}
__attribute__((force_align_arg_pointer))
void GetEulerAngles(NiMatrix33 *mat, double *heading, double *attitude, double *bank) {
const double singularityNorthPole = 0.998;
const double singularitySouthPole = -0.998;
if (mat->data[1][0] > singularityNorthPole) { // singularity at north pole
*heading = _imp__atan2(mat->data[0][2], mat->data[2][2]);
*attitude = M_PI / 2;
*bank = 0;
} else if (mat->data[1][0] < singularitySouthPole) { // singularity at south pole
*heading = _imp__atan2(mat->data[0][2], mat->data[2][2]);
*attitude = -M_PI / 2;
*bank = 0;
} else {
*heading = _imp__atan2(-mat->data[2][0], mat->data[0][0]);
*bank = _imp__atan2(-mat->data[1][2];
}
}
__attribute__((force_align_arg_pointer))
void SetRotationMatrix(NiMatrix33 *mat, double attitude, double bank) {
double ca = cos(attitude);
double sa = sin(attitude);
double cb = cos(bank);
double sb = sin(bank);
mat->data[0][0] = ca;
mat->data[0][1] = -sa * cb;
mat->data[0][2] = sa * sb;
mat->data[1][0] = sa;
mat->data[1][1] = ca * cb;
mat->data[1][2] = -ca * sb;
mat->data[2][0] = 0.0;
mat->data[2][1] = sb;
mat->data[2][2] = cb;
}
__attribute__((force_align_arg_pointer))
void SetRotationMatrix2(NiMatrix33 *mat, double sacb, double cacb, double sb) {
double cb = _imp__sqrt(1 - sb * sb);
double ca = cacb / cb;
double sa = sacb / cb;
mat->data[0][0] = ca;
mat->data[0][1] = -sacb;
mat->data[0][2] = sa * sb;
mat->data[1][0] = sa;
mat->data[1][1] = cacb;
mat->data[1][2] = -ca * sb;
mat->data[2][0] = 0.0;
mat->data[2][1] = sb;
mat->data[2][2] = cb;
}
float __attribute__((noinline)) GetObjectHeight(TESObjectREFR *Object) {
float p[3];
void** vtbl = *(void***)Object;
asm("pushl %%edx;call *%%eax"::"a"(vtbl[0x74]), "c"(Object), "d"(p));
return p[2];
}
}
build.bat
"C:\Users\Admin\Downloads\mingw64\bin\g++.exe" -I ../skse64 -O3 -msse3 -mfpmath=sse -Wno-multichar -shared -o ..\..\Data\SKSE\Plugins\homproj.dll -m64 -Wl,--add-stdcall-alias,--subsystem,windows,--gc-sections,--relax,-s homproj.cpp homproj.s -static -lkernel32 -luser32 -lmsvcrt
fud.h
#include <cstdint>
#include <cstdio>
#include <Windows.h>
using UInt8 = uint8_t;
using UInt16 = uint16_t;
using UInt32 = uint32_t;
using UInt64 = uint64_t;
using SInt8 = int8_t;
using SInt16 = int16_t;
using SInt32 = int32_t;
constexpr int DEBUG_STRING_SIZE = 256;
#define ASSERT(...)
#define STATIC_ASSERT(...)
#define _MESSAGE(...)
#define __MACRO_JOIN__(a, b) __MACRO_JOIN_2__(a, b)
#define __MACRO_JOIN_2__(a, b) __MACRO_JOIN_3__(a, b)
#define __MACRO_JOIN_3__(a, b) a##b
constexpr HANDLE CurrentProcess = (HANDLE) - 1;
constexpr int WM_MOUSEMOVE2 = WM_USER + 1746;
constexpr int WM_KEYTOGGLE = WM_USER + 1747;
constexpr DWORD ENABLEANIMCAM = 0x9831718;
constexpr DWORD CHANGEZOFFSET = 0x9831717;
constexpr DWORD CHANGEZOOM = 0x9831716;
#define PlayerAddress (*(PlayerCharacter**)0x01B2E8E4)
#define PlayerCell (PlayerAddress ? ((volatile PlayerCharacter*)PlayerAddress)->parentCell : 0)
#define rtdsc(lo, hi) asm (".byte 0x0f,0x31" : "=a" (lo), "=d" (hi))
extern "C" NTSTATUS __declspec(dllimport) __stdcall NtWriteVirtualMemory(
HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG NumberOfBytesToWrite, PULONG NumberOfBytesWritten);
extern "C" double __declspec(dllimport) __cdecl sin(double x);
extern "C" double __declspec(dllimport) __cdecl cos(double x);
extern "C" int __cdecl swprintf(wchar_t *ws, size_t len, const wchar_t *format, ...);
#define dbgprint(format, ...) \
do { \
char s[DEBUG_STRING_SIZE]; \
_snprintf(s, DEBUG_STRING_SIZE, format, ##__VA_ARGS__); \
OutputDebugStringA(s); \
} while(0)
#define dbgprintw(format, ...) \
do { \
wchar_t s[DEBUG_STRING_SIZE]; \
_snwprintf(s, DEBUG_STRING_SIZE, format, ##__VA_ARGS__); \
OutputDebugStringW(s); \
} while(0)
class StringFinder_CI {
private:
std::string m_stringToFind;
public:
StringFinder_CI(const std::string &str) : m_stringToFind(str) {}
bool Accept(const std::string &str);
bool Accept(char *str);
};
bool StringFinder_CI::Accept(char *str) {
return !_stricmp(str, m_stringToFind.c_str());
}
template<typename T>
T InterlockedDecrement(volatile T *p) {
return InterlockedDecrement((volatile LONG *) p);
}
struct TLSData {
UInt32 pad000[(0x2F8 - 0x000) >> 2]; // 000
UInt8 consoleMode; // 2F8
UInt8 pad2F9[3]; // 2F9
};
static TLSData *GetTLSData() {
TLSData *result;
asm volatile("movq 0x01BBEB54,%%rcx\n"
"movq %%fs:0x2c,%%rdx\n"
"movq (%%rdx,%%rcx,4),%%rax":"=a"(result)::"%rcx", "%rdx");
return result;
}
homproj.s
.section .text
.globl _start
_start:
push %rax
push %rbx
push %rcx
push %rdx
push %rsi
push %rdi
/* Additional operations or code here */
pop %rdi
pop %rsi
/* Additional operations or code here */
_GoBack:
mov 0xA0(%rcx), %rdx
mov 4(%rsp), %rax /* Corrected from %esp to %rsp */
mov %rdx, (%rax)
mov 0xA4(%rcx), %rdx
mov %rdx, 4(%rax)
mov 0xA8(%rcx), %rcx
mov %rcx, 8(%rax)
retq/* Corrected ret syntax for 64-bit */
skse?
pre-update skyrim?
do i have to download CK to do it or it's already implemented?
does this affect all spells or only adept & above?