File information

Last updated

Original upload

Created by

Pyromancer

Uploaded by

rhonjhonson

Virus scan

Safe to use

Tags for this mod

9 comments

  1. Doesn't work for Skyrim SE Anniversary edition 1.6.1.x
  2. modmeca
    modmeca
    • member
    • 15 kudos
    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.
  3. hart02
    hart02
    • premium
    • 0 kudos
    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"

    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 */

  4. Sky7025
    Sky7025
    • premium
    • 0 kudos
    Is it compatible with Skyrim VR ( compiled with CommonLibSSE NG)?
    1. hart02
      hart02
      • premium
      • 0 kudos
      It needs recompiling to 64bit so no.
  5. Qarbone
    Qarbone
    • premium
    • 3 kudos
    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.
  6. YuiMada
    YuiMada
    • member
    • 0 kudos
    so what are the requirements?
    skse?
    pre-update skyrim?
    1. rhonjhonson
      rhonjhonson
      • premium
      • 328 kudos
      yes, only skse
    2. YuiMada
      YuiMada
      • member
      • 0 kudos
      so how to use this?
      do i have to download CK to do it or it's already implemented?
      does this affect all spells or only adept & above?