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

Cake_

Известный
Проверенный
263
313
Как получить коорды объекта / модели? Попытался сам написать, что-то не то вообщем
C++:
float pos[3];

    for (int i = 0; i < SAMP_MAX_OBJECTS; i++)
    {
        if (SF->getSAMP()->getInfo()->pPools->pObject->iIsListed[i] != 1)
            continue;
        if (SF->getSAMP()->getInfo()->pPools->pObject->object[i] == NULL)
            continue;
        if (SF->getSAMP()->getInfo()->pPools->pObject->object[i]->pGTAEntity == NULL)
            continue;

        pos[0] = SF->getSAMP()->getInfo()->pPools->pObject->object[i]->fPos[0];
        pos[1] = SF->getSAMP()->getInfo()->pPools->pObject->object[i]->fPos[1];
        pos[2] = SF->getSAMP()->getInfo()->pPools->pObject->object[i]->fPos[2];
 

SiTrak

Известный
193
251
Как получить коорды объекта / модели? Попытался сам написать, что-то не то вообщем
C++:
float pos[3];

    for (int i = 0; i < SAMP_MAX_OBJECTS; i++)
    {
        if (SF->getSAMP()->getInfo()->pPools->pObject->iIsListed[i] != 1)
            continue;
        if (SF->getSAMP()->getInfo()->pPools->pObject->object[i] == NULL)
            continue;
        if (SF->getSAMP()->getInfo()->pPools->pObject->object[i]->pGTAEntity == NULL)
            continue;

        pos[0] = SF->getSAMP()->getInfo()->pPools->pObject->object[i]->fPos[0];
        pos[1] = SF->getSAMP()->getInfo()->pPools->pObject->object[i]->fPos[1];
        pos[2] = SF->getSAMP()->getInfo()->pPools->pObject->object[i]->fPos[2];
C++:
                        if (pObj->iModel == objes[4])
                        {
                            memcpy(pos, &SF->getSAMP()->getInfo()->pPools->pObject->object[i]->pGTAEntity->base.matrix[12], sizeof(float)* 3);
                            //    uint16_t    model_id = SF->getSAMP()->getInfo()->pPools->pObject->object[i]->pGTAEntity->base.model_alt_id;


                            SF->getGame()->convert3DCoordsToScreen(position[0], position[1], position[2], &obmypos[0], &obmypos[1]);

                            SF->getGame()->convert3DCoordsToScreen(pos[0], pos[1], pos[2], &obsreen[0], &obsreen[1]);
                            if (IsOnScreen(i))
                            {
                                SF->getRender()->DrawLine(obmypos[0], obmypos[1], obsreen[0], obsreen[1], sizelin[4], 0xFF00FF00);
                            }
                        }
 
  • Нравится
Реакции: Cake_

index

Известный
126
82
Небольшая абстрактная задачка: имеется объект Cell, полем которого является указатель на объект (pMan) одного из возможных других классов с разным поведением и полями (virtual не предлагать :) ). Когда указатель на Cell передадут в какую-либо функцию (в приведенном примере все происходит в main) эта функция должна будет вызывать конкретный метод объекта класса, на который указывает pMan, но в зависимости от того, на какой класс там вообще идет указание.
Код (не цепляйтесь к тому, что все паблик, суть вопроса в самой концепции):
C++:
#include <iostream>
using namespace std;

class Man1 {
public:
    void do1() {
        cout << "Man1" << endl;
    }
};

class Man2 {
public:
    void do2() {
        cout << "Man2" << endl;
    }
};

class Cell {
public:
    enum class Type {
        man1, man2
    }; // Всевозможные типы

    Type type;
    void *pMan; // Указатель на Man1 или Man2, в зависимости от того, что находится в type

    Cell(Type x, void *px) : type(x), pMan(px) {}
};

int main(void)
{
    Cell *cell = new Cell(Cell::Type::man2, new Man2);

    if(cell->type == Cell::Type::man1)       // false
        static_cast<Man1*>(cell->pMan)->do1();
    else if (cell->type == Cell::Type::man2) // true
        static_cast<Man2*>(cell->pMan)->do2(); // выведет Man2
    return 0;
}

И сам вопрос: как реализовать подобную вещь более адекватно и канонично? В приведенном примере конструктор Cell может схавать
C++:
Cell(Cell::Type::man1, new Man2);
и в дальнейшем получить неопределенное поведение. Хотелось бы видеть подобные ошибки на этапе компиляции.
 
Последнее редактирование:
463
825
Как из данной строки получить "97.1445.1541.67" ?
Код:
{"as":"AS21127 JSC \"Zap-Sib TransTeleCom\", FFFFFFF","city":"FFFFFFF","country":"SSSSSS","countryCode":"RU","isp":"JSC \"Zap-Sib TransTeleCom\"","lat":12.1234,"lon":23.34,"org":"JSC Zap-Sib TransTeleCom","query":"97.1445.1541.67","region":"WER","regionName":"QWERTY","status":"success","timezone":"Asia/ESFFF","zip":"653008"}
 

imring

Ride the Lightning
Всефорумный модератор
2,355
2,516
Как из данной строки получить "97.1445.1541.67" ?
Код:
{"as":"AS21127 JSC \"Zap-Sib TransTeleCom\", FFFFFFF","city":"FFFFFFF","country":"SSSSSS","countryCode":"RU","isp":"JSC \"Zap-Sib TransTeleCom\"","lat":12.1234,"lon":23.34,"org":"JSC Zap-Sib TransTeleCom","query":"97.1445.1541.67","region":"WER","regionName":"QWERTY","status":"success","timezone":"Asia/ESFFF","zip":"653008"}
https://github.com/nlohmann/json
 

san0

Известный
Друг
411
267
Небольшая абстрактная задачка
Мне кажется, немножко детали упущены по поводу того, как это все должно использоваться. Это к тому, что, возможно, задачу можно будет свести к использованию обвертки с помощью std::bind или лямбда-выражения, либо же, всегда применить другую парадигму.

В любом случае, хотелось бы посоветовать либо использовать типобезопасный variant
C++:
#include <variant>
using Cell = std::variant<Man1*, Man2*>;

void usage_one(Cell cell) {
    if (auto man1 = std::get_if<Man1*>(&cell)) {
        (*man1)->do1();
    } else if (auto man2 = std::get_if<Man2*>(&cell)) {
        (*man2)->do2();
    }
}
Либо, если очень хочется написать обвертку, то что-то такое
C++:
#include <type_traits>

namespace std {
    template <class T, class... R>
    struct is_any : std::disjunction<std::is_same<T, R>...> {};
}

template <typename C>
class CellWrapper {
public:
    C* pMan;
 
    CellWrapper(C* ptr) : pMan(ptr) {
         // static_assert(std::is_class<C>::value);
         static_assert(std::is_any<C, Man1, Man2>::value,
             "CellWrapper could be created only with Man1 and Man2"
         );
    };
 
    C* operator->() {
        return this->pMan;
    }
};

template<typename C>
void usage_two(CellWrapper<C>* cell) {
    if constexpr (std::is_same<C, Man1>()) {
        (*cell)->do1();
    } else if constexpr (std::is_same<C, Man2>()) {
        (*cell)->do2();
    }
}

Использование
C++:
int main(void) {
    {
        auto cell = Cell(new Man1);
        usage_one(cell);
    }
    {
        auto cell = CellWrapper(new Man2);
        usage_two(&cell); // как и просилось, именно указатель
    }
}
Поправьте, если это не то, что требовалось.
P.S. В примерах выше по причине использования new была продемонстрирована утечка памяти
 
Последнее редактирование:
  • Нравится
Реакции: index

index

Известный
126
82
Мне кажется, немножко детали упущены по поводу того, как это все должно использоваться.
Есть массив (обертка не подойдет) объектов Cell. Из этого массива произвольным образом выбирается элемент, и, в зависимости от типа ассоциированного с ним объекта другого класса, выполняются определенные действия. По сути, полиморфизм времени выполнения. На псевдокоде это выглядит так:
Код:
// Cell type1 fileds: index, name, doSmth11(), doSmth12()
// Cell type2 fileds: cost, group, doSmth21(), doSmth22()

Cell cellArr[N];
fill(cellArr);
a = cellArr[random(0,N-1)];
if (a.type == type1)
{
  a.doSmth11();
  a.doSmth12();
}
else if (a.type == type2)
{
  a.doSmth21();
  a.doSmth22();
}
Пример больше подходит для языков с динамической типизацией, но хотелось бы увидеть реализацию подобного на c++.
P.S. Хотелось бы посоветовать не использовать new в современных проектах: начиная с C++20 new является deprecated. Даже в примерах выше по причине использования new была продемонстрирована утечка памяти
upd: На cppReference ничего об этом не сказано. Также безрезультатно гуглил в других сточниках. Можно поинтересоваться, откуда информация?
 
Последнее редактирование:

san0

Известный
Друг
411
267
Хотелось бы увидеть реализацию подобного на c++
Последний из способов, наверное, наиболее благоприятный по причине низкой посадки по рантайму
C++:
#include <iostream>
#include <vector>
#include <any>
#include <typeindex>
#include <typeinfo>

struct Man1 {
    unsigned long long index = 0LL;
    std::string name = "Name";
    void doSmth11() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->index << std::endl;
    }
   
    void doSmth12() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->name << std::endl; 
    }
};


struct Man2 {
    unsigned long long cost = 2222LL;
    std::string group = "Group";
    void doSmth21() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->cost << std::endl;
    }
   
    void doSmth22() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->group << std::endl; 
    }
};

int main() {
    std::vector<std::any> pool;
   
    pool.push_back(Man1{});
    pool.push_back(Man2{});
   
    for (auto&& e : pool) {
        if (std::type_index(e.type()) == std::type_index(typeid(Man1))) {
            auto restoredMan1 = std::any_cast<Man1>(e);
            restoredMan1.doSmth11();
            restoredMan1.doSmth12();
        } else if (e.type().hash_code() == typeid(Man2).hash_code()) {
            auto restoredMan2 = std::any_cast<Man2>(e);
            restoredMan2.doSmth21();
            restoredMan2.doSmth22();
        }
    }
}
C++:
#include <iostream>
#include <vector>

struct ManEssential { 
    virtual void __unused(void) {};
};

struct Man1 : ManEssential {
    unsigned long long index = 0LL;
    std::string name = "Name";
    void doSmth11() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->index << std::endl;
    }
   
    void doSmth12() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->name << std::endl; 
    }
};


struct Man2 : ManEssential {
    unsigned long long cost = 2222LL;
    std::string group = "Group";
    void doSmth21() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->cost << std::endl;
    }
   
    void doSmth22() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->group << std::endl; 
    }
};

int main() {
    std::vector<ManEssential*> pool;
   
    pool.push_back(new Man2);
    pool.push_back(new Man1);
   
    for (auto&& e : pool) {
        if (auto restoredMan1 = dynamic_cast<Man1*>(e)) {
            restoredMan1->doSmth11();
            restoredMan1->doSmth12();
        } else if (auto restoredMan2 = dynamic_cast<Man2*>(e)) {
            restoredMan2->doSmth21();
            restoredMan2->doSmth22();
        }
    }
}
C++:
#include <iostream>
#include <vector>

struct Man1 {
    unsigned long long index = 0LL;
    std::string name = "Name";
    void doSmth11() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->index << std::endl;
    }
   
    void doSmth12() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->name << std::endl; 
    }
};


struct Man2 {
    unsigned long long cost = 2222LL;
    std::string group = "Group";
    void doSmth21() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->cost << std::endl;
    }
   
    void doSmth22() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << 
            this->group << std::endl; 
    }
};

enum class ManSubtype {
    kMan1,
    kMan2
};

struct ObjectSlicing : public Man1, public Man2 {
    const ManSubtype type;

    template<typename T> 
    ObjectSlicing(const T&& man) : type([=] {
        if constexpr (std::is_same<T, Man1>()) {
            return ManSubtype::kMan1;
        } else if constexpr (std::is_same<T, Man2>()) {
            return ManSubtype::kMan2;
        }
    }()) 
    {}
};

int main() {
    std::vector<class ObjectSlicing> pool;
   
    pool.push_back(ObjectSlicing(Man1{}));
    pool.push_back(ObjectSlicing(Man2{}));
   
    for (auto&& e : pool) {
        if (e.type == ManSubtype::kMan1) {
            Man1 restoredMan1 = e;
            restoredMan1.doSmth11();
            restoredMan1.doSmth12();
        } else if (e.type == ManSubtype::kMan2) {
            Man2 restoredMan2 = e;
            restoredMan2.doSmth21();
            restoredMan2.doSmth22();
        }
       
    }
}
Можно поинтересоваться, откуда информация?
Первоапрельская шутка 2018 года, не воспринимайте всерьез
http://modernescpp.com/index.php/no-new-new
Каким образом можно поменять расположение киллстата по вертикали?
samp.dll + 0x66655 =>
patch 5 bytes to mov eax,00000010, where 0x10 - Y offset
samp.dll + 0x66668 =>
patch 5 bytes to mov eax,00000020, where 0x20 - X offset
 
  • Нравится
Реакции: Yuan и index

Cake_

Известный
Проверенный
263
313
Дайте функцию бега на сф, пожалуйста не кидайте соб
 

ALF

Известный
Проверенный
320
537
Либо я дико туплю, либо это отступы между строчками и отступы самих ников, а не расположение киллиста. Покопавшись, понял, что положение киллстата зависит от игрового разрешения. Тот плагин, который я кидал, как-то подменяет это самое разрешение, но при этом остальные части (худ, чат и т.д). никак не изменяет. При выгрузке плагина, киллстат встаёт на своё место. Интересная задумка, но не могу придумать, как можно заблокировать изменение остальных элементов, чтобы двигать только киллстат. Но спасибо за помощь.
не, ты какую то хрень написал.

DWORD addrX = samp.dll + 0x6665C;
DWORD addrY = samp.dll + 0x66645;
 
  • Нравится
Реакции: Yuan

checkdasound

Известный
Проверенный
963
406
Пытаюсь переделать свой скрипт в аси формат. Все сделал, кроме нормальной эмуляции игровых клавиш. Нынешняя эмуляция работает через раз.
C++:
#include "main.h"

void __cdecl thread(void *pArg)
{
   while (true)
   {
       Sleep(1);
       if (isKeyDown(0x31))
       {
           if (IsCharOnFoot())
           {
               SetGameKeyState(0x20, 255);
               Sleep(10);
               SetGameKeyState(0x20, 0);
               GTAfunc_showStyledText("ON FOOT", 2000, 1);
           }
       }
       if (isKeyDown(0xA0))
       {
           if (IsCharInAnyCar())
           {
               type = CurrentVehicleModelType();
               if (type == 1)
               {
                   SetGameKeyState(0x20, 255);
                   Sleep(10);
                   SetGameKeyState(0x20, 0);
                   GTAfunc_showStyledText("ON BIKE", 2000, 1);
               }
               else if (type == 2) {
                   SetGameKeyState(0x2, -128);
                   Sleep(10);
                   SetGameKeyState(0x2, 0);
                   GTAfunc_showStyledText("ON MOTO", 2000, 1);
               }
           }
       }
   }
}

BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
   if (fdwReason == DLL_PROCESS_ATTACH)
   {
       _beginthread(thread, 0, nullptr);
           return TRUE;
   }

}

C++:
#include <windows.h>
#include <process.h>
#include <TlHelp32.h>

DWORD CPed = 0xB6F5F0;
DWORD CPedStatus = 0x530;
DWORD ProcID;
DWORD p1;
HANDLE hProcess;

unsigned int CurrentVehiclePointer = 0xBA18FC;
int Model = 0;
int Status = 0;
int type;
unsigned long temp;

int bike[3] = { 481, 509, 510 };
int moto[11] = { 448, 461, 462, 463, 468, 471, 521, 522, 523, 581, 586 };

using namespace std;

DWORD GetProcId(const char* procname)
{
   PROCESSENTRY32 pe;
   HANDLE hSnap;

   pe.dwSize = sizeof(PROCESSENTRY32);
   hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
   if (Process32First(hSnap, &pe)) {
       do {
           if (strcmp(pe.szExeFile, procname) == 0)
               break;
       } while (Process32Next(hSnap, &pe));
   }
   return pe.th32ProcessID;
}

void SetGameKeyState(BYTE key, BYTE state)
{
   p1 = 0xB73458 + key;
   memset((void*)p1, state, 1);
};

bool isKeyDown(int key)
{
   SHORT keyState = GetKeyState(key);
   return (keyState & 0x8000);
}

void GTAfunc_showStyledText(const char *text, int time, int style)
{
   ((void(__cdecl *) (const char *text, int time, int style)) (0x0069F2B0)) (text, time, style);
}

int CurrentPedStatus()
{
   ProcID = GetProcId("gta_sa.exe");
   hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcID);

   ReadProcessMemory(hProcess, reinterpret_cast<LPVOID>(CPed), &temp, sizeof(temp), 0);
   CPedStatus = temp + 0x530;

   ReadProcessMemory(hProcess, reinterpret_cast<LPVOID>(CPedStatus), &Status, sizeof(temp), 0);
   return Status;
}

bool IsCharInAnyCar()
{
   Status = CurrentPedStatus();
   if (Status == 50)
   {
       return true;
   }
   else
   {
       return false;
   }
}

bool IsCharOnFoot()
{
   Status = CurrentPedStatus();
   if (Status == 1)
   {
       return true;
   }
   else
   {
       return false;
   }
}

int CurrentVehicleModelType()
{
   unsigned int CurrentVehiclePointer = *(unsigned int*)0xBA18FC;
   unsigned short model = *(unsigned short*)(CurrentVehiclePointer + 34);
   if (IsCharInAnyCar())
   {
       for (int counter = 0; counter < 3; counter++)
       {
           if (model == bike[counter])
           {
               return 1;
           }
       }
       for (int counter = 0; counter < 11; counter++)
       {
           if (model == moto[counter])
           {
               return 2;
           }
       }
   } else {
       return 0;
   }
}

static struct _Keys
{
   bool        bPressed;
   DWORD       dwStartTime;
}kPressingKeys[256];

BOOL  State_Key(int Key, DWORD dwTimeOut)
{
   if (HIWORD(GetKeyState(Key)))
   {
       if (!kPressingKeys[Key].bPressed || (kPressingKeys[Key].dwStartTime && (kPressingKeys[Key].dwStartTime + dwTimeOut) <= GetTickCount()))
       {
           kPressingKeys[Key].bPressed = TRUE;
           if (dwTimeOut > NULL)
               kPressingKeys[Key].dwStartTime = GetTickCount();
           return TRUE;
       }
   }
   else
       kPressingKeys[Key].bPressed = FALSE;
   return FALSE;
}
 

CleanLegend

Известный
Всефорумный модератор
476
929
Пытаюсь переделать свой скрипт в аси формат. Все сделал, кроме нормальной эмуляции игровых клавиш. Нынешняя эмуляция работает через раз.
C++:
#include "main.h"

void __cdecl thread(void *pArg)
{
   while (true)
   {
       Sleep(1);
       if (isKeyDown(0x31))
       {
           if (IsCharOnFoot())
           {
               SetGameKeyState(0x20, 255);
               Sleep(10);
               SetGameKeyState(0x20, 0);
               GTAfunc_showStyledText("ON FOOT", 2000, 1);
           }
       }
       if (isKeyDown(0xA0))
       {
           if (IsCharInAnyCar())
           {
               type = CurrentVehicleModelType();
               if (type == 1)
               {
                   SetGameKeyState(0x20, 255);
                   Sleep(10);
                   SetGameKeyState(0x20, 0);
                   GTAfunc_showStyledText("ON BIKE", 2000, 1);
               }
               else if (type == 2) {
                   SetGameKeyState(0x2, -128);
                   Sleep(10);
                   SetGameKeyState(0x2, 0);
                   GTAfunc_showStyledText("ON MOTO", 2000, 1);
               }
           }
       }
   }
}

BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
   if (fdwReason == DLL_PROCESS_ATTACH)
   {
       _beginthread(thread, 0, nullptr);
           return TRUE;
   }

}

C++:
#include <windows.h>
#include <process.h>
#include <TlHelp32.h>

DWORD CPed = 0xB6F5F0;
DWORD CPedStatus = 0x530;
DWORD ProcID;
DWORD p1;
HANDLE hProcess;

unsigned int CurrentVehiclePointer = 0xBA18FC;
int Model = 0;
int Status = 0;
int type;
unsigned long temp;

int bike[3] = { 481, 509, 510 };
int moto[11] = { 448, 461, 462, 463, 468, 471, 521, 522, 523, 581, 586 };

using namespace std;

DWORD GetProcId(const char* procname)
{
   PROCESSENTRY32 pe;
   HANDLE hSnap;

   pe.dwSize = sizeof(PROCESSENTRY32);
   hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
   if (Process32First(hSnap, &pe)) {
       do {
           if (strcmp(pe.szExeFile, procname) == 0)
               break;
       } while (Process32Next(hSnap, &pe));
   }
   return pe.th32ProcessID;
}

void SetGameKeyState(BYTE key, BYTE state)
{
   p1 = 0xB73458 + key;
   memset((void*)p1, state, 1);
};

bool isKeyDown(int key)
{
   SHORT keyState = GetKeyState(key);
   return (keyState & 0x8000);
}

void GTAfunc_showStyledText(const char *text, int time, int style)
{
   ((void(__cdecl *) (const char *text, int time, int style)) (0x0069F2B0)) (text, time, style);
}

int CurrentPedStatus()
{
   ProcID = GetProcId("gta_sa.exe");
   hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcID);

   ReadProcessMemory(hProcess, reinterpret_cast<LPVOID>(CPed), &temp, sizeof(temp), 0);
   CPedStatus = temp + 0x530;

   ReadProcessMemory(hProcess, reinterpret_cast<LPVOID>(CPedStatus), &Status, sizeof(temp), 0);
   return Status;
}

bool IsCharInAnyCar()
{
   Status = CurrentPedStatus();
   if (Status == 50)
   {
       return true;
   }
   else
   {
       return false;
   }
}

bool IsCharOnFoot()
{
   Status = CurrentPedStatus();
   if (Status == 1)
   {
       return true;
   }
   else
   {
       return false;
   }
}

int CurrentVehicleModelType()
{
   unsigned int CurrentVehiclePointer = *(unsigned int*)0xBA18FC;
   unsigned short model = *(unsigned short*)(CurrentVehiclePointer + 34);
   if (IsCharInAnyCar())
   {
       for (int counter = 0; counter < 3; counter++)
       {
           if (model == bike[counter])
           {
               return 1;
           }
       }
       for (int counter = 0; counter < 11; counter++)
       {
           if (model == moto[counter])
           {
               return 2;
           }
       }
   } else {
       return 0;
   }
}

static struct _Keys
{
   bool        bPressed;
   DWORD       dwStartTime;
}kPressingKeys[256];

BOOL  State_Key(int Key, DWORD dwTimeOut)
{
   if (HIWORD(GetKeyState(Key)))
   {
       if (!kPressingKeys[Key].bPressed || (kPressingKeys[Key].dwStartTime && (kPressingKeys[Key].dwStartTime + dwTimeOut) <= GetTickCount()))
       {
           kPressingKeys[Key].bPressed = TRUE;
           if (dwTimeOut > NULL)
               kPressingKeys[Key].dwStartTime = GetTickCount();
           return TRUE;
       }
   }
   else
       kPressingKeys[Key].bPressed = FALSE;
   return FALSE;
}
Для нормальной эмуляции клавиш нужно хукать функцию, которая отвечает за нажатие игровых клавиш. https://git.prime-hack.net/SR_team/AsiBase/src/branch/master/sys/SREvents.cpp#L432
Как вариант можешь вызывать функции SF или WinAPI. и не используй RPM и WPM в dll