S0meTh1n69
Участник
- 19
- 8
Тим, напиши пожалуйста как можно заменить эти 11 строк твоими 211 строк вместо 2х
Тим, напиши пожалуйста как можно заменить эти 11 строк твоими 211 строк вместо 2х
дело ведь не в количестве строк 🥲11 строк вместо 2х
Я тоже не про количество, мне просто интересно как заменить это.дело ведь не в количестве строк 🥲
Тим, напиши пожалуйста как можно заменить эти 11 строк твоими 2
void add_chat_message(DWORD dwColor, LPCSTR szString, ...)
{
va_list ap;
char msg[/* SAMP_MAX_CHAT_MESSAGE*/ 144] = { 0 };
va_start(ap, szString);
vsprintf_s(msg, szString, ap);
va_end(ap);
DWORD base = reinterpret_cast<DWORD>(GetModuleHandleW(L"samp.dll"));
typedef void(__thiscall* CChat__AddEntry)(void*, int, char*, char*, DWORD, DWORD);
reinterpret_cast<CChat__AddEntry>(base + /* SAMP_PTR_FUNC_ADDTOCHATWND */ 0x64010)(*reinterpret_cast<void**>(base + /* SAMP_PTR_CHAT_INFO */ 0x21A0E4), 8, msg, 0, dwColor, 0);
}
почему 2? можно и 1 😀11 строк вместо 2х
#include <Windows.h>
#include "main.h"
SAMPFUNCS *SF = new SAMPFUNCS();
void __stdcall mainloop()
{
static bool initialized = false;
static bool activated = false;
if (!initialized)
{
if (GAME && GAME->GetSystemState() == eSystemState::GS_PLAYING_GAME && SF->getSAMP()->IsInitialized())
{
initialized = true;
SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xAA, 0), "SAMPFUNCS Plugin loaded.");
}
}
if (SF->getGame()->isKeyPressed('H'))
{
activated = true;
}
while (activated)
{
SF->getSAMP()->getPlayers()->pLocalPlayer->Say("/edit");
Sleep(2500);
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)
{
if (dwReasonForCall == DLL_PROCESS_ATTACH)
SF->initPlugin(mainloop, hModule);
return TRUE;
}
нельзя делать Sleep в mainloop, ты останавливаешь всю игру, а не только свой плагин. так же нельзя делать while в mainloop, да и нет смысла, так как mainloop вызывается постоянно. используй if и GetTickCount (функция которая берет текущее количество пройденых милисекунд с запуска системы, 1000 милисекунд = 1 секунда), вот так:игра просто виснет
#include "main.h"
SAMPFUNCS *SF = new SAMPFUNCS();
void __stdcall mainloop()
{
static bool initialized = false;
static bool activated = false;
static DWORD dwTime = 0;
if (!initialized)
{
if (GAME && GAME->GetSystemState() == eSystemState::GS_PLAYING_GAME && SF->getSAMP()->IsInitialized())
{
initialized = true;
SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xAA, 0), "SAMPFUNCS Plugin loaded.");
}
}
else
{
if (SF->getGame()->isKeyPressed('H'))
{
// активирует и деактивирует на ту же кнопку
activated = !activated;
}
if (activated && GetTickCount() - dwTime >= /* время ожидания */ 2500)
{
SF->getSAMP()->getPlayers()->pLocalPlayer->Say("/edit");
dwTime = GetTickCount();
}
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)
{
if (dwReasonForCall == DLL_PROCESS_ATTACH)
SF->initPlugin(mainloop, hModule);
return TRUE;
}
Игра уже не виснет, но команда отправляется только тогда когда я жму H а не циклически как хотелосьнельзя делать Sleep в mainloop, ты останавливаешь всю игру, а не только свой плагин. так же нельзя делать while в mainloop, да и нет смысла, так как mainloop вызывается постоянно. используй if и GetTickCount (функция которая берет текущее количество пройденых милисекунд с запуска системы, 1000 милисекунд = 1 секунда), вот так:
C++:#include "main.h" SAMPFUNCS *SF = new SAMPFUNCS(); void __stdcall mainloop() { static bool initialized = false; static bool activated = false; static DWORD dwTime = 0; if (!initialized) { if (GAME && GAME->GetSystemState() == eSystemState::GS_PLAYING_GAME && SF->getSAMP()->IsInitialized()) { initialized = true; SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xAA, 0), "SAMPFUNCS Plugin loaded."); } } else { if (SF->getGame()->isKeyPressed('H')) { // активирует и деактивирует на ту же кнопку activated = !activated; } if (activated && GetTickCount() - dwTime > /* время ожидания */2500) { SF->getSAMP()->getPlayers()->pLocalPlayer->Say("/edit"); dwTime = GetTickCount(); } } } BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved) { if (dwReasonForCall == DLL_PROCESS_ATTACH) SF->initPlugin(mainloop, hModule); return TRUE; }
команда отправляется каждые 2.5 секунды, можешь проверить это добавлением логгированием в месте отправления командыИгра уже не виснет, но команда отправляется только тогда когда я жму H а не циклически как хотелось
У SF плагинов есть специальный коллбек, который выполняется перед выгрузкойрешил добавить фикс краша по адрессу 0x0072CD14 в сф плагин. заметил, что при отгрузке плагина через pfree или просто выходе из игры, то функция хука пропадает быстрее, чем сам хук снимается и игра крашится. когда я делал тоже самое в проекте с аси плагином, то всё было окей. как можно это исправить?
хук я ставлю в DLL_PROCESS_ATTACH, а снимаю в DLL_PROCESS_DETACH.
не нахожу, можешь ткнуть пальцем пожалуйстаспециальный коллбек
регистрируешь в mainloop коллбек на приходящие rpc, читаешь данные, взаимодействуешь:Как мне в сф сделать onServerMessage как в луа?
// регистрируем коллбек в mainloop
SF->getRakNet()->registerRakNetCallback(RAKHOOK_TYPE_INCOMING_RPC, incomingRPC);
bool CALLBACK incomingRPC(stRakNetHookParams* params)
{
// проверяем что пришло рпц сообщения в чат по id
if (params->packetId == RPC_ScrClientMessage)
{
DWORD color; // цвет
DWORD length; // длинна сообщения
char message[256]; // сообщение
// читаем данные
params->bitStream->ResetReadPointer();
params->bitStream->Read(color);
params->bitStream->Read(length);
params->bitStream->Read(message, length);
message[length] = '\0'; // ставим в конце массава NULL чтобы превратить наш массив символов в стринг
// взаимодействуем
}
return true; // возвращаем true чтобы рпц принимались
}
не нахожу, можешь ткнуть пальцем пожалуйста
void __stdcall dest() {
}
SF->getGame()->registerGameDestructorCallback(dest);//init
результатом вычисления фрагмента не является функция, принимающая 4 аргументов
class user32
{
char* base_address;
template <typename function>
void call(function func, int a,const char* b, const char* c, long d)
{
func(a, b, c, d)();
}
public:
user32()
{
base_address = (char*)GetModuleHandleA("user32.dll");
}
void MessageBoxA(int a, const char* b, const char* c, long d)
{
call((base_address + 0x77B30),a,b,c,d);
}
};
Пытаюсь реализовать класс с функцией, способной вызывать другие функции по адресам, но компилятор ругается:
Вот, что я пытался ему впарить:Код:результатом вычисления фрагмента не является функция, принимающая 4 аргументов
C++:class user32 { char* base_address; template <typename function> void call(function func, int a,const char* b, const char* c, long d) { func(a, b, c, d)(); } public: user32() { base_address = (char*)GetModuleHandleA("user32.dll"); } void MessageBoxA(int a, const char* b, const char* c, long d) { call((base_address + 0x77B30),a,b,c,d); } };
Копаясь в интернете, я понял, что можно как-то сделать, чтобы функция объявлялась как обычная статическая и перекидывала аргументы через fastcall, stdcall и т.д., типа ты её объявил в переменной, но аргументы перекинул как в статическую и всё на ок сработало, но в тех громоздких конструкциях я так и не нашёл минималистичного примера, который смог бы понять. Всё как-то слишком уж перегружено
Отчаянно нуждаюсь в помощи в понимании этого механизма
то, что я уже написал, это попытка сделать прямой вызов MessageBoxA, не используя исходники, но зная оффсет в библиотеке (для чего и нужна эта функция в принципе)
#include <Windows.h>
class user32
{
using TypeMessageBoxA = int(__stdcall *)(HWND, LPCSTR, LPCSTR, UINT);
TypeMessageBoxA messageBoxA;
template <typename F, typename... Args>
void call(F f, Args... args)
{
f(args...);
}
public:
user32()
{
auto user32Module = LoadLibraryA("user32.dll");
messageBoxA = reinterpret_cast<TypeMessageBoxA>(
GetProcAddress(user32Module, "MessageBoxA"));
}
void MessageBoxA(HWND a, LPCSTR b, LPCSTR c, UINT d)
{
call(messageBoxA, a, b, c, d);
}
};
int main()
{
user32 obj;
obj.MessageBoxA(NULL,
"Resource not available\nDo you want to try again?",
"Account details",
MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2);
return 0;
}
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS 1
#include "main.h"
#include "imgui/imgui.h"
#include "imgui/imgui_impl_dx9.h"
#include "imgui/imgui_impl_win32.h"
#include <d3d9.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include <tchar.h>
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
SAMPFUNCS* SF = new SAMPFUNCS();
void CALLBACK PluginFree()
{
ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
bool CALLBACK WndProcHandler(HWND hwd, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGui_ImplWin32_WndProcHandler(hwd, msg, wParam, lParam);
return true;
}
HRESULT CALLBACK Reset(D3DPRESENT_PARAMETERS* pPresentationParameters)
{
ImGui_ImplDX9_InvalidateDeviceObjects();
return true;
}
bool CALLBACK Present(CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion)
{
if (SUCCEEDED(SF->getRender()->BeginRender()))
{
static bool menu = true, checkbox;
ImGui_ImplDX9_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
ImGui::SetNextWindowSize(ImVec2(228, 228));
ImGui::Begin("123", &menu, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
{
ImGui::Checkbox("111", &checkbox);
}
ImGui::End();
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
SF->getRender()->EndRender();
}
return true;
}
void CALLBACK mainloop()
{
static bool init = false;
if (!init)
{
if (GAME == nullptr)
return;
if (GAME->GetSystemState() != eSystemState::GS_PLAYING_GAME)
return;
if (!SF->getSAMP()->IsInitialized())
return;
ImGui::CreateContext();
ImGui_ImplWin32_Init(GetActiveWindow());
ImGui_ImplDX9_Init(SF->getRender()->getD3DDevice());
SF->getRender()->registerD3DCallback(eDirect3DDeviceMethods::D3DMETHOD_PRESENT, Present);
SF->getRender()->registerD3DCallback(eDirect3DDeviceMethods::D3DMETHOD_RESET, Reset);
SF->getGame()->registerWndProcCallback(SFGame::MEDIUM_CB_PRIORITY, WndProcHandler);
SF->getGame()->registerGameDestructorCallback(PluginFree);
init = true;
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)
{
if (dwReasonForCall == DLL_PROCESS_ATTACH)
SF->initPlugin(mainloop, hModule);
return TRUE;
}