Everything ini configurable

This commit is contained in:
Hash Borgir 2024-05-03 07:34:36 -06:00
parent 7fd617abd7
commit 06c28f4d56
48 changed files with 254 additions and 153 deletions

2
ClassDiagram.cd Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram />

View File

@ -180,6 +180,7 @@
<ClCompile Include="vendor\minhook\src\trampoline.c" /> <ClCompile Include="vendor\minhook\src\trampoline.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="ClassDiagram.cd" />
<None Include="vendor\minhook\dll_resources\MinHook.def" /> <None Include="vendor\minhook\dll_resources\MinHook.def" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Binary file not shown.

View File

@ -1,11 +1,2 @@
 autosort_client.cpp  ui_manager.cpp
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(197,15): warning C4018: '<': signed/unsigned mismatch
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(197,66): warning C4018: '<=': signed/unsigned mismatch
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(252,41): warning C4244: '=': conversion from 'double' to 'int32_t', possible loss of data
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(255,43): warning C4244: '=': conversion from 'double' to 'int32_t', possible loss of data
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(258,41): warning C4244: '=': conversion from 'double' to 'int32_t', possible loss of data
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(261,43): warning C4244: '=': conversion from 'double' to 'int32_t', possible loss of data
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(264,41): warning C4244: '=': conversion from 'double' to 'int32_t', possible loss of data
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(282,41): warning C4244: '=': conversion from 'double' to 'int32_t', possible loss of data
D:\VSCode\d2tweaks-rnd2k\src\d2tweaks\client\modules\autosort\autosort_client.cpp(288,41): warning C4244: '=': conversion from 'double' to 'int32_t', possible loss of data
D2tweaks.vcxproj -> D:\Diablo II\MODS\ironman-dev\D2tweaks.dll 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.

View File

@ -1044,5 +1044,11 @@ namespace diablo2 {
// Write a function signature for this function // Write a function signature for this function
static structures::D2ItemStatCostTxt* get_item_stat_cost_record(int nStatId); static structures::D2ItemStatCostTxt* get_item_stat_cost_record(int nStatId);
//D2Common.0x6FD57720 (#10602)
//int __stdcall DATATBLS_GetItemIdFromItemCode(uint32_t dwCode)
static int get_item_id_from_item_code(uint32_t dwCode);
}; };
} }

View File

@ -47,5 +47,8 @@ namespace diablo2 {
static void update_inventory_items(structures::game* game, structures::unit* player); 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); static uint32_t __fastcall diablo2::d2_game::transmogrify(diablo2::structures::game* game, diablo2::structures::unit* player);
//D2Game.0x6FC4ED80
structures::unit* __fastcall D2GAME_CreateItemEx_6FC4ED80(structures::game* pGame, structures::D2ItemDropStrc* pItemDrop, int32_t a3);
}; };
} }

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include "room.h"
#include <windows.h>
#pragma pack(push, 1) #pragma pack(push, 1)
@ -74,6 +76,50 @@ namespace diablo2 {
ITEMFLAG_ITEM = 0x08000000 ITEMFLAG_ITEM = 0x08000000
}; };
struct D2SeedStrc
{
union
{
struct
{
uint32_t nLowSeed; //0x00
uint32_t nHighSeed; //0x04
};
uint64_t lSeed; //0x00
};
};
struct D2ItemDropStrc
{
diablo2::structures::unit* pUnit; //0x00
D2SeedStrc* pSeed; //0x04
diablo2::structures::game* pGame; //0x08
int32_t nItemLvl; //0x0C
uint32_t unk0x10; //0x10
int32_t nId; //0x14
int32_t nSpawnType; //0x18 [3 for ground spawn, 4 for inv spawn]
int32_t nX; //0x1C
int32_t nY; //0x20
diablo2::structures::room* pRoom; //0x24
uint16_t wUnitInitFlags; //0x28
uint16_t wItemFormat; //0x2A [ptGame0x0x78]
BOOL bForce; //0x2C
int32_t nQuality; //0x30
int32_t nQuantity; //0x34
int32_t nMinDur; //0x38
int32_t nMaxDur; //0x3C
int32_t nItemIndex; //0x40
uint32_t dwFlags1; //0x44 - itemflag override (used when force is true)
uint32_t dwSeed; //0x48 - overrides the seed, used when force is true
uint32_t dwItemSeed; //0x4C - overrides the item seed when force is true
int32_t eEarLvl; //0x50
int32_t nQtyOverride; //0x54
char szName[16]; //0x58
int32_t nPrefix[3]; //0x68
int32_t nSuffix[3]; //0x74
uint32_t dwFlags2; //0x80
};
struct unit { struct unit {
unit_type_t type; unit_type_t type;

View File

@ -236,15 +236,9 @@ public:
for (const auto& stat : stats) { for (const auto& stat : stats) {
int param = stat.param; int param = stat.param;
int op = stat.op; int op = stat.op;
int32_t spirits = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(185), NULL);
int32_t soulscaptured = statValue = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(184), NULL);
auto statline = diablo2::d2_common::get_item_stat_cost_record(stat.stat); auto statline = diablo2::d2_common::get_item_stat_cost_record(stat.stat);
auto opBase = statline->wOpBase; auto opBase = statline->wOpBase;
auto opStat = statline->wOpStat[0]; auto opStat = statline->wOpStat[0];
auto opBaseValue = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(opBase), NULL); auto opBaseValue = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(opBase), NULL);
auto opStatValue = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(opStat), NULL); auto opStatValue = diablo2::d2_common::get_stat(player, static_cast<diablo2::unit_stats_t>(opStat), NULL);
@ -299,8 +293,6 @@ public:
if (!diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH) if (!diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH)
&& !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CHARACTER) && !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CHARACTER)
// && !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_INVENTORY)
// && !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_SKILL)
&& !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CHAT) && !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CHAT)
&& !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_NPCMENU) && !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_NPCMENU)
&& !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_MAINMENU) && !diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_MAINMENU)
@ -329,34 +321,25 @@ public:
//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*>(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::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::d2_win::set_current_font(diablo2::UI_FONT_16); // Set font to FONT16
//diablo2::structures::d2_cmp::init_gfx_data(&g_gfxdata); //diablo2::structures::d2_cmp::init_gfx_data(&g_gfxdata);
//diablo2::d2_gfx::draw_image(&g_gfxdata, 200, 200, 1, 5, 0); //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. // instead try to load direct jpg with gdi and insetad ofloading jpg file, specify it bb64 encoded and decode it.
} }
} }
if (m_help_enabled) { if (m_help_enabled) {
const int windowWidth = 1280; //const int windowWidth = 1280;
const int windowHeight = 768; //const int windowHeight = 768;
//const int boxWidth = 1000;
const int boxWidth = 1000; //const int boxHeight = 680;
const int boxHeight = 680; //const int boxX = (windowWidth - boxWidth) / 2;
//const int boxY = (windowHeight - boxHeight) / 2;
const int boxX = (windowWidth - boxWidth) / 2; //const std::string helpText = "This is a sample help screen! You can put help text in here!?";
const int boxY = (windowHeight - boxHeight) / 2; //// Draw filled background box
//diablo2::d2_gfx::draw_filled_rect(boxX, boxY, boxX + boxWidth, boxY + boxHeight, 0, 255);
const std::string helpText = "This is a sample help screen! You can put help text in here!?"; //// Draw justified text inside the box with padding
//drawJustifiedTextInBox(helpText, boxX, boxY, boxWidth, boxHeight, 0);
// 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; diablo2::ui_color_t::UI_COLOR_WHITE;
@ -391,8 +374,6 @@ public:
int sHCenter = sHeight / 2; int sHCenter = sHeight / 2;
int sWCenter = sWidth / 2; int sWCenter = sWidth / 2;
//spdlog::info("healthPercentage: {}", healthPercentage);
// Define default bar color // Define default bar color
DWORD barColor = 0; DWORD barColor = 0;
@ -407,42 +388,54 @@ public:
barColor = 5; barColor = 5;
} }
//spdlog::info("barColor: {}", barColor);
// Define the dimensions for the bars // Define the dimensions for the bars
int barWidth = 200; // Width of the bars int pbarWidth = GetPrivateProfileIntA("Options", "pbarWidth", 200, "./d2tweaks.ini");
int barHeight = 16; // Height of the bars int pbarHeight = GetPrivateProfileIntA("Options", "pbarHeight", 16, "./d2tweaks.ini");
// Define the coordinates for the bars // Define the coordinates for the bars
int barX = 245; // Left coordinate of the bars int barX = 245; // Left coordinate of the bars
int barY_HP = 728; // Top coordinate of the HP bar 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_Mana = barY_HP + pbarHeight + 4; // Top coordinate of the Mana bar with separator
int barY_Stamina = barY_Mana + barHeight + 4; // Top coordinate of the Stamina bar with separator int barY_Stamina = barY_Mana + pbarHeight + 4; // Top coordinate of the Stamina bar with separator
std::wstring life = strHP + L" / " + strMaxHP; std::wstring life = strHP + L" / " + strMaxHP;
std::wstring mana = strMana + L" / " + strMaxMana; std::wstring mana = strMana + L" / " + strMaxMana;
std::wstring stamina = strStamina + L" / " + strMaxStamina; std::wstring stamina = strStamina + L" / " + strMaxStamina;
// Calculate the filled widths of the bars // Calculate the filled widths of the bars
int filledHPWidth = static_cast<int>(healthPercentage * barWidth); int filledHPWidth = static_cast<int>(healthPercentage * pbarWidth);
int filledManaWidth = static_cast<int>(manaPercentage * barWidth); int filledManaWidth = static_cast<int>(manaPercentage * pbarWidth);
int filledStaminaWidth = static_cast<int>(staminaPercentage * barWidth); int filledStaminaWidth = static_cast<int>(staminaPercentage * pbarWidth);
// at 345 we need to minus the width of the text // 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); sWCenter = barX + 100 - (diablo2::d2_win::get_text_pixel_width(const_cast<wchar_t*>(mana.c_str())) / 2);
HWND diabloIIWnd = FindDiabloIIWindow(); HWND diabloIIWnd = FindDiabloIIWindow();
// Draw the filled HP bar // Get player_bars_enabled from [Options] in d2tweaks.ini
diablo2::d2_gfx::draw_filled_rect(barX, barY_HP, barX + filledHPWidth, barY_HP + barHeight, barColor, 255); int player_bars_enabled_hp = GetPrivateProfileIntA("Options", "player_bars_hp_enabled", 1, "./d2tweaks.ini");
//DrawFilledRect(diabloIIWnd, barX, barY_HP, barX + filledHPWidth, barY_HP + barHeight, RGB(255, 0, 0)); // Red color for HP int player_bars_X_hp = GetPrivateProfileIntA("Options", "player_bars_hp_X", barX, "./d2tweaks.ini");
diablo2::d2_win::draw_text(const_cast<wchar_t*>(life.c_str()), sWCenter, barY_HP + 15, diablo2::UI_COLOR_WHITE, 0); int player_bars_Y_hp = GetPrivateProfileIntA("Options", "player_bars_hp_Y", barY_HP, "./d2tweaks.ini");
// Draw the filled Mana bar int player_bars_enabled_mana = GetPrivateProfileIntA("Options", "player_bars_mana_enabled", 1, "./d2tweaks.ini");
diablo2::d2_gfx::draw_filled_rect(barX, barY_Mana, barX + filledManaWidth, barY_Mana + barHeight, 140, 255); int player_bars_X_mana = GetPrivateProfileIntA("Options", "player_bars_mana_X", barX, "./d2tweaks.ini");
//DrawFilledRect(diabloIIWnd, barX, barY_Mana, barX + filledManaWidth, barY_Mana + barHeight, RGB(100, 100, 255)); // Blue color for Mana int player_bars_Y_mana = GetPrivateProfileIntA("Options", "player_bars_mana_Y", barY_Mana, "./d2tweaks.ini");
diablo2::d2_win::draw_text(const_cast<wchar_t*>(mana.c_str()), sWCenter, barY_Mana + 15, diablo2::UI_COLOR_WHITE, 0);
if (player_bars_enabled_hp == 1) {
// Draw the filled HP bar
diablo2::d2_gfx::draw_filled_rect(player_bars_X_hp, player_bars_Y_hp, barX + filledHPWidth, barY_HP + pbarHeight, 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);
}
if (player_bars_enabled_mana == 1) {
// Draw the filled Mana bar
diablo2::d2_gfx::draw_filled_rect(player_bars_X_mana, player_bars_Y_mana, barX + filledManaWidth, barY_Mana + pbarHeight, 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 // Define the number of separators
int numColors = 256; int numColors = 256;

View File

@ -5,91 +5,45 @@
#include <d2tweaks/ui/controls/button.h> #include <d2tweaks/ui/controls/button.h>
#include <d2tweaks/client/client.h> #include <d2tweaks/client/client.h>
#include <diablo2/d2client.h> #include <diablo2/d2client.h>
#include <d2tweaks/ui/ui_manager.h> #include <diablo2/d2gfx.h>
#include <DllNotify.h> #include <DllNotify.h>
#include <D2Template.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
#include <diablo2/d2common.h> #include <diablo2/d2common.h>
#include <d2tweaks/ui/ui_manager.h> #include <d2tweaks/ui/ui_manager.h>
#include <cstdlib> // For system function
#include <shellapi.h> // For ShellExecute
#include <Windows.h> #include <Windows.h>
#include <algorithm> #include <algorithm>
#include <common/hooking.h> #include <common/hooking.h>
#include <d2tweaks/common/protocol.h> #include <d2tweaks/common/protocol.h>
#include <d2tweaks/ui/menu.h> #include <d2tweaks/ui/menu.h>
#include <diablo2/d2win.h>
#include <diablo2/d2client.h>
#include <diablo2/d2common.h>
#include <diablo2/d2game.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <Windows.h>
#include <d2tweaks/client/modules/autosort/autosort_client.h> #include <d2tweaks/client/modules/autosort/autosort_client.h>
#include <d2tweaks/client/client.h>
#include <spdlog/spdlog.h>
#include <d2tweaks/common/common.h> #include <d2tweaks/common/common.h>
#include <d2tweaks/common/protocol.h>
#include <d2tweaks/common/asset_manager.h> #include <d2tweaks/common/asset_manager.h>
#include <d2tweaks/ui/menu.h>
#include <d2tweaks/ui/ui_manager.h>
#include <d2tweaks/ui/controls/control.h> #include <d2tweaks/ui/controls/control.h>
#include <d2tweaks/ui/controls/button.h>
#include <diablo2/d2common.h>
#include <diablo2/d2client.h>
#include <diablo2/d2win.h> #include <diablo2/d2win.h>
#include <diablo2/d2gfx.h>
#include <diablo2/d2cmp.h> #include <diablo2/d2cmp.h>
#include <diablo2/structures/unit.h> #include <diablo2/structures/unit.h>
#include <diablo2/structures/inventory.h> #include <diablo2/structures/inventory.h>
#include <diablo2/structures/item_data.h> #include <diablo2/structures/item_data.h>
#include <diablo2/structures/player_data.h> #include <diablo2/structures/player_data.h>
#include <diablo2/structures/path.h> #include <diablo2/structures/path.h>
#include <diablo2/structures/game.h> #include <diablo2/structures/game.h>
#include <diablo2/structures/data/items_line.h> #include <diablo2/structures/data/items_line.h>
#include <diablo2/structures/data/item_types_line.h> #include <diablo2/structures/data/item_types_line.h>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <string>
#include <filesystem> #include <filesystem>
#include <unordered_map> #include <unordered_map>
#include <time.h> #include <time.h>
#include <cmath> #include <cmath>
#include <random> #include <random>
#include <algorithm>
#include <functional> #include <functional>
#include <map> #include <map>
#include <iomanip> // For std::setw #include <iomanip> // For std::setw
#include <sstream> #include <sstream>
#include <stdexcept> // For std::invalid_argument #include <stdexcept> // For std::invalid_argument
#include <iostream>
#include <vector> #include <vector>
#include <string> #include <string>
#include <CommCtrl.h> // Include for edit control #include <CommCtrl.h> // Include for edit control
@ -123,40 +77,57 @@ d2_tweaks::client::modules::loot_filter_settings_toggle_menu::loot_filter_settin
m_filter_settings_menu = singleton<ui::ui_manager>::instance().get_menu("loot_filter_settings_menu"); m_filter_settings_menu = singleton<ui::ui_manager>::instance().get_menu("loot_filter_settings_menu");
// toggle stats button
m_btn_toggle_stats = static_cast<ui::controls::button*>(get_control("m_toggle_stats")); m_btn_toggle_stats = static_cast<ui::controls::button*>(get_control("m_toggle_stats"));
m_btn_toggle_stats->set_enabled(true); m_btn_toggle_stats->set_enabled(true);
m_btn_toggle_stats->set_visible(true); m_btn_toggle_stats->set_visible(true);
m_btn_toggle_stats->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_stats_settings_click, this)); m_btn_toggle_stats->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_stats_settings_click, this));
// help button
m_btn_toggle_help = static_cast<ui::controls::button*>(get_control("m_toggle_help")); 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_enabled(true);
m_btn_toggle_help->set_visible(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)); m_btn_toggle_help->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_help_click, this));
// toggle open/close cube button
m_btn_toggle_cube = static_cast<ui::controls::button*>(get_control("m_toggle_cube")); m_btn_toggle_cube = static_cast<ui::controls::button*>(get_control("m_toggle_cube"));
m_btn_toggle_cube->set_enabled(true); m_btn_toggle_cube->set_enabled(true);
m_btn_toggle_cube->set_visible(true); m_btn_toggle_cube->set_visible(true);
auto player = diablo2::d2_client::get_local_player();
//iterate over all items in player inventory
for (auto item = player->inventory->first_item; item != nullptr; item = item->item_data->pt_next_item) {
const auto record = diablo2::d2_common::get_item_record(item->data_record_index);
char* normCode1 = record->string_code;
if (strncmp(normCode1, "box", 3) == 0) {
m_btn_toggle_cube->set_enabled(true);
m_btn_toggle_cube->set_visible(true);
break;
}
else {
m_btn_toggle_cube->set_enabled(false);
m_btn_toggle_cube->set_visible(false);
}
}
m_btn_toggle_cube->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_cube_click, this)); m_btn_toggle_cube->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_cube_click, this));
// toggle open/close stash button
m_btn_toggle_stash = static_cast<ui::controls::button*>(get_control("m_toggle_stash")); m_btn_toggle_stash = static_cast<ui::controls::button*>(get_control("m_toggle_stash"));
m_btn_toggle_stash->set_enabled(true); m_btn_toggle_stash->set_enabled(true);
m_btn_toggle_stash->set_visible(true); m_btn_toggle_stash->set_visible(true);
//auto player = diablo2::d2_client::get_local_player(); //iterate over all items in player inventory
////iterate over all items in player inventory for (auto item = player->inventory->first_item; item != nullptr; item = item->item_data->pt_next_item) {
//for (auto item = player->inventory->first_item; item != nullptr; item = item->item_data->pt_next_item) { const auto record = diablo2::d2_common::get_item_record(item->data_record_index);
// const auto record = diablo2::d2_common::get_item_record(item->data_record_index); char* normCode1 = record->string_code;
// char* normCode1 = record->string_code; if (strncmp(normCode1, "st0", 3) == 0) {
// if (strncmp(normCode1, "st0", 3) == 0) { m_btn_toggle_stash->set_enabled(true);
// m_btn_toggle_stash->set_enabled(true); m_btn_toggle_stash->set_visible(true);
// m_btn_toggle_stash->set_visible(true); break;
// break; }
// } else {
// else { m_btn_toggle_stash->set_enabled(false);
// m_btn_toggle_stash->set_enabled(false); m_btn_toggle_stash->set_visible(false);
// m_btn_toggle_stash->set_visible(false); }
// } }
//}
m_btn_toggle_stash->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_stash_click, this)); m_btn_toggle_stash->set_on_click(std::bind(&loot_filter_settings_toggle_menu::toggle_stash_click, this));
} }
@ -244,9 +215,7 @@ void d2_tweaks::client::modules::loot_filter_settings_toggle_menu::toggle_stash_
diablo2::d2_client::send_to_server(&packet, sizeof packet); diablo2::d2_client::send_to_server(&packet, sizeof packet);
} }
else { else {
//run a for loop and send th set_ui_toggle packet 255 times from 1 to 255
diablo2::d2_client::set_ui_toggle(0x19, 1, FALSE); diablo2::d2_client::set_ui_toggle(0x19, 1, FALSE);
// send to server7 to close cube packet 0x4F // send to server7 to close cube packet 0x4F
diablo2::d2_client::send_to_server_7(0x4F, 0x17, 0, 0); diablo2::d2_client::send_to_server_7(0x4F, 0x17, 0, 0);
} }
@ -255,7 +224,11 @@ void d2_tweaks::client::modules::loot_filter_settings_toggle_menu::toggle_stash_
void d2_tweaks::client::modules::loot_filter_settings_toggle_menu::toggle_help_click() { void d2_tweaks::client::modules::loot_filter_settings_toggle_menu::toggle_help_click() {
//m_help_enabled = !m_help_enabled; //m_help_enabled = !m_help_enabled;
// Open the default OS browser to the URL // Open the default OS browser to the URL
const std::string url = "https://im.stoned.io"; // read the url from the ./d2tweaks.ini file
char urlBuffer[256];
GetPrivateProfileStringA("Options", "help_url", "", urlBuffer, sizeof(urlBuffer), "./d2tweaks.ini");
const std::string url(urlBuffer);
#ifdef _WIN32 #ifdef _WIN32
// For Windows // For Windows
ShellExecute(nullptr, "open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL); ShellExecute(nullptr, "open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);

View File

@ -71,6 +71,12 @@
#include <d2tweaks/client/client.h> #include <d2tweaks/client/client.h>
#include <chrono> // Include chrono for time-based operations
// Define a static variable to keep track of the last time the stash window was toggled
static std::chrono::steady_clock::time_point lastToggleTime;
#pragma pack(push, 1) #pragma pack(push, 1)
using namespace std; using namespace std;
@ -247,37 +253,101 @@ LRESULT d2_tweaks::ui::ui_manager::wnd_proc(HWND hWnd, UINT msg, WPARAM wParam,
} }
if (wParam == 'V') { if (wParam == 'V') {
const auto player = diablo2::d2_client::get_local_player(); // Define a cooldown duration in milliseconds
int32_t st0Guid = 0; constexpr int cooldownDuration = 500; // Adjust this value as needed
uint32_t st0X = 0;
uint32_t st0Y = 0; // Get the current time
diablo2::structures::unit* box{}; auto currentTime = std::chrono::steady_clock::now();
for (auto item = player->inventory->first_item; item != nullptr; item = item->item_data->pt_next_item) {
const auto record = diablo2::d2_common::get_item_record(item->data_record_index); // Calculate the time elapsed since the last stash toggle
char* st0Code = record->string_code; auto timeElapsed = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastToggleTime).count();
if (strncmp(st0Code, "st0", 3) == 0) {
box = item; // Check if enough time has elapsed since the last toggle
st0Guid = box->guid; if (timeElapsed >= cooldownDuration) {
st0X = player->path->mapx; // Update the last toggle time
st0Y = player->path->mapy; lastToggleTime = currentTime;
if (!diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH)) {
// Code to open stash
const auto player = diablo2::d2_client::get_local_player();
int32_t st0Guid = 0;
uint32_t st0X = 0;
uint32_t st0Y = 0;
diablo2::structures::unit* box{};
for (auto item = player->inventory->first_item; item != nullptr; item = item->item_data->pt_next_item) {
const auto record = diablo2::d2_common::get_item_record(item->data_record_index);
char* st0Code = record->string_code;
if (strncmp(st0Code, "st0", 3) == 0) {
box = item;
st0Guid = box->guid;
st0X = player->path->mapx;
st0Y = player->path->mapy;
}
}
struct D2GSPacketClt20 {
uint8_t PacketId; // 0x01
uint32_t guid; // 0x06
uint32_t tx; // 0x07
uint32_t ty; // 0x09
};
D2GSPacketClt20 packet;
packet.PacketId = 0x20;
packet.guid = st0Guid;
packet.tx = st0X;
packet.ty = st0Y;
diablo2::d2_client::send_to_server(&packet, sizeof packet);
block = true;
// MessageBoxA(NULL, "Stash opened", "Stash", MB_OK);
// spdlog::info("Stash opened");
}
else {
// Code to close stash
// Close stash
diablo2::d2_client::set_ui_toggle(0x19, 1, FALSE);
// send to server7 to close cube packet 0x4F
diablo2::d2_client::send_to_server_7(0x4F, 0x17, 0, 0);
block = true;
} }
} }
struct D2GSPacketClt20 {
uint8_t PacketId; // 0x01
uint32_t guid; // 0x06
uint32_t tx; // 0x07
uint32_t ty; // 0x09
};
D2GSPacketClt20 packet;
packet.PacketId = 0x20;
packet.guid = st0Guid;
packet.tx = st0X;
packet.ty = st0Y;
diablo2::d2_client::send_to_server(&packet, sizeof packet);
m_stash_enabled = false;
block = true;
} }
//if (wParam == 'V') {
// const auto player = diablo2::d2_client::get_local_player();
// int32_t st0Guid = 0;
// uint32_t st0X = 0;
// uint32_t st0Y = 0;
// diablo2::structures::unit* box{};
// for (auto item = player->inventory->first_item; item != nullptr; item = item->item_data->pt_next_item) {
// const auto record = diablo2::d2_common::get_item_record(item->data_record_index);
// char* st0Code = record->string_code;
// if (strncmp(st0Code, "st0", 3) == 0) {
// box = item;
// st0Guid = box->guid;
// st0X = player->path->mapx;
// st0Y = player->path->mapy;
// }
// }
// struct D2GSPacketClt20 {
// uint8_t PacketId; // 0x01
// uint32_t guid; // 0x06
// uint32_t tx; // 0x07
// uint32_t ty; // 0x09
// };
// D2GSPacketClt20 packet;
// packet.PacketId = 0x20;
// packet.guid = st0Guid;
// packet.tx = st0X;
// packet.ty = st0Y;
// diablo2::d2_client::send_to_server(&packet, sizeof packet);
// m_stash_enabled = false;
// block = true;
//}
// Send item move packet + transmute packet for certain codes only for runes and gems // Send item move packet + transmute packet for certain codes only for runes and gems
if (wParam == 'G') { if (wParam == 'G') {
// Call the item_click function using the function pointer // Call the item_click function using the function pointer

View File

@ -257,4 +257,13 @@ void diablo2::d2_common::ITEMS_SetItemFlag(structures::unit* item, uint32_t dwFl
diablo2::structures::D2ItemStatCostTxt* diablo2::d2_common::get_item_stat_cost_record(int statId) { diablo2::structures::D2ItemStatCostTxt* diablo2::d2_common::get_item_stat_cost_record(int statId) {
static wrap_func_fast<diablo2::structures::D2ItemStatCostTxt* (int)> get_item_stat_cost_record(0x642b0, get_base()); static wrap_func_fast<diablo2::structures::D2ItemStatCostTxt* (int)> get_item_stat_cost_record(0x642b0, get_base());
return get_item_stat_cost_record(statId); return get_item_stat_cost_record(statId);
}
//D2Common.0x6FD57720 (#10602)
//int __stdcall DATATBLS_GetItemIdFromItemCode(uint32_t dwCode)
//static int get_item_id_from_item_code(uint32_t dwCode);
int32_t diablo2::d2_common::get_item_id_from_item_code(uint32_t dwCode) {
static wrap_func_std_import<int32_t(uint32_t)> get_item_id_from_item_code(10602, get_base());
return get_item_id_from_item_code(dwCode);
} }

View File

@ -135,4 +135,11 @@ uint32_t __fastcall diablo2::d2_game::transmogrify(diablo2::structures::game* ga
} }
// d2game:$0x60010 // d2game:$0x60010
// int __fastcall CRAFT_Transmogrify(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2CubemainTXT* pCubeTxt, void* pUnknown) // int __fastcall CRAFT_Transmogrify(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2CubemainTXT* pCubeTxt, void* pUnknown)
// Add a wrapper for the following function:
// structures::unit* __fastcall D2GAME_CreateItemEx_6FC4ED80(structures::game* pGame, structures::D2ItemDropStrc* pItemDrop, int32_t a3);
diablo2::structures::unit* __fastcall diablo2::d2_game::D2GAME_CreateItemEx_6FC4ED80(diablo2::structures::game* pGame, diablo2::structures::D2ItemDropStrc* pItemDrop, int32_t a3) {
static wrap_func_fast< diablo2::structures::unit* (diablo2::structures::game*, diablo2::structures::D2ItemDropStrc*, int32_t)> D2GAME_CreateItemEx_6FC4ED80(0x1ed80, get_base());
return D2GAME_CreateItemEx_6FC4ED80(pGame, pItemDrop, a3);
}