Spinn
Новичок
Структура файлов:
- main.cpp: Точка входа и основная логика.
- inventory.h / inventory.cpp: Классы и функции, связанные с инвентарем.
- renderer.h / renderer.cpp: Классы и функции для отрисовки интерфейса.
- config.h / config.cpp: Загрузка и хранение настроек из конфигурационного файла.
- utils.h / utils.cpp: Вспомогательные функции.
C++:
#pragma once
#include <string>
struct Config {
int toggleKey;
std::string fontName;
int fontSize;
bool LoadConfig(const std::string& filename);
};
extern Config gConfig;
C++:
#include "config.h"
#include <fstream>
#include <sstream>
Config gConfig;
bool Config::LoadConfig(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open())
return false;
std::string line;
while (std::getline(file, line)) {
std::istringstream is_line(line);
std::string key;
if (std::getline(is_line, key, '=')) {
std::string value;
if (std::getline(is_line, value)) {
if (key == "ToggleKey")
toggleKey = std::stoi(value);
else if (key == "FontName")
fontName = value;
else if (key == "FontSize")
fontSize = std::stoi(value);
}
}
}
return true;
}
C++:
#pragma once
#include <vector>
#include <string>
struct InventoryItem {
std::string name;
int quantity;
};
class Inventory {
public:
void AddItem(const std::string& name, int quantity);
void RemoveItem(const std::string& name, int quantity);
const std::vector<InventoryItem>& GetItems() const;
private:
std::vector<InventoryItem> items;
};
extern Inventory gInventory;
C++:
#include "inventory.h"
Inventory gInventory;
void Inventory::AddItem(const std::string& name, int quantity) {
for (auto& item : items) {
if (item.name == name) {
item.quantity += quantity;
return;
}
}
items.push_back({ name, quantity });
}
void Inventory::RemoveItem(const std::string& name, int quantity) {
for (auto it = items.begin(); it != items.end(); ++it) {
if (it->name == name) {
it->quantity -= quantity;
if (it->quantity <= 0)
items.erase(it);
return;
}
}
}
const std::vector<InventoryItem>& Inventory::GetItems() const {
return items;
}
C++:
#pragma once
#include <d3d9.h>
#include <d3dx9.h>
class Renderer {
public:
Renderer();
~Renderer();
bool Initialize(LPDIRECT3DDEVICE9 device);
void RenderInventory(const std::vector<InventoryItem>& items);
private:
LPDIRECT3DDEVICE9 pDevice;
ID3DXFont* pFont;
ID3DXSprite* pSprite;
LPDIRECT3DTEXTURE9 pBackgroundTexture;
};
C++:
#include "renderer.h"
#include "config.h"
#include <string>
Renderer::Renderer() : pDevice(nullptr), pFont(nullptr), pSprite(nullptr), pBackgroundTexture(nullptr) {}
Renderer::~Renderer() {
if (pFont)
pFont->Release();
if (pSprite)
pSprite->Release();
if (pBackgroundTexture)
pBackgroundTexture->Release();
}
bool Renderer::Initialize(LPDIRECT3DDEVICE9 device) {
pDevice = device;
HRESULT hr = D3DXCreateFontA(pDevice, gConfig.fontSize, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
gConfig.fontName.c_str(), &pFont);
if (FAILED(hr))
return false;
hr = D3DXCreateSprite(pDevice, &pSprite);
if (FAILED(hr))
return false;
hr = D3DXCreateTextureFromFileA(pDevice, "inventory_bg.png", &pBackgroundTexture);
if (FAILED(hr))
return false;
return true;
}
void Renderer::RenderInventory(const std::vector<InventoryItem>& items) {
if (!pDevice || !pFont || !pSprite || !pBackgroundTexture)
return;
// Отрисовка фона
D3DXVECTOR3 pos(50.0f, 50.0f, 0.0f);
pSprite->Begin(D3DXSPRITE_ALPHABLEND);
pSprite->Draw(pBackgroundTexture, NULL, NULL, &pos, D3DCOLOR_ARGB(200, 255, 255, 255));
pSprite->End();
// Отрисовка текста
RECT rect;
SetRect(&rect, 60, 60, 400, 600);
pFont->DrawTextA(NULL, "Inventory:", -1, &rect, DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 255, 255));
int offsetY = 80;
for (const auto& item : items) {
RECT itemRect;
SetRect(&itemRect, 60, offsetY, 400, offsetY + 20);
std::string itemText = item.name + " x" + std::to_string(item.quantity);
pFont->DrawTextA(NULL, itemText.c_str(), -1, &itemRect, DT_NOCLIP, D3DCOLOR_ARGB(255, 200, 200, 200));
offsetY += 20;
}
}
C++:
#pragma once
#include <windows.h>
bool DetourFunction(BYTE* src, const BYTE* dst, const int len);
Код:
#include "utils.h"
#include <memory.h>
bool DetourFunction(BYTE* src, const BYTE* dst, const int len) {
if (len < 5)
return false;
DWORD curProtection;
if (!VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection))
return false;
memset(src, 0x90, len);
uintptr_t relativeAddress = ((uintptr_t)dst - (uintptr_t)src) - 5;
src[0] = 0xE9;
*(uintptr_t*)(src + 1) = relativeAddress;
DWORD temp;
VirtualProtect(src, len, curProtection, &temp);
return true;
}
C++:
#include <windows.h>
#include <d3d9.h>
#include "renderer.h"
#include "inventory.h"
#include "config.h"
#include "utils.h"
typedef HRESULT(WINAPI* EndScene_t)(LPDIRECT3DDEVICE9 pDevice);
EndScene_t oEndScene = nullptr;
Renderer* gRenderer = nullptr;
LPDIRECT3DDEVICE9 pDevice = nullptr;
bool showInventory = false;
HRESULT WINAPI hkEndScene(LPDIRECT3DDEVICE9 pDevice) {
if (GetAsyncKeyState(gConfig.toggleKey) & 1) {
showInventory = !showInventory;
}
if (showInventory) {
if (!gRenderer) {
gRenderer = new Renderer();
if (!gRenderer->Initialize(pDevice)) {
delete gRenderer;
gRenderer = nullptr;
}
}
if (gRenderer) {
gRenderer->RenderInventory(gInventory.GetItems());
}
} else if (gRenderer) {
delete gRenderer;
gRenderer = nullptr;
}
return oEndScene(pDevice);
}
DWORD WINAPI MainThread(LPVOID lpReserved) {
if (!gConfig.LoadConfig("plugin_config.ini")) {
MessageBoxA(NULL, "Failed to load config file.", "Error", MB_ICONERROR);
return 1;
}
while (!pDevice) {
pDevice = **(LPDIRECT3DDEVICE9**)(0xC97C28);
Sleep(100);
}
DWORD* vTable = *(DWORD**)(pDevice);
if (!DetourFunction((BYTE*)vTable[42], (BYTE*)hkEndScene, 5)) {
MessageBoxA(NULL, "Failed to hook EndScene.", "Error", MB_ICONERROR);
return 1;
}
oEndScene = (EndScene_t)vTable[42];
gInventory.AddItem("Health Potion", 5);
gInventory.AddItem("Armor Vest", 1);
gInventory.AddItem("Ammo Pack", 100);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
CreateThread(NULL, 0, MainThread, NULL, 0, NULL);
} else if (ul_reason_for_call == DLL_PROCESS_DETACH) {
if (gRenderer) {
delete gRenderer;
gRenderer = nullptr;
}
}
return TRUE;
}
ToggleKey=0x09 FontName=Arial FontSize=16 - ToggleKey: Клавиша для отображения/скрытия инвентаря (0x09 = VK_TAB).
- FontName: Название шрифта.
- FontSize: Размер шрифта.
