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

@ -47,12 +47,12 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\Diablo II\MODS\ironman-dev</OutDir>
<OutDir>..\..\Diablo II\MODS\ironman-dev\</OutDir>
<IntDir>$(SolutionDir)Build\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\Diablo II\MODS\ironman-dev</OutDir>
<OutDir>..\..\Diablo II\MODS\ironman-dev\</OutDir>
<IntDir>$(SolutionDir)Build\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

Binary file not shown.

View File

@ -1,3 +1,2 @@
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.CppBuild.targets(517,5): warning MSB8004: Output Directory does not end with a trailing slash. This build instance will add the slash as it is required to allow proper evaluation of the Output Directory.
ui_manager.cpp
 ui_manager.cpp
D2tweaks.vcxproj -> D:\Diablo II\MODS\ironman-dev\D2tweaks.dll

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -28,6 +28,9 @@ extern int randStatBool;
extern bool m_stats_enabled;
extern bool m_help_enabled;
namespace diablo2 {
namespace structures {
struct unit;

View File

@ -17,6 +17,7 @@ namespace d2_tweaks {
class loot_filter_settings_toggle_menu final : public ui::menu, singleton<loot_filter_settings_toggle_menu> {
ui::controls::button* m_toggle_filter_settings_btn;
ui::controls::button* m_btn_toggle_stats;
ui::controls::button* m_btn_toggle_help;
menu* m_filter_settings_menu;
bool m_show;
public:
@ -24,6 +25,7 @@ namespace d2_tweaks {
void toggle_filter_settings_click();
void toggle_stats_settings_click();
void toggle_help_click();
void draw() override;

View File

@ -235,6 +235,7 @@ namespace d2_tweaks {
struct item_move_cs : packet_header {
uint32_t item_guid;
const char* item_code;
uint8_t target_page;
uint32_t bag_guid = 0;
bool updateBag;

View File

@ -86,5 +86,10 @@ namespace diablo2 {
static bool is_gamble_open();
static uint8_t current_interact_menu();
static void resync_vendor_inventory(structures::unit* ptNPC);
static int32_t send_to_server_9(BYTE type, DWORD num, DWORD unk1);
};
}

View File

@ -47,5 +47,6 @@ namespace diablo2 {
static void update_inventory_items(structures::game* game, structures::unit* player);
static uint32_t __fastcall diablo2::d2_game::transmogrify(diablo2::structures::game* game, diablo2::structures::unit* player);
};
}

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);
}
}
}

View File

@ -109,6 +109,13 @@ int32_t diablo2::d2_client::send_to_server_7(BYTE type, DWORD num, DWORD unk1, D
return send_to_server_7(type, num, unk1, unk2);
}
//D2FUNC(D2CLIENT, SendToServer9, void, __fastcall, (BYTE type, DWORD num, DWORD unk1), 0xDA40) // Interact
int32_t diablo2::d2_client::send_to_server_9(BYTE type, DWORD num, DWORD unk1) {
static wrap_func_fast<int32_t(BYTE type, DWORD num, DWORD unk1)> send_to_server_9(0xDA40, get_base());
return send_to_server_9(type, num, unk1);
}
uint32_t diablo2::d2_client::screen_height() {
return *reinterpret_cast<uint32_t*>(get_base() + 0xD40F0);
}

View File

@ -15,3 +15,4 @@ int32_t diablo2::d2_net::send_to_client(int32_t queue, int32_t clientId, void* p
static wrap_func_std_import<int32_t(int32_t, int32_t, void*, size_t)> send_to_client(10006, get_base());
return send_to_client(queue, clientId, packet, size);
}