Добавить native-функцию из моей DLL в мои скрипты .uc.

gbcdev96

Путник
VIP
Сообщения
57
Розыгрыши
0
Репутация
0
Реакции
1
Баллы
31
Привет, у меня есть DLL, и я регистрирую native-функцию, где будет два параметра. Часть с регистрацией моей native-функции работает правильно.

Код:
#include "pch.h"
#include <string>
#include <sstream>

class UObject {};

struct FFrame
{
public:
    int* ftable;
    void* Node;
    UObject* Object;
    BYTE* Code;
    BYTE* Locals;
    INT LineNum;


    inline INT ReadInt() {
        INT Result;
        Result = *(INT*)Code;
        Code += sizeof(INT);
        Code++;
        return Result;
    }

    inline void SkipByte(){
       ++Code;
    }

    inline void SkipBytes(const INT Count){
        Code += Count;
    }

    inline BYTE ReadByte(){
        return *Code++;
    }
};

#define RESULT_DECL void*const Result
typedef void (*Native)(struct FFrame& TheStack, RESULT_DECL);
typedef BYTE(__cdecl* GRegisterNative_fnType)(INT iNative, const Native& Func);
GRegisterNative_fnType volatile GRegisterNative_fn = NULL;

void RequestAutoSoulShot(struct FFrame& Stack, RESULT_DECL)
{
    Stack.Code++;

    int param1 = Stack.ReadInt();
    int param2 = Stack.ReadByte();

    std::stringstream ss;
    ss << "param1: " << param1 << ", param2: " << param2;
    std::wstring message = std::wstring(ss.str().begin(), ss.str().end());
    MessageBox(nullptr, message.c_str(), L"hook", MB_OK);
}

// Точка входа DLL
extern "C" __declspec(dllexport)
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
    if (ul_reason_for_call != DLL_PROCESS_ATTACH) {
        return TRUE;     
    }

    auto hCore = GetModuleHandleA("Core.dll");
    if (!hCore) {
        MessageBoxW(NULL, L"FailedToGetHCore", L"hook", MB_OK);
        return true;
    }

    GRegisterNative_fn = (GRegisterNative_fnType)GetProcAddress(hCore, "?GRegisterNative@@YAEHABQ8UObject@@AEXAAUFFrame@@QAX@Z@Z");
    if (!GRegisterNative_fn) {
        MessageBox(nullptr, L"Nullable GRegisterNative_fn", L"hook", MB_OK);
        return true;
    }
    
    GRegisterNative_fn(4004, &RequestAutoSoulShot);

    return TRUE;
}

Но я не знаю, как использовать эту функцию, как вызвать её в моём файле UC, например, где я объявляю:

native(4004) final static function bool RequestAutoSoulShot( int shotid, bool _type );

Например, я попытался объявить её в NWindow/Classes/UIScript.UC и использовать в классе, который находится в Interface/Classes/AutoShotWnd.UC.

C++:
class AutoShotItemWnd extends UICommonAPI;

var WindowHandle zzMe;
var ItemWindowHandle zzinventory_item;
var ItemWindowHandle rhand;
var ItemInfo zziteminfoka;
var int _type;
var int _activateShotType;
var int _shotID;
var int zzkiaka2a;
var bool zzasnewk;
var ShortcutWnd zzshortcut;

function registerload()
{
    RegisterEvent(150);
    RegisterEvent(40);
    RegisterEvent(2610);
    RegisterEvent(693);
    RegisterEvent(44467);
    return;
}

function sendRequestToServer(optional int shotID, optional int _type)
{
    local string zParam;

    // End:0x21
    if( shotID > 10000 )
    {
        shotID = shotID - 10000;
    }

    RequestAutoSoulShot(shotID, True);

    //RequestBypassToServer((("RequestAutoShot: ShotID="$string(shotID))$" bEnable=")$string(_type));
    ParamAdd(zParam, "ShotID", string(shotID));
    ParamAdd(zParam, "bEnable", string(_type));
    
    if( _type == 1 )
    {
        ActivateAnimation(zParam);
    }

    return;
}

function OnLoad()
{    handleEquipRHandItem();
    registerload();
    inithandle();
    sendRequestToServer();
    return;
}

Но я не могу скомпилировать, у меня возникает ошибка при вызове функции:


AutoShotItemWnd.uc(35) : Error, 'RequestAutoSoulShot': Bad command or expression
Compile aborted due to errors.

Я попытался вызвать её напрямую в моём скрипте: AutoShotItemWnd.uc.

AutoShotItemWnd.uc

C++:
native(4004) final static function bool RequestAutoSoulShot( int shotid, bool _type );

function registerload()
{
    RegisterEvent(150);
    RegisterEvent(40);
    RegisterEvent(2610);
    RegisterEvent(693);
    RegisterEvent(44467);
    return;
}

function sendRequestToServer(optional int shotID, optional int _type)
{
    local string zParam;

    // End:0x21
    if( shotID > 10000 )
    {
        shotID = shotID - 10000;
    }

    RequestAutoSoulShot(shotID, True);

    //RequestBypassToServer((("RequestAutoShot: ShotID="$string(shotID))$" bEnable=")$string(_type));
    ParamAdd(zParam, "ShotID", string(shotID));
    ParamAdd(zParam, "bEnable", string(_type));
    
    if( _type == 1 )
    {
        ActivateAnimation(zParam);
    }

    return;
}

Но я получил ошибку. Моя функция действительно была вызвана, но с ошибкой, и она была вызвана ещё до входа в игру. Кто-нибудь может мне помочь? Где мне объявить мою native-функцию в UC и как её вызывать?

1736569757282.webp
 
Советую посмотреть например:

И похожие темы не только в ресурсах, самое главное указывать свободное число и правильно передавать параметры.
 
Советую посмотреть например:

И похожие темы не только в ресурсах, самое главное указывать свободное число и правильно передавать параметры.
Я попробовал с твоей DLL, и сработало :/ Я пытался сделать это с RequestAutoShot, но все равно продолжаю получать критические удары.

C++:
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class UObject {};

struct FFrame
{
public:
    int* ftable;
    void* Node;
    UObject* Object;
    BYTE* Code;
    BYTE* Locals;
    INT LineNum;


    inline INT ReadInt() {
        INT Result;
        Result = *(INT*)Code;
        Code += sizeof(INT);
        Code++;
        return Result;
    }

    inline void SkipByte() {
        ++Code;
    }

    inline void SkipBytes(const INT Count) {
        Code += Count;
    }

    inline BYTE ReadByte() {
        return *Code++;
    }
};

#define RESULT_DECL void*const Result
typedef void (*Native)(struct FFrame& TheStack, RESULT_DECL);
typedef BYTE(__cdecl* GRegisterNative_fnType)(INT iNative, const Native& Func);
GRegisterNative_fnType volatile GRegisterNative_fn = NULL;

void functionUC(struct FFrame& Stack, RESULT_DECL)
{
    Stack.Code++;
    MessageBox(nullptr, L"ENTER ON FUCNTION", L"hook", MB_OK);
}

void hookCore()
{
    auto hCore = GetModuleHandleA("Core.dll");

    if (hCore) {
        GRegisterNative_fnType GRegisterNative_fn = (GRegisterNative_fnType)GetProcAddress(hCore, "?GRegisterNative@@YAEHABQ8UObject@@AEXAAUFFrame@@QAX@Z@Z");
        if (GRegisterNative_fn) {
            GRegisterNative_fn(3003, &functionUC);
        }
    }
}

extern "C" __declspec(dllexport)
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hinstDLL);
        CreateThread(0, 0, LPTHREAD_START_ROUTINE(hookCore), 0, 0, 0);
    }

    if (fdwReason == DLL_PROCESS_DETACH) {}
    if (fdwReason == DLL_THREAD_ATTACH) {}
    if (fdwReason == DLL_THREAD_DETACH) {}

    return true;
}

UICommonAPI.uc

C++:
class UICommonAPI extends UIScript;

// Dialog API
enum EDialogType
{
    DIALOG_OKCancel,
    DIALOG_OK,
    DIALOG_OKCancelInput,
    DIALOG_OKInput,
    DIALOG_Warning,
    DIALOG_Notice,
    DIALOG_NumberPad,
    DIALOG_Progress,
};

enum DialogDefaultAction
{
    EDefaultNone,
    EDefaultOK,
    EDefaultCancel,
};

enum HeaderPosition
{
    Header_Head,
    Header_MidBody,
    Header_LowBody
};

struct PlayerStatusInfo
{
    var int CreatureID;
    var int CurHP;
    var int MaxHP;
    var int CurMP;
    var int MaxMP;
    var int Team;
};

struct infoautobuff
{
    var int Id;
    var string Name;
    var bool answermatha;
    var int quequierestuax2;
};

native(2025) final function string GetTitleExt();

native(3003) final function RequestAutoSoulShot(int s, int t);

function ChangeTitleExt(string TitleExt) {
    TitleExt = GetTitleExt();
}



И я вызываю это в своем AutoShotItemWnd.UC.


C++:
class AutoShotItemWnd extends UICommonAPI;

var WindowHandle zzMe;
var ItemWindowHandle zzinventory_item;
var ItemWindowHandle rhand;
var ItemInfo zziteminfoka;
var int _type;
var int _activateShotType;
var int _shotID;
var int zzkiaka2a;
var bool zzasnewk;
var ShortcutWnd zzshortcut;

function registerload()
{
    RegisterEvent(150);
    RegisterEvent(40);
    RegisterEvent(2610);
    RegisterEvent(693);
    RegisterEvent(44467);
    return;
}

function sendRequestToServer(optional int shotID, optional int _type)
{
    local string zParam;

    // End:0x21
    if( shotID > 10000 )
    {
        shotID = shotID - 10000;
    }

    RequestAutoSoulShot(3000, 1);

    //RequestBypassToServer((("RequestAutoShot: ShotID="$string(shotID))$" bEnable=")$string(_type));
    ParamAdd(zParam, "ShotID", string(shotID));
    ParamAdd(zParam, "bEnable", string(_type));
    
    if( _type == 1 )
    {
        ActivateAnimation(zParam);
    }

    return;
}

function OnLoad()
{    handleEquipRHandItem();
    registerload();
    inithandle();
    sendRequestToServer();
    return;
}


Я внедрил DLL в fire.dll, потом в ogg.dll, но безуспешно :/

1736607931521.webp

1736607938869.webp
 
Советую почитать тему еще:
 
Советую почитать тему еще:
Я использовал эту и другую тему в качестве ссылки, частично нашел проблему: я вызывал функцию в OnLoad(); после удаления все заработало:

C++:
function OnLoad()
{    handleEquipRHandItem();
    registerload();
    inithandle();
    //sendRequestToServer();
    return;
}

Теперь, заходя в игру после события 150, я могу извлечь значения, отправленные через .uc, но сразу после этого получаю критическую ошибку и не знаю причину:

1736611768825.webp

1736611785877.webp


code:

C++:
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class UObject {};

struct FFrame
{
public:
    int* ftable;
    void* Node;
    UObject* Object;
    BYTE* Code;
    BYTE* Locals;
    INT LineNum;


    inline INT ReadInt() {
        INT Result;
        Result = *(INT*)Code;
        Code += sizeof(INT) + 1;
        return Result;
    }

    inline void SkipByte() {
        ++Code;
    }

    inline void SkipBytes(const INT Count) {
        Code += Count;
    }

    inline BYTE ReadByte() {
        return *Code++;
    }
};

#define RESULT_DECL void*const Result
typedef void (*Native)(struct FFrame& TheStack, RESULT_DECL);
typedef BYTE(__cdecl* GRegisterNative_fnType)(INT iNative, const Native& Func);
GRegisterNative_fnType volatile GRegisterNative_fn = NULL;

void functionUC(struct FFrame& Stack, RESULT_DECL)
{
    Stack.Code++;
    int param1 = Stack.ReadInt();
    int param2 = Stack.ReadInt();

    // Formata a string com ambos os parâmetros
    char buffer[256];
    sprintf_s(buffer, sizeof(buffer), "Param1: %d, Param2: %d", param1, param2);

    MessageBoxA(NULL, buffer, "Valores dos Parâmetros", MB_OK);
}

void hookCore()
{
    auto hCore = GetModuleHandleA("Core.dll");

    if (hCore) {
        GRegisterNative_fnType GRegisterNative_fn = (GRegisterNative_fnType)GetProcAddress(hCore, "?GRegisterNative@@YAEHABQ8UObject@@AEXAAUFFrame@@QAX@Z@Z");
        if (GRegisterNative_fn) {
            GRegisterNative_fn(3003, &functionUC);
        }
    }
}

extern "C" __declspec(dllexport)
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hinstDLL);
        CreateThread(0, 0, LPTHREAD_START_ROUTINE(hookCore), 0, 0, 0);
    }

    if (fdwReason == DLL_PROCESS_DETACH) {}
    if (fdwReason == DLL_THREAD_ATTACH) {}
    if (fdwReason == DLL_THREAD_DETACH) {}

    return true;
}
 
Я использовал эту и другую тему в качестве ссылки, частично нашел проблему: я вызывал функцию в OnLoad(); после удаления все заработало:

C++:
function OnLoad()
{    handleEquipRHandItem();
    registerload();
    inithandle();
    //sendRequestToServer();
    return;
}

Теперь, заходя в игру после события 150, я могу извлечь значения, отправленные через .uc, но сразу после этого получаю критическую ошибку и не знаю причину:

Посмотреть вложение 83179

Посмотреть вложение 83180


code:

C++:
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class UObject {};

struct FFrame
{
public:
    int* ftable;
    void* Node;
    UObject* Object;
    BYTE* Code;
    BYTE* Locals;
    INT LineNum;


    inline INT ReadInt() {
        INT Result;
        Result = *(INT*)Code;
        Code += sizeof(INT) + 1;
        return Result;
    }

    inline void SkipByte() {
        ++Code;
    }

    inline void SkipBytes(const INT Count) {
        Code += Count;
    }

    inline BYTE ReadByte() {
        return *Code++;
    }
};

#define RESULT_DECL void*const Result
typedef void (*Native)(struct FFrame& TheStack, RESULT_DECL);
typedef BYTE(__cdecl* GRegisterNative_fnType)(INT iNative, const Native& Func);
GRegisterNative_fnType volatile GRegisterNative_fn = NULL;

void functionUC(struct FFrame& Stack, RESULT_DECL)
{
    Stack.Code++;
    int param1 = Stack.ReadInt();
    int param2 = Stack.ReadInt();

    // Formata a string com ambos os parâmetros
    char buffer[256];
    sprintf_s(buffer, sizeof(buffer), "Param1: %d, Param2: %d", param1, param2);

    MessageBoxA(NULL, buffer, "Valores dos Parâmetros", MB_OK);
}

void hookCore()
{
    auto hCore = GetModuleHandleA("Core.dll");

    if (hCore) {
        GRegisterNative_fnType GRegisterNative_fn = (GRegisterNative_fnType)GetProcAddress(hCore, "?GRegisterNative@@YAEHABQ8UObject@@AEXAAUFFrame@@QAX@Z@Z");
        if (GRegisterNative_fn) {
            GRegisterNative_fn(3003, &functionUC);
        }
    }
}

extern "C" __declspec(dllexport)
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hinstDLL);
        CreateThread(0, 0, LPTHREAD_START_ROUTINE(hookCore), 0, 0, 0);
    }

    if (fdwReason == DLL_PROCESS_DETACH) {}
    if (fdwReason == DLL_THREAD_ATTACH) {}
    if (fdwReason == DLL_THREAD_DETACH) {}

    return true;
}
Здесь например наглядный рабочий пример и не крашит.

 
Здесь например наглядный рабочий пример и не крашит.

1736614965386.webp


Мой код не отличается, думаю, причина в другом. Я вызываю: RequestAutoSoulShot(3952, 1);, но если я считываю 2 целых числа, игра выдает критическую ошибку. Значение param2 кажется странным:

То есть, я могу правильно считать первый аргумент, но со вторым возникает проблема, он не принимает мое значение 1.
 
Когда я отправляю 1, следующий байт после чтения ssID — 38, а когда отправляю 0 — 37. Я предполагаю, что 37 — это false, а 38 — true. Но самое странное, что я указал это как int в коде .uc. Есть ли в этом логика? (Это в IL)

RequestAutoSoulShot(3952, 0):

1736618865825.webp

1736618872109.webp


RequestAutoSoulShot(3952, 1):
 

Вложения

  • 1736618959047.webp
    1736618959047.webp
    16,8 КБ · Просмотры: 9
Я очень запутался. Когда я подставляю значения вместо переменных, утверждение выше обретает смысл:

uc:

C++:
RequestAutoSoulShot(3952, 1);

В результате у меня получились следующие байты:

Код:
0x1d 0x70 0x0f 0x00 0x00 0x26 0x16 0x1b 0x7d 0x2c 0x00 0x00 0x00 0x80 0xe3 0x85 0x13 0x1f 0x53 0x68 0x6f 0x74 0x49 0x44 0x00 0x39 0x53 0x00 0x00 0xe7 0x85 0x13 0x16 0x1b 0x7d 0x2c 0x00 0x00 0x00 0x80 0xe3 0x85 0x13 0x1f 0x62 0x45 0x6e 0x61 0x62 0x6c 0x65 0x00 0x39 0x53 0x00 0x80 0x5c 0x7e 0x13 0x16 0x07 0xcb 0x00 0x9a 0x00 0x80 0x5c 0x7e 0x13 0x26 0x16 0x1b 0xad 0xd9 0x00 0x00 0x00 0x80 0xe3 0x85 0x13 0x16 0x04 0x0b 0x04 0x0b 0x00

Где 0x1D это 29, что означает, что следующие 4 байта содержат целое число: 0x00 0x00 0x0F 0x7
который в формате little endian и равен 3952 (id, который я передал)

и следующий байт: 0x26 это 38, который, как я предполагаю, является 1, который я отправил, когда я отправляю 0, он равен 37.


Код:
    RequestAutoSoulShot(shotID, _type);


Но когда я передаю переменные, байты полностью меняются, и моё число 3952 исчезает. Кто-нибудь знает причину? Как мне его получить?

Это байты, полученные при передаче переменных в качестве аргументов функции микроконтроллера:

Код:
0x00 0x80 0x54 0x4a 0x12 0x00 0x80 0x4a 0x49 0x12 0x16 0x1b 0x7d 0x2c 0x00 0x00 0x00 0x80 0xe3 0x51 0x12 0x1f 0x53 0x68 0x6f 0x74 0x49 0x44 0x00 0x39 0x53 0x00 0x80 0x54 0x4a 0x12 0x16 0x1b 0x7d 0x2c 0x00 0x00 0x00 0x80 0xe3 0x51 0x12 0x1f 0x62 0x45 0x6e 0x61 0x62 0x6c 0x65 0x00 0x39 0x53 0x00 0x80 0x4a 0x49 0x12 0x16 0x07 0xcf 0x00 0x9a 0x00 0x80 0x4a 0x49 0x12 0x26 0x16 0x1b 0xad 0xd9 0x00
 
Мое мнение что проще тогда передавать как string, на стороне dll уже из string переводить в int значение.
Это самый простой вариант если нужно передавать числа.
 
Мое мнение что проще тогда передавать как string, на стороне dll уже из string переводить в int значение.
Это самый простой вариант если нужно передавать числа.
У меня есть слабое ощущение, что даже с использованием строки проблема останется той же. Я думаю, проблема заключается в передаче переменной. Похоже, что UC не отправляет значение, а передает ссылку на память, когда передается переменная.
Но я попробую с string.
 
Последнее редактирование:
Назад
Сверху Снизу