Working on right click gem extraction

This commit is contained in:
Hash Borgir
2024-04-28 12:09:32 -06:00
parent d7fab9d077
commit 74f1d9de01
59 changed files with 418 additions and 187 deletions

View File

@@ -4,7 +4,6 @@
#include <spdlog/spdlog.h>
#include <d2tweaks/common/common.h>
#include <d2tweaks/common/protocol.h>
#include <d2tweaks/common/asset_manager.h>
@@ -20,7 +19,6 @@
#include <diablo2/d2gfx.h>
#include <diablo2/d2cmp.h>
#include <diablo2/structures/unit.h>
#include <diablo2/structures/inventory.h>
#include <diablo2/structures/item_data.h>
@@ -45,10 +43,19 @@
#include <string>
#include <map>
#include <DllNotify.h>
#include <D2Template.h>
#include <diablo2/d2gfx.h>
#include <string>
#include <vector>
#include <sstream>
#include <string>
#include <locale>
#include <codecvt>
MODULE_INIT(autosort)
enum ColorEnum {
@@ -88,7 +95,6 @@ std::map<int, diablo2::ui_font_t> fontMap = {
{13, diablo2::ui_font_t::UI_FONT_INGAMECHAT}
};
class inventory_sort_menu : public d2_tweaks::ui::menu {
d2_tweaks::common::asset* m_buttons_img;
@@ -115,8 +121,6 @@ public:
m_sort_cube_btn = get_button("m_sort_cube_btn", std::bind(&inventory_sort_menu::sort_cube_click, this));
}
// Function to find the Diablo II window handle
HWND FindDiabloIIWindow() {
return FindWindow(NULL, "Diablo II");
@@ -132,11 +136,81 @@ public:
ReleaseDC(hwnd, hdc);
}
int statsFont = GetPrivateProfileIntA("Options", "statsFont", 0, "./d2tweaks.ini");
ULONGLONG lastSendTime = GetTickCount64();
// Function to split a string into words
std::vector<std::string> split(const std::string& s, char delim) {
std::stringstream ss(s);
std::string item;
std::vector<std::string> tokens;
while (getline(ss, item, delim)) {
tokens.push_back(item);
}
return tokens;
}
std::wstring stringToWstring(const std::string& str) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.from_bytes(str);
}
// Function to justify a line of text
void justifyLine(const std::vector<std::string>& words, int start, int end, int maxLineLength, int& xPos, int yPos, int padding) {
int lineLength = 0;
for (int i = start; i <= end; i++) {
lineLength += words[i].length() * 8; // Assuming each character has a width of 8 pixels
}
int numSpaces = end - start;
int extraSpaces = maxLineLength - lineLength - padding * 2;
int spaceWidth = 8;
int extraSpacePerGap = numSpaces > 0 ? extraSpaces / numSpaces : 0;
int remainingSpaces = numSpaces > 0 ? extraSpaces % numSpaces : 0;
for (int i = start; i <= end; i++) {
diablo2::d2_win::draw_boxed_text(const_cast<wchar_t*>(stringToWstring(words[i]).c_str()), xPos + padding, yPos, 0, 0, diablo2::UI_COLOR_WHITE); // Assuming paletteIndex, transTbl, and color are 0
xPos += words[i].length() * 8 + spaceWidth + extraSpacePerGap + padding;
if (remainingSpaces > 0) {
xPos += 1; // Add an extra pixel for the remaining spaces
remainingSpaces--;
}
}
}
// Function to draw justified text inside a box with padding
void drawJustifiedTextInBox(const std::string& text, int boxX, int boxY, int boxWidth, int boxHeight, int padding) {
std::vector<std::string> words = split(text, ' ');
int maxLineLength = boxWidth;
int xPos = boxX + padding;
int yPos = boxY + padding;
for (size_t i = 0; i < words.size(); ) {
int start = i;
int end = i;
int lineLength = 0;
// Find the end index for the current line
while (end < words.size() && lineLength + words[end].length() <= maxLineLength) {
lineLength += words[end].length();
if (end > start) {
lineLength++; // Add space width
}
end++;
}
justifyLine(words, start, end - 1, maxLineLength, xPos, yPos, padding);
yPos += 16; // Assuming each line is 16 pixels tall
xPos = boxX + padding;
i = end;
}
}
void draw() override {
@@ -157,16 +231,12 @@ public:
// Initialize statValue
int32_t statValue = 0;
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH)) {
diablo2::d2_gfx::draw_filled_rect(130, 48, 640, 155, 5, 50);
}
if (m_stats_enabled) {
for (const auto& stat : stats) {
double param = 6;
int32_t spirits = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(185), NULL);
@@ -175,7 +245,7 @@ public:
switch (stat.stat) {
// 2. (statValue <- this is probably op stat1 ? * baseValue <- this is probably op base ) / 2 ^ param
// (op stat1 value * base stat value) / (2 ^ param)
// (op stat1 value * base stat value) / (2 ^ param)
// let's try this fucking thing
case 190: {
@@ -229,7 +299,6 @@ public:
// By default, get player stats
statValue = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(stat.stat), NULL);
break;
}
}
@@ -273,7 +342,6 @@ public:
diablo2::d2_common::set_stat(player, static_cast<diablo2::unit_stats_t>(randStat), 0, 0);
diablo2::d2_common::set_stat(player, static_cast<diablo2::unit_stats_t>(randStatBool), 0, 0);
}
}
*/
auto statValueStr = std::to_wstring(statValue);
@@ -301,175 +369,185 @@ public:
&& !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_HELP)
&& !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_MERC)
&& !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_SCROLL)) {
// Draw stats
diablo2::d2_win::set_current_font(fontMap[statsFont]); // Set font to FONT16
diablo2::d2_win::draw_text(const_cast<wchar_t*>(statText.c_str()), stat.x1, stat.y1 + textOffset, stat.colorStat, 0);
diablo2::d2_win::set_current_font(fontMap[statsFont]); // Set font to FONT16
diablo2::d2_win::draw_text(const_cast<wchar_t*>(statValueStr.c_str()), stat.x2, stat.y2 + textOffset, stat.colorStatValue, 0);
//diablo2::d2_win::draw_boxed_text(const_cast<wchar_t*>(statText.c_str()), stat.x1, stat.y1 + textOffset, 1, 0, stat.colorStat);
//diablo2::d2_win::draw_boxed_text(const_cast<wchar_t*>(statValueStr.c_str()), stat.x2, stat.y2 + textOffset, 1, 4, stat.colorStatValue);
// diablo2::d2_win::set_current_font(diablo2::UI_FONT_16); // Set font to FONT16
//diablo2::structures::d2_cmp::init_gfx_data(&g_gfxdata);
//diablo2::d2_gfx::draw_image(&g_gfxdata, 200, 200, 1, 5, 0);
// instead try to load direct jpg with gdi and insetad ofloading jpg file, specify it bb64 encoded and decode it.
diablo2::ui_color_t::UI_COLOR_WHITE;
// print player health, mana, and stamina bars, lastexp, nextexp, and level
// Get current HP, Mana, and Stamina along with their maximum values
int statHP = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(6), NULL) / 256;
int statMaxHP = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(7), NULL) / 256;
int statMana = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(8), NULL) / 256;
int statMaxMana = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(9), NULL) / 256;
int statStamina = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(10), NULL) / 256;
int statMaxStamina = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(11), NULL) / 256;
// Convert the integer values to wide character strings
std::wstring strHP = std::to_wstring(statHP);
std::wstring strMaxHP = std::to_wstring(statMaxHP);
std::wstring strMana = std::to_wstring(statMana);
std::wstring strMaxMana = std::to_wstring(statMaxMana);
std::wstring strStamina = std::to_wstring(statStamina);
std::wstring strMaxStamina = std::to_wstring(statMaxStamina);
diablo2::d2_win::set_current_font(diablo2::UI_FONT_16); // Set font to FONT16
// Calculate the percentages of current HP, Mana, and Stamina
float healthPercentage = static_cast<float>(statHP) / static_cast<float>(statMaxHP);
float manaPercentage = static_cast<float>(statMana) / static_cast<float>(statMaxMana);
float staminaPercentage = static_cast<float>(statStamina) / static_cast<float>(statMaxStamina);
int sHeight = 768;
int sWidth = 1280;
int sHCenter = sHeight / 2;
int sWCenter = sWidth / 2;
//spdlog::info("healthPercentage: {}", healthPercentage);
// Define default bar color
DWORD barColor = 0;
// Determine bar color based on health percentage
if (healthPercentage > .80) {
barColor = 118;
}
else if (healthPercentage > .50) {
barColor = 13;
}
else {
barColor = 5;
}
//spdlog::info("barColor: {}", barColor);
// Define the dimensions for the bars
int barWidth = 200; // Width of the bars
int barHeight = 16; // Height of the bars
// Define the coordinates for the bars
int barX = sWCenter - 100; // Left coordinate of the bars
int barY_HP = 654; // Top coordinate of the HP bar
int barY_Mana = barY_HP + barHeight + 4; // Top coordinate of the Mana bar with separator
int barY_Stamina = barY_Mana + barHeight + 4; // Top coordinate of the Stamina bar with separator
std::wstring life = L"L: " + strHP + L" / " + strMaxHP;
std::wstring mana = L"M: " + strMana + L" / " + strMaxMana;
std::wstring stamina = L"" + strStamina + L" / " + strMaxStamina;
int lifeWidth = diablo2::d2_win::get_text_pixel_width(const_cast<wchar_t*>(life.c_str()));
int manaWidth = diablo2::d2_win::get_text_pixel_width(const_cast<wchar_t*>(mana.c_str()));
int staminaWidth = diablo2::d2_win::get_text_pixel_width(const_cast<wchar_t*>(stamina.c_str()));
// Calculate the filled widths of the bars
int filledHPWidth = static_cast<int>(healthPercentage * barWidth);
int filledManaWidth = static_cast<int>(manaPercentage * barWidth);
int filledStaminaWidth = static_cast<int>(staminaPercentage * barWidth);
// at 345 we need to minus the width of the text
sWCenter = barX + 100 - (diablo2::d2_win::get_text_pixel_width(const_cast<wchar_t*>(mana.c_str())) / 2);
HWND diabloIIWnd = FindDiabloIIWindow();
// Draw the filled HP bar
diablo2::d2_gfx::draw_filled_rect(barX, barY_HP, barX + filledHPWidth, barY_HP + barHeight, barColor, 255);
//DrawFilledRect(diabloIIWnd, barX, barY_HP, barX + filledHPWidth, barY_HP + barHeight, RGB(255, 0, 0)); // Red color for HP
diablo2::d2_win::draw_text(const_cast<wchar_t*>(life.c_str()), sWCenter, barY_HP + 15, stat.colorStatValue, 0);
// Draw the filled Mana bar
diablo2::d2_gfx::draw_filled_rect(barX, barY_Mana, barX + filledManaWidth, barY_Mana + barHeight, 140, 255);
//DrawFilledRect(diabloIIWnd, barX, barY_Mana, barX + filledManaWidth, barY_Mana + barHeight, RGB(100, 100, 255)); // Blue color for Mana
diablo2::d2_win::draw_text(const_cast<wchar_t*>(mana.c_str()), sWCenter, barY_Mana + 15, stat.colorStatValue, 0);
/*
// Define the number of separators
int numColors = 256;
int numColumns = 4;
int colorsPerColumn = numColors / numColumns;
int separatorHeight = 1; // Height of each separator
int columnOffset = 200; // Offset for each column
// Iterate over each column
for (int column = 0; column < numColumns; ++column) {
// Calculate the starting X coordinate for this column
int columnX = barX + (column * columnOffset);
// Draw the filled Mana bars for this column
for (int i = 0; i < colorsPerColumn; ++i) {
int colorIndex = column * colorsPerColumn + i;
int separatorY = barY_Mana + barHeight + i * (separatorHeight + barHeight);
// Draw the filled Mana bar
diablo2::d2_gfx::draw_filled_rect(columnX, separatorY, columnX + filledManaWidth, separatorY + barHeight, colorIndex, 255);
// Draw the index number at the same coordinates as the bar
std::wstring indexStr = std::to_wstring(colorIndex);
diablo2::d2_win::draw_text(const_cast<wchar_t*>(indexStr.c_str()), columnX - 20, separatorY, diablo2::UI_COLOR_DARK_GOLD, 0);
}
}
*/
// Draw the filled Stamina bar
// diablo2::d2_gfx::draw_filled_rect(barX, barY_Stamina, barX + filledStaminaWidth, barY_Stamina + barHeight, 12, 255);
//DrawFilledRect(diabloIIWnd, barX, barY_Stamina, barX + filledStaminaWidth, barY_Stamina + barHeight, RGB(255, 255, 0)); // Green color for Stamina
int statLevel = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(12), NULL);
int statLastExp = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(29), NULL);
int statNextExp = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(30), NULL);
diablo2::d2_win::set_current_font(diablo2::UI_FONT_16); // Set font to FONT16
}
//diablo2::d2_win::draw_boxed_text(const_cast<wchar_t*>(statText.c_str()), stat.x1, stat.y1 + textOffset, 1, 0, stat.colorStat);
//diablo2::d2_win::draw_boxed_text(const_cast<wchar_t*>(statValueStr.c_str()), stat.x2, stat.y2 + textOffset, 1, 4, stat.colorStatValue);
// diablo2::d2_win::set_current_font(diablo2::UI_FONT_16); // Set font to FONT16
//diablo2::structures::d2_cmp::init_gfx_data(&g_gfxdata);
//diablo2::d2_gfx::draw_image(&g_gfxdata, 200, 200, 1, 5, 0);
// instead try to load direct jpg with gdi and insetad ofloading jpg file, specify it bb64 encoded and decode it.
}
}
if (m_help_enabled) {
const int windowWidth = 1280;
const int windowHeight = 768;
const int boxWidth = 1000;
const int boxHeight = 680;
const int boxX = (windowWidth - boxWidth) / 2;
const int boxY = (windowHeight - boxHeight) / 2;
const std::string helpText = "This is a sample help screen! You can put help text in here!?";
// Draw filled background box
diablo2::d2_gfx::draw_filled_rect(boxX, boxY, boxX + boxWidth, boxY + boxHeight, 0, 255);
// Draw justified text inside the box with padding
drawJustifiedTextInBox(helpText, boxX, boxY, boxWidth, boxHeight, 0);
}
diablo2::ui_color_t::UI_COLOR_WHITE;
// print player health, mana, and stamina bars, lastexp, nextexp, and level
// Get current HP, Mana, and Stamina along with their maximum values
int statHP = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(6), NULL) / 256;
int statMaxHP = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(7), NULL) / 256;
int statMana = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(8), NULL) / 256;
int statMaxMana = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(9), NULL) / 256;
int statStamina = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(10), NULL) / 256;
int statMaxStamina = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(11), NULL) / 256;
// Convert the integer values to wide character strings
std::wstring strHP = std::to_wstring(statHP);
std::wstring strMaxHP = std::to_wstring(statMaxHP);
std::wstring strMana = std::to_wstring(statMana);
std::wstring strMaxMana = std::to_wstring(statMaxMana);
std::wstring strStamina = std::to_wstring(statStamina);
std::wstring strMaxStamina = std::to_wstring(statMaxStamina);
diablo2::d2_win::set_current_font(diablo2::UI_FONT_16); // Set font to FONT16
// Calculate the percentages of current HP, Mana, and Stamina
float healthPercentage = static_cast<float>(statHP) / static_cast<float>(statMaxHP);
float manaPercentage = static_cast<float>(statMana) / static_cast<float>(statMaxMana);
float staminaPercentage = static_cast<float>(statStamina) / static_cast<float>(statMaxStamina);
int sHeight = 768;
int sWidth = 1280;
int sHCenter = sHeight / 2;
int sWCenter = sWidth / 2;
//spdlog::info("healthPercentage: {}", healthPercentage);
// Define default bar color
DWORD barColor = 0;
// Determine bar color based on health percentage
if (healthPercentage > .80) {
barColor = 118;
}
else if (healthPercentage > .50) {
barColor = 13;
}
else {
barColor = 5;
}
//spdlog::info("barColor: {}", barColor);
// Define the dimensions for the bars
int barWidth = 200; // Width of the bars
int barHeight = 16; // Height of the bars
// Define the coordinates for the bars
int barX = 245; // Left coordinate of the bars
int barY_HP = 728; // Top coordinate of the HP bar
int barY_Mana = barY_HP + barHeight + 4; // Top coordinate of the Mana bar with separator
int barY_Stamina = barY_Mana + barHeight + 4; // Top coordinate of the Stamina bar with separator
std::wstring life = strHP + L" / " + strMaxHP;
std::wstring mana = strMana + L" / " + strMaxMana;
std::wstring stamina = strStamina + L" / " + strMaxStamina;
// Calculate the filled widths of the bars
int filledHPWidth = static_cast<int>(healthPercentage * barWidth);
int filledManaWidth = static_cast<int>(manaPercentage * barWidth);
int filledStaminaWidth = static_cast<int>(staminaPercentage * barWidth);
// at 345 we need to minus the width of the text
sWCenter = barX + 100 - (diablo2::d2_win::get_text_pixel_width(const_cast<wchar_t*>(mana.c_str())) / 2);
HWND diabloIIWnd = FindDiabloIIWindow();
// Draw the filled HP bar
diablo2::d2_gfx::draw_filled_rect(barX, barY_HP, barX + filledHPWidth, barY_HP + barHeight, barColor, 255);
//DrawFilledRect(diabloIIWnd, barX, barY_HP, barX + filledHPWidth, barY_HP + barHeight, RGB(255, 0, 0)); // Red color for HP
diablo2::d2_win::draw_text(const_cast<wchar_t*>(life.c_str()), sWCenter, barY_HP + 15, diablo2::UI_COLOR_WHITE, 0);
// Draw the filled Mana bar
diablo2::d2_gfx::draw_filled_rect(barX, barY_Mana, barX + filledManaWidth, barY_Mana + barHeight, 140, 255);
//DrawFilledRect(diabloIIWnd, barX, barY_Mana, barX + filledManaWidth, barY_Mana + barHeight, RGB(100, 100, 255)); // Blue color for Mana
diablo2::d2_win::draw_text(const_cast<wchar_t*>(mana.c_str()), sWCenter, barY_Mana + 15, diablo2::UI_COLOR_WHITE, 0);
/*
// Define the number of separators
int numColors = 256;
int numColumns = 4;
int colorsPerColumn = numColors / numColumns;
int separatorHeight = 1; // Height of each separator
int columnOffset = 200; // Offset for each column
// Iterate over each column
for (int column = 0; column < numColumns; ++column) {
// Calculate the starting X coordinate for this column
int columnX = barX + (column * columnOffset);
// Draw the filled Mana bars for this column
for (int i = 0; i < colorsPerColumn; ++i) {
int colorIndex = column * colorsPerColumn + i;
int separatorY = barY_Mana + barHeight + i * (separatorHeight + barHeight);
// Draw the filled Mana bar
diablo2::d2_gfx::draw_filled_rect(columnX, separatorY, columnX + filledManaWidth, separatorY + barHeight, colorIndex, 255);
// Draw the index number at the same coordinates as the bar
std::wstring indexStr = std::to_wstring(colorIndex);
diablo2::d2_win::draw_text(const_cast<wchar_t*>(indexStr.c_str()), columnX - 20, separatorY, diablo2::UI_COLOR_DARK_GOLD, 0);
}
}
*/
// Draw the filled Stamina bar
// diablo2::d2_gfx::draw_filled_rect(barX, barY_Stamina, barX + filledStaminaWidth, barY_Stamina + barHeight, 12, 255);
//DrawFilledRect(diabloIIWnd, barX, barY_Stamina, barX + filledStaminaWidth, barY_Stamina + barHeight, RGB(255, 255, 0)); // Green color for Stamina
int statLevel = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(12), NULL);
int statLastExp = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(29), NULL);
int statNextExp = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(30), NULL);
diablo2::d2_win::set_current_font(diablo2::UI_FONT_16); // Set font to FONT16
if (!should_draw()) {
m_sort_inventory_btn->set_enabled(false);
m_sort_inventory_btn->set_visible(false);
@@ -546,12 +624,9 @@ private:
}
};
void d2_tweaks::client::modules::autosort::init_early() {
}
void d2_tweaks::client::modules::autosort::init() {
char acPathToIni[MAX_PATH] = { 0 };
const char* pcIniFile = "\\d2tweaks.ini";
@@ -583,5 +658,4 @@ void d2_tweaks::client::modules::autosort::handle_packet(common::packet_header*
diablo2::d2_common::inv_add_item(player->inventory, item, inventorySort->tx, inventorySort->ty, inventoryIndex, true, item->item_data->page);
diablo2::d2_common::inv_update_item(player->inventory, item, true);
}
}

View File

@@ -9,7 +9,24 @@
#include <DllNotify.h>
#include <D2Template.h>
#include <diablo2/d2gfx.h>
#include <string>
#include <vector>
#include <sstream>
#include <string>
#include <locale>
#include <codecvt>
#include <cstdlib> // For system function
#include <shellapi.h> // For ShellExecute
using namespace d2_tweaks::client::modules;
bool m_stats_enabled = false;
bool m_help_enabled = false;
d2_tweaks::client::modules::loot_filter_settings_toggle_menu::loot_filter_settings_toggle_menu(token) {
m_show = false;
@@ -39,6 +56,11 @@ d2_tweaks::client::modules::loot_filter_settings_toggle_menu::loot_filter_settin
m_btn_toggle_stats->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_stats_settings_click, this));
m_btn_toggle_help = static_cast<ui::controls::button*>(get_control("m_toggle_help"));
m_btn_toggle_help->set_enabled(true);
m_btn_toggle_help->set_visible(true);
m_btn_toggle_help->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_help_click, this));
}
void d2_tweaks::client::modules::loot_filter_settings_toggle_menu::toggle_filter_settings_click() {
@@ -55,6 +77,23 @@ void d2_tweaks::client::modules::loot_filter_settings_toggle_menu::toggle_stats_
m_stats_enabled = !m_stats_enabled;
}
void d2_tweaks::client::modules::loot_filter_settings_toggle_menu::toggle_help_click() {
//m_help_enabled = !m_help_enabled;
// Open the default OS browser to the URL
const std::string url = "https://im.stoned.io";
#ifdef _WIN32
// For Windows
ShellExecute(nullptr, "open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
#elif defined __linux__ || defined __APPLE__
// For Linux and macOS
system(("xdg-open " + url).c_str());
#else
// Unsupported platform
// You can add handling for other platforms here
#endif
}
void d2_tweaks::client::modules::loot_filter_settings_toggle_menu::draw() {
m_btn_toggle_stats->set_enabled(diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_INTERFACE));
m_btn_toggle_stats->set_visible(diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_INTERFACE));

View File

@@ -13,6 +13,64 @@
#include <spdlog/spdlog.h>
#include <fstream>
#include <iostream>
#include <diablo2/d2client.h>
#include <iomanip> // For std::setw
#include <sstream>
#include <string>
#include <stdexcept> // For std::invalid_argument
#include <windows.h> // Include Windows API header for MessageBox
// Define your deserialization method for the item structure
diablo2::structures::unit unserialize_item(const std::string& itemcode, std::ifstream& file) {
// Read each line from the file
std::string line;
while (std::getline(file, line)) {
// Split the line into item code and serialized data
std::istringstream iss(line);
std::string code;
std::getline(iss, code, ':');
if (code == itemcode) {
// Found matching item code, extract serialized data
std::string serializedData;
std::getline(iss, serializedData);
// Convert serialized data from hexadecimal string to binary
std::istringstream hexStream(serializedData);
diablo2::structures::unit item;
for (size_t i = 0; i < sizeof(item); ++i) {
int byte;
if (!(hexStream >> std::hex >> byte)) {
throw std::invalid_argument("Error reading serialized data");
}
reinterpret_cast<char*>(&item)[i] = static_cast<char>(byte);
}
return item;
}
}
// Item code not found
throw std::invalid_argument("Item code not found");
}
#include <iomanip> // For std::setw
void serialize_item(const std::string& itemcode, const diablo2::structures::unit& item, std::ofstream& file) {
// Write item code
file << itemcode << ":";
// Write serialized data
for (size_t i = 0; i < sizeof(item); ++i) {
file << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned>(reinterpret_cast<const char*>(&item)[i]);
}
// Add a newline after each item
file << std::endl;
}
MODULE_INIT(item_move)
void d2_tweaks::server::modules::item_move::init() {
@@ -35,7 +93,13 @@ bool d2_tweaks::server::modules::item_move::handle_packet(diablo2::structures::g
static auto& instance = singleton<server>::instance();
const auto itemMove = static_cast<common::item_move_cs*>(packet);
const auto key = static_cast<common::item_move_cs*>(packet)->item_code;
// Display key in a message box
MessageBox(NULL, key, "Item code", MB_OK | MB_ICONINFORMATION);
const auto item = instance.get_server_unit(game, itemMove->item_guid, diablo2::structures::unit_type_t::UNIT_TYPE_ITEM); //0x4 = item
const char* itemcode = itemMove->item_code;
const auto bag = instance.get_server_unit(game, itemMove->bag_guid, diablo2::structures::unit_type_t::UNIT_TYPE_ITEM); //0x4 = item
D2PropertyStrc itemProperty = {};
@@ -49,6 +113,9 @@ bool d2_tweaks::server::modules::item_move::handle_packet(diablo2::structures::g
if (item == nullptr)
return true; //block further packet processing
const auto inventoryIndex = diablo2::d2_common::get_inventory_index(player, itemMove->target_page, game->item_format == 101);
uint32_t tx, ty;
@@ -75,6 +142,22 @@ bool d2_tweaks::server::modules::item_move::handle_packet(diablo2::structures::g
diablo2::d2_net::send_to_client(1, client->client_id, &resp, sizeof resp);
if (itemMove->updateBag == 1) {
// Serialize item data into binary file
std::string playerName = player->player_data->name;
std::string fileName = "./Save/" + playerName + ".boh";
std::ofstream outFile(fileName, std::ios::binary);
if (!outFile) {
std::cerr << "Error opening file: " << fileName << std::endl;
return false;
}
serialize_item(itemcode, *item, outFile);
outFile.close();
}
return true;
}

View File

@@ -62,6 +62,16 @@
#include <string>
#include <map>
#include <iomanip> // For std::setw
#include <sstream>
#include <string>
#include <stdexcept> // For std::invalid_argument
#include <iostream>
#include <vector>
#include <string>
using namespace std;
diablo2::structures::unit* g_item1;
static LRESULT(__stdcall* g_wnd_proc_original)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
@@ -127,6 +137,8 @@ struct D2InventoryGridInfoStrc
WORD pad0x16; //0x16
};
LRESULT d2_tweaks::ui::ui_manager::wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
static auto& instance = singleton<ui_manager>::instance();
@@ -462,9 +474,10 @@ LRESULT d2_tweaks::ui::ui_manager::wnd_proc(HWND hWnd, UINT msg, WPARAM wParam,
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH) || diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CUBE) || diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_INVENTORY)) {
for (const auto& gem : gemTypes) {
// Accessing key and value
const std::string& key = gem.first;
const std::string& _key = gem.first;
const char* key = gem.first.c_str();
const GemType& value = gem.second;
if (strncmp(normCode, key.c_str(), 3) == 0) {
if (strncmp(normCode, key, 3) == 0) {
D2PropertyStrc itemProperty = {};
itemProperty.nProperty = value.rowID - 3;
itemProperty.nLayer = 0;
@@ -475,12 +488,15 @@ LRESULT d2_tweaks::ui::ui_manager::wnd_proc(HWND hWnd, UINT msg, WPARAM wParam,
static d2_tweaks::common::item_move_cs packet;
packet.item_guid = g_hoverItem->guid;
packet.item_code = key;
packet.bag_guid = gemBagGuid;
packet.updateBag = 1;
packet.prop = itemProperty.nProperty;
packet.val = itemProperty.nMin;
packet.target_page = 99;
diablo2::d2_client::send_to_server(&packet, sizeof packet);
}
}
}