Другое С/С++ Вопрос - Ответ

CleanLegend

Известный
Всефорумный модератор
477
935
Как вывести локально сообщение в asi?
BlastHackNet/mod_s0beit_sa(https://github.com/BlastHackNet/mod_s0beit_sa/blob/master/src/samp.cpp#L675)
why this not working i wanted to check when i'm driving to put gravity back to normal

if (cheat_state->state == CHEAT_STATE_ACTOR)
{
gta_gravity_set(10.0000);
}
else if (cheat_state->state == CHEAT_STATE_VEHICLE)
{
gta_gravity_set(0.0080);
}
cheat_state->state maybe can't change, check it
Здравствуйте.
Заметил, что из за перехвата оконной процедуры(wndproc) через SetWindowLongPtr, при выгрузке плагина через консоль сф командой "pfree SFPlugin" происходит краш. В коллбэке деструктора игры и DLL PROCESS DETACH'e пытался восстанавливать оригинальный WndProc, но краш все равно был.
Может быть, кто нибудь знает, из за чего такое происходит?
C++:
#define  _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
#include <windows.h>
#include <string>
#include <assert.h>
#include <process.h>
#include "SAMPFUNCS_API.h"
#include "game_api\game_api.h"
#pragma comment(lib, "user32.lib")
SAMPFUNCS *SF = new SAMPFUNCS();

WNDPROC oWndProc = 0;

LRESULT    __stdcall WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    SF->getSAMP()->getChat()->AddChatMessage(-1, "WNDPROC CALLED");
    return CallWindowProcA(oWndProc, hWnd, uMsg, wParam, lParam);
}
void __stdcall Destructor() {
    static bool once = false;
    if (!once) {
        SetWindowLongPtr(GetForegroundWindow(), GWLP_WNDPROC, (long)oWndProc);
        once = true;
    }
}
void CALLBACK mainloop()
{
    static bool init = false;
    if (!init)
    {
        if (GAME == nullptr || GAME->GetSystemState() != eSystemState::GS_PLAYING_GAME || !SF->getSAMP()->IsInitialized())
            return;
        oWndProc = (WNDPROC)SetWindowLongPtr(GetForegroundWindow(), GWLP_WNDPROC, (long)WndProc);
        SF->getGame()->registerGameDestructorCallback(Destructor);
        init = true;
    }
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)
{
    if (dwReasonForCall == DLL_PROCESS_ATTACH)
        SF->initPlugin(mainloop, hModule);
    else if (dwReasonForCall == DLL_PROCESS_DETACH)
        Destructor();
    return TRUE;
}
в sf wndproc уже перехвачен, достаточно зарегать каллбек.
тут пример - Гайд - API SF | Урок 5 - Подключение ImGui(https://blast.hk/threads/23083/)
 

_Vine_

Активный
154
57
BlastHackNet/mod_s0beit_sa(https://github.com/BlastHackNet/mod_s0beit_sa/blob/master/src/samp.cpp#L675)

cheat_state->state maybe can't change, check it

в sf wndproc уже перехвачен, достаточно зарегать каллбек.
тут пример - Гайд - API SF | Урок 5 - Подключение ImGui(https://blast.hk/threads/23083/)
А можно ли как то сделать это без сф?
 

#Rin

Известный
Всефорумный модератор
1,214
1,043
нет, твой хук потом еще 40 раз какие-нибудь собейты, сфы перезапишут в итоге очередь не вернуть
Может можно выделить память (Чтобы при выгрузке функция осталось в процессе), записать туда функцию WndProc которая вызывает следующий WndProc, что бы не сломать очередь?
 

Roger571

Известный
58
31
как изменить текст уже отрендеренного текста?
Смотря какого текста.
Если игрового, то через память.
А через д3д хук - сам решаешь, шо рендерить.

я уже отрендерил текст через д3д, как мне изменить текст на другой?
Ты можешь изменять данные каждый раз при вызове proxyIDirect3DDevice9::Present
Можешь посмотреть, как это реализовано в собейте.
 

_Vine_

Активный
154
57
Может можно выделить память (Чтобы при выгрузке функция осталось в процессе), записать туда функцию WndProc которая вызывает следующий WndProc, что бы не сломать очередь?
Тоже об этом думал, но столкнулся с рядом проблем.
1) Не совсем уверен, правильно ли создаю функцию в динамической памяти, может быть есть более правильный способ?
C++:
void func(){
// code
}

int main(){
    LPVOID memory = VirtualAlloc(0, /* Размер функции в байтах */, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    DWORD oldProtect;
    VirtualProtect(func, /* Размер функции*/, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy(memory, func, /*  Размер функции */);
    VirtualProtect(func, /* Размер функции */, oldProtect, 0);
     // memory  - указатель на копию функции func в динамической памяти
}
2) С выделением функции и ее вызовом проблем нет, до выгрузки плагина из игры.
После выгрузки плагина из игры при первом вызове WNDPROC происходит краш.
То есть, если выгрузить плагин, и ничего не делать(не двигать курсор, не нажимать клавиши на клавиатуре), то краша, пока, не будет, до тех пор пока что то не начать делать.
Указатель на оригинальный WNDPROC выделяю динамически, сообщение в чат вовсе убрал.
Смотрел в отладчике, после выгрузки плагина указатель на указатель на оригинальный WNDPROC становится недоступным, тк он находится в самом плагине, который был выгружен. Ну, и, собственно, из за этого и происходит краш. Как исправить не знаю, может кто подскажет?
 

SR_team

like pancake
BH Team
4,804
6,475
Lua:
local talb = {
hhh = "huy",
dd = "pd"
}
Как сделать такой-же массив в c++?
C++:
struct talb_t{
    std::string hhh = "huy";
    std::string dd = "pd";
};
Это просто структура, что бы к ней обращаться нужно еще и переменную создать
C++:
talb_t talb;
Далее можно юзать
Код:
SF->Log(talb.hhh);
talb.dd = "new dd";
 

-raymond-

Известный
110
9
не могу понять что значат параметр bs.Write(true);, и bs.Write(3);
C++:
BitStream bs;
    bs.Write(true);
    bs.Write(TargetID);
    bs.Write((float)damage);
    bs.Write(weapon_id);
    bs.Write(3);
    SF->getRakNet()->SendRPC(RPCEnumeration::RPC_GiveTakeDamage, &bs);