mirror of
https://gitlab.com/hashborgir/d2tweaks-rnd2k.git
synced 2025-09-18 17:42:08 +00:00
1657 lines
58 KiB
C++
1657 lines
58 KiB
C++
#include <Windows.h>
|
|
#include <algorithm>
|
|
#include <chrono>
|
|
#include <common/hooking.h>
|
|
#include <d2tweaks/client/client.h>
|
|
#include <d2tweaks/client/modules/autosort/autosort_client.h>
|
|
#include <d2tweaks/common/asset_manager.h>
|
|
#include <d2tweaks/common/common.h>
|
|
#include <d2tweaks/common/protocol.h>
|
|
#include <d2tweaks/ui/controls/button.h>
|
|
#include <d2tweaks/ui/controls/control.h>
|
|
#include <d2tweaks/ui/menu.h>
|
|
#include <d2tweaks/ui/ui_manager.h>
|
|
#include <diablo2/d2client.h>
|
|
#include <diablo2/d2cmp.h>
|
|
#include <diablo2/d2common.h>
|
|
#include <diablo2/d2game.h>
|
|
#include <diablo2/d2gfx.h>
|
|
#include <diablo2/d2win.h>
|
|
#include <diablo2/structures/data/item_types_line.h>
|
|
#include <diablo2/structures/data/items_line.h>
|
|
#include <diablo2/structures/game.h>
|
|
#include <diablo2/structures/inventory.h>
|
|
#include <diablo2/structures/item_data.h>
|
|
#include <diablo2/structures/path.h>
|
|
#include <diablo2/structures/player_data.h>
|
|
#include <diablo2/structures/unit.h>
|
|
#include <fstream>
|
|
#include <functional>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <random>
|
|
#include <spdlog/spdlog.h>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <time.h>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
#include <CommCtrl.h> // Include for edit control
|
|
#include <d2tweaks/client/modules/loot_filter/loot_filter_settings_toggle_menu.h>
|
|
|
|
// 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)
|
|
|
|
using namespace std;
|
|
|
|
diablo2::structures::unit* g_item1;
|
|
|
|
static LRESULT(__stdcall* g_wnd_proc_original)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
d2_tweaks::ui::ui_manager::ui_manager(token) {
|
|
hooking::hook(diablo2::d2_win::get_base() + 0xD9B0, wnd_proc, reinterpret_cast<void**>(&g_wnd_proc_original));
|
|
}
|
|
|
|
void d2_tweaks::ui::ui_manager::add_menu(menu* m) {
|
|
if (m == nullptr)
|
|
return;
|
|
|
|
const auto it = std::find(m_menus.begin(), m_menus.end(), m);
|
|
|
|
if (it != m_menus.end())
|
|
return;
|
|
|
|
m_menus.push_back(m);
|
|
}
|
|
|
|
d2_tweaks::ui::menu* d2_tweaks::ui::ui_manager::get_menu(const std::string& name) {
|
|
if (name.empty())
|
|
return nullptr;
|
|
|
|
//TODO: optimize somehow
|
|
for (auto menu : m_menus) {
|
|
if (menu->get_name() == name)
|
|
return menu;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void d2_tweaks::ui::ui_manager::remove_menu(menu* m) {
|
|
if (m == nullptr)
|
|
return;
|
|
|
|
m_menus.erase(std::remove(m_menus.begin(), m_menus.end(), m), m_menus.end());
|
|
}
|
|
|
|
void d2_tweaks::ui::ui_manager::draw() {
|
|
//process_inputs();
|
|
|
|
for (auto menu : m_menus) {
|
|
if (!menu->get_visible())
|
|
continue;
|
|
|
|
menu->draw();
|
|
}
|
|
}
|
|
|
|
const char* ITEMS_armor_and_weapons[] = {
|
|
"hax", "axe", "2ax", "mpi", "wax", "lax", "bax", "btx", "gax", "gix",
|
|
"wnd", "ywn", "bwn", "gwn", "clb", "scp", "gsc", "wsp", "spc", "mac",
|
|
"mst", "fla", "whm", "mau", "gma", "ssd", "scm", "sbr", "flc", "crs",
|
|
"bsd", "lsd", "wsd", "2hs", "clm", "gis", "bsw", "flb", "gsd", "dgr",
|
|
"dir", "kri", "bld", "tkf", "tax", "bkf", "bal", "jav", "pil", "ssp",
|
|
"glv", "tsp", "spr", "tri", "brn", "spt", "pik", "bar", "vou", "scy",
|
|
"pax", "hal", "wsc", "sst", "lst", "cst", "bst", "wst", "sbw", "hbw",
|
|
"lbw", "cbw", "sbb", "lbb", "swb", "lwb", "lxb", "mxb", "hxb", "rxb",
|
|
"gps", "ops", "gpm", "opm", "gpl", "opl", "d33", "g33", "leg", "hdm",
|
|
"hfh", "hst", "msf", "9ha", "9ax", "92a", "9mp", "9wa", "9la", "9ba",
|
|
"9bt", "9ga", "9gi", "9wn", "9yw", "9bw", "9gw", "9cl", "9sc", "9qs",
|
|
"9ws", "9sp", "9ma", "9mt", "9fl", "9wh", "9m9", "9gm", "9ss", "9sm",
|
|
"9sb", "9fc", "9cr", "9bs", "9ls", "9wd", "92h", "9cm", "9gs", "9b9",
|
|
"9fb", "9gd", "9dg", "9di", "9kr", "9bl", "9tk", "9ta", "9bk", "9b8",
|
|
"9ja", "9pi", "9s9", "9gl", "9ts", "9sr", "9tr", "9br", "9st", "9p9",
|
|
"9b7", "9vo", "9s8", "9pa", "9h9", "9wc", "8ss", "8ls", "8cs", "8bs",
|
|
"8ws", "8sb", "8hb", "8lb", "8cb", "8s8", "8l8", "8sw", "8lw", "8lx",
|
|
"8mx", "8hx", "8rx", "qf1", "qf2", "ktr", "wrb", "axf", "ces", "clw",
|
|
"btl", "skr", "9ar", "9wb", "9xf", "9cs", "9lw", "9tw", "9qr", "7ar",
|
|
"7wb", "7xf", "7cs", "7lw", "7tw", "7qr", "7ha", "7ax", "72a", "7mp",
|
|
"7wa", "7la", "7ba", "7bt", "7ga", "7gi", "7wn", "7yw", "7bw", "7gw",
|
|
"7cl", "7sc", "7qs", "7ws", "7sp", "7ma", "7mt", "7fl", "7wh", "7m7",
|
|
"7gm", "7ss", "7sm", "7sb", "7fc", "7cr", "7bs", "7ls", "7wd", "72h",
|
|
"7cm", "7gs", "7b7", "7fb", "7gd", "7dg", "7di", "7kr", "7bl", "7tk",
|
|
"7ta", "7bk", "7b8", "7ja", "7pi", "7s7", "7gl", "7ts", "7sr", "7tr",
|
|
"7br", "7st", "7p7", "7o7", "7vo", "7s8", "7pa", "7h7", "7wc", "6ss",
|
|
"6ls", "6cs", "6bs", "6ws", "6sb", "6hb", "6lb", "6cb", "6s7", "6l7",
|
|
"6sw", "6lw", "6lx", "6mx", "6hx", "6rx", "ob1", "ob2", "ob3", "ob4",
|
|
"ob5", "am1", "am2", "am3", "am4", "am5", "ob6", "ob7", "ob8", "ob9",
|
|
"oba", "am6", "am7", "am8", "am9", "ama", "obb", "obc", "obd", "obe",
|
|
"obf", "amb", "amc", "amd", "ame", "amf", "cap", "skp", "hlm", "fhl",
|
|
"ghm", "crn", "msk", "qui", "lea", "hla", "stu", "rng", "scl", "chn",
|
|
"brs", "spl", "plt", "fld", "gth", "ful", "aar", "ltp", "buc", "sml",
|
|
"lrg", "kit", "tow", "gts", "lgl", "vgl", "mgl", "tgl", "hgl", "lbt",
|
|
"vbt", "mbt", "tbt", "hbt", "lbl", "vbl", "mbl", "tbl", "hbl", "bhm",
|
|
"bsh", "spk", "xap", "xkp", "xlm", "xhl", "xhm", "xrn", "xsk", "xui",
|
|
"xea", "xla", "xtu", "xng", "xcl", "xhn", "xrs", "xpl", "xlt", "xld",
|
|
"xth", "xul", "xar", "xtp", "xuc", "xml", "xrg", "xit", "xow", "xts",
|
|
"xlg", "xvg", "xmg", "xtg", "xhg", "xlb", "xvb", "xmb", "xtb", "xhb",
|
|
"zlb", "zvb", "zmb", "ztb", "zhb", "xh9", "xsh", "xpk", "dr1", "dr2",
|
|
"dr3", "dr4", "dr5", "ba1", "ba2", "ba3", "ba4", "ba5", "pa1", "pa2",
|
|
"pa3", "pa4", "pa5", "ne1", "ne2", "ne3", "ne4", "ne5", "ci0", "ci1",
|
|
"ci2", "ci3", "uap", "ukp", "ulm", "uhl", "uhm", "urn", "usk", "uui",
|
|
"uea", "ula", "utu", "ung", "ucl", "uhn", "urs", "upl", "ult", "uld",
|
|
"uth", "uul", "uar", "utp", "uuc", "uml", "urg", "uit", "uow", "uts",
|
|
"ulg", "uvg", "umg", "utg", "uhg", "ulb", "uvb", "umb", "utb", "uhb",
|
|
"ulc", "uvc", "umc", "utc", "uhc", "uh9", "ush", "upk", "dr6", "dr7",
|
|
"dr8", "dr9", "dra", "ba6", "ba7", "ba8", "ba9", "baa", "pa6", "pa7",
|
|
"pa8", "pa9", "paa", "ne6", "ne7", "ne8", "ne9", "nea", "drb", "drc",
|
|
"drd", "dre", "drf", "bab", "bac", "bad", "bae", "baf", "pab", "pac",
|
|
"pad", "pae", "paf", "neb", "neg", "ned", "nee", "nef", "tor", "ooc",
|
|
"eaq", "ebq", "ib3", "aqv", "cqv"
|
|
|
|
// demon keys/chests
|
|
"dkr1", "dkr2", "dkr3", "dkr4", "dkr5", "da1", "db1", "dc1"
|
|
// crafting items
|
|
"afr", "afy", "afp", "af0", "afx", "afh", "afq", "afj", "aft", "afi",
|
|
"afe", "afg", "afk", "ae7", "afn", "ae8", "afl", "ae9", "afv", "afz",
|
|
"af3", "af1", "afm", "af5", "afc", "afo", "afw", "afs", "af2", "afd",
|
|
"afb", "af4", "afu",
|
|
|
|
// rings/amulets
|
|
"rin", "amu", "jew"
|
|
};
|
|
|
|
const char* ITEMS_gems_and_runes[] = {
|
|
"gcv", "gcw", "gcg", "gcr", "gcb", "skc", "gcy", "gfv", "gfw", "gfg",
|
|
"gfr", "gfb", "skf", "gfy", "gsv", "gsw", "gsg", "gsr", "gsb", "sku",
|
|
"gsy", "gzv", "glw", "glg", "glr", "glb", "skl", "gly", "gpv", "gpw",
|
|
"gpg", "gpr", "gpb", "skz", "gpy", "ib1", "r01", "r02", "r03", "r04",
|
|
"r05", "r06", "r07", "r08", "r09", "r10", "r11", "r12", "r13", "r14",
|
|
"r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24",
|
|
"r25", "r26", "r27", "r28", "r29", "r30", "r31", "r32", "r33", "ib2",
|
|
};
|
|
|
|
const char* ITEMS_Stones[] = {
|
|
// stones
|
|
"abc", "abd", "abe", "abf", "abg", "abh", "abi", "abj", "abk", "abl",
|
|
"abm", "abn", "abo", "abp", "abq", "abr", "abs", "abt", "abu", "abv",
|
|
"abw", "abx", "aby", "abz", "ab0", "ab1", "ab2", "ab3", "ab4", "ab5",
|
|
"ab6", "ab7", "ab8", "ab9", "acb", "acd", "ace", "acf", "acg", "ach",
|
|
"aci", "acj", "ack", "acl", "acm", "acn", "aco", "acp", "acq", "acr",
|
|
"acs", "act", "acu", "acv", "acw", "acx", "acy", "acz", "ac0", "ac1",
|
|
"ac2", "ac3", "ac4", "ac5", "ac6", "ac7", "ac8", "ac9", "adb", "adc",
|
|
"ade", "adf", "adg", "adh", "adi", "adj", "adk", "adl", "adm", "adn",
|
|
"ado", "adp", "adq", "adr", "ads", "adt", "adu", "adv", "adw", "adx",
|
|
"ady", "adz", "ad0", "ad1", "ad2", "ad3", "ad4", "ad5", "ad6", "ad7",
|
|
"ad8", "ad9", "aeb", "aec", "aed", "aef", "aeg", "aeh", "aei", "aej",
|
|
"aek", "ael", "aem", "aen", "aeo", "aep", "aeq", "aer", "aes", "aet",
|
|
"aeu", "aev", "aew", "aex", "aey", "aez", "ae0", "ae1", "ae2", "ae3",
|
|
"ae4", "ae5", "ae6",
|
|
};
|
|
|
|
// Define a structure named GemType
|
|
struct GemType {
|
|
// Comment: The number of chipped gems of this type
|
|
int chippedCount;
|
|
|
|
// Comment: The row number in properties.txt minus 3, representing the type of gem
|
|
int rowID;
|
|
};
|
|
|
|
// Gem/Rune Extractors
|
|
static std::unordered_map<std::string, GemType> stoneTypes = {
|
|
};
|
|
|
|
// Gems/runes and their corresponding codes and properties.txt line numbers
|
|
static std::unordered_map<std::string, GemType> gemTypes = {
|
|
{"gcv", {1, 382}}, // Chipped Amethyst
|
|
{"gcw", {1, 383}}, // Chipped Diamond
|
|
{"gcg", {1, 384}}, // Chipped Emerald
|
|
{"gcr", {1, 381}}, // Chipped Ruby
|
|
{"gcb", {1, 385}}, // Chipped Sapphire
|
|
{"skc", {1, 387}}, // Chipped Skull
|
|
{"gcy", {1, 386}}, // Chipped Topaz
|
|
{"gfv", {3, 382}}, // Flawed Amethyst
|
|
{"gfw", {3, 383}}, // Flawed Diamond
|
|
{"gfg", {3, 384}}, // Flawed Emerald
|
|
{"gfr", {3, 381}}, // Flawed Ruby
|
|
{"gfb", {3, 385}}, // Flawed Sapphire
|
|
{"skf", {3, 387}}, // Flawed Skull
|
|
{"gfy", {3, 386}}, // Flawed Topaz
|
|
{"gsv", {9, 382}}, // Amethyst
|
|
{"gsw", {9, 383}}, // Diamond
|
|
{"gsg", {9, 384}}, // Emerald`
|
|
{"gsr", {9, 381}}, // Ruby
|
|
{"gsb", {9, 385}}, // Sapphire
|
|
{"sku", {9, 387}}, // Skull
|
|
{"gsy", {9, 386}}, // Topaz
|
|
{"gzv", {27, 382}}, // Flawless Amethyst
|
|
{"glw", {27, 383}}, // Flawless Diamond
|
|
{"glg", {27, 384}}, // Flawless Emerald
|
|
{"glr", {27, 381}}, // Flawless Ruby
|
|
{"glb", {27, 385}}, // Flawless Sapphire
|
|
{"skl", {27, 387}}, // Flawless Skull
|
|
{"gly", {27, 386}}, // Flawless Topaz
|
|
{"gpv", {81, 382}}, // Perfect Amethyst
|
|
{"gpw", {81, 383}}, // Perfect Diamond
|
|
{"gpg", {81, 384}}, // Perfect Emerald
|
|
{"gpr", {81, 381}}, // Perfect Ruby
|
|
{"gpb", {81, 385}}, // Perfect Sapphire
|
|
{"skz", {81, 387}}, // Perfect Skull
|
|
{"gpy", {81, 386}}, // Perfect Topaz
|
|
{"r01", {1, 388}}, // El Rune
|
|
{"r02", {3, 388}}, // Eld Rune
|
|
{"r03", {9, 388}}, // Tir Rune
|
|
{"r04", {27, 388}}, // Nef Rune
|
|
{"r05", {81, 388}}, // Eth Rune
|
|
{"r06", {243, 388}}, // Ith Rune
|
|
{"r07", {1, 389}}, // Tal Rune
|
|
{"r08", {3, 389}}, // Ral Rune
|
|
{"r09", {9, 389}}, // Ort Rune
|
|
{"r10", {27, 389}}, // Thul Rune
|
|
{"r11", {81, 389}}, // Amn Rune
|
|
{"r12", {243, 389}}, // Sol Rune
|
|
{"r13", {1, 390}}, // Shael Rune
|
|
{"r14", {3, 390}}, // Dol Rune
|
|
{"r15", {9, 390}}, // Hel Rune
|
|
{"r16", {27, 390}}, // Io Rune
|
|
{"r17", {81, 390}}, // Lum Rune
|
|
{"r18", {243, 390}}, // Ko Rune
|
|
{"r19", {1, 391}}, // Fal Rune
|
|
{"r20", {3, 391}}, // Lem Rune
|
|
{"r21", {9, 391}}, // Pul Rune
|
|
{"r22", {27, 391}}, // Um Rune
|
|
{"r23", {81, 3901}}, // Mal Rune
|
|
{"r24", {243, 391}}, // Ist Rune
|
|
{"r25", {1, 392}}, // Gul Rune
|
|
{"r26", {3, 392}}, // Vex Rune
|
|
{"r27", {9, 392}}, // Ohm Rune
|
|
{"r28", {27, 392}}, // Lo Rune
|
|
{"r29", {81, 392}}, // Sur Rune
|
|
{"r30", {243, 392}}, // Ber Rune
|
|
{"r31", {1, 393}}, // Jah Rune
|
|
{"r32", {2, 393}}, // Cham Rune
|
|
{"r33", {4, 393}}, // Zod Rune
|
|
//stones
|
|
{"abc", {1, 351}},
|
|
{"abd", {2, 351}},
|
|
{"abe", {4, 351}},
|
|
{"abf", {8, 351}},
|
|
{"abg", {16, 351}},
|
|
{"abh", {32, 351}},
|
|
{"abi", {64, 351}},
|
|
{"abj", {128, 351}},
|
|
{"abk", {256, 351}},
|
|
{"abl", {512, 351}},
|
|
{"abm", {1024, 351}},
|
|
{"abn", {2048, 351}},
|
|
{"abo", {4096, 351}},
|
|
{"abp", {8192, 351}},
|
|
{"abq", {16384, 351}},
|
|
{"abr", {32768, 351}},
|
|
{"abs", {65536, 351}},
|
|
{"abt", {131072, 351}},
|
|
{"abu", {262144, 351}},
|
|
{"abv", {1, 352}},
|
|
{"abw", {2, 352}},
|
|
{"abx", {4, 352}},
|
|
{"aby", {8, 352}},
|
|
{"abz", {16, 352}},
|
|
{"ab0", {32, 352}},
|
|
{"ab1", {64, 352}},
|
|
{"ab2", {128, 352}},
|
|
{"ab3", {256, 352}},
|
|
{"ab4", {512, 352}},
|
|
{"ab5", {1024, 352}},
|
|
{"ab6", {2048, 352}},
|
|
{"ab7", {4096, 352}},
|
|
{"ab8", {8192, 352}},
|
|
{"ab9", {16384, 352}},
|
|
{"acb", {32768, 352}},
|
|
{"acd", {65536, 352}},
|
|
{"ace", {131072, 352}},
|
|
{"acf", {262144, 352}},
|
|
{"acg", {1, 353}},
|
|
{"ach", {2, 353}},
|
|
{"aci", {4, 353}},
|
|
{"acj", {8, 353}},
|
|
{"ack", {16, 353}},
|
|
{"acl", {32, 353}},
|
|
{"acm", {64, 353}},
|
|
{"acn", {128, 353}},
|
|
{"aco", {256, 353}},
|
|
{"acp", {512, 353}},
|
|
{"acq", {1024, 353}},
|
|
{"acr", {2048, 353}},
|
|
{"acs", {4096, 353}},
|
|
{"act", {8192, 353}},
|
|
{"acu", {16384, 353}},
|
|
{"acv", {32768, 353}},
|
|
{"acw", {65536, 353}},
|
|
{"acx", {131072, 353}},
|
|
{"acy", {262144, 353}},
|
|
{"acz", {1, 354}},
|
|
{"ac0", {2, 354}},
|
|
{"ac1", {4, 354}},
|
|
{"ac2", {8, 354}},
|
|
{"ac3", {16, 354}},
|
|
{"ac4", {32, 354}},
|
|
{"ac5", {64, 354}},
|
|
{"ac6", {128, 354}},
|
|
{"ac7", {256, 354}},
|
|
{"ac8", {512, 354}},
|
|
{"ac9", {1024, 354}},
|
|
{"adb", {2048, 354}},
|
|
{"adc", {4096, 354}},
|
|
{"ade", {8192, 354}},
|
|
{"adf", {16384, 354}},
|
|
{"adg", {32768, 354}},
|
|
{"adh", {65536, 354}},
|
|
{"adi", {131072, 354}},
|
|
{"adj", {262144, 354}},
|
|
{"adk", {1, 355}},
|
|
{"adl", {2, 355}},
|
|
{"adm", {4, 355}},
|
|
{"adn", {8, 355}},
|
|
{"ado", {16, 355}},
|
|
{"adp", {32, 355}},
|
|
{"adq", {64, 355}},
|
|
{"adr", {128, 355}},
|
|
{"ads", {256, 355}},
|
|
{"adt", {512, 355}},
|
|
{"adu", {1024, 355}},
|
|
{"adv", {2048, 355}},
|
|
{"adw", {4096, 355}},
|
|
{"adx", {8192, 355}},
|
|
{"ady", {16384, 355}},
|
|
{"adz", {32768, 355}},
|
|
{"ad0", {65536, 355}},
|
|
{"ad1", {131072, 355}},
|
|
{"ad2", {262144, 355}},
|
|
{"ad3", {1, 356}},
|
|
{"ad4", {2, 356}},
|
|
{"ad5", {4, 356}},
|
|
{"ad6", {8, 356}},
|
|
{"ad7", {16, 356}},
|
|
{"ad8", {32, 356}},
|
|
{"ad9", {64, 356}},
|
|
{"aeb", {128, 356}},
|
|
{"aec", {256, 356}},
|
|
{"aed", {512, 356}},
|
|
{"aef", {1024, 356}},
|
|
{"aeg", {2048, 356}},
|
|
{"aeh", {4096, 356}},
|
|
{"aei", {8192, 356}},
|
|
{"aej", {16384, 356}},
|
|
{"aek", {32768, 356}},
|
|
{"ael", {65536, 356}},
|
|
{"aem", {131072, 356}},
|
|
{"aen", {262144, 356}},
|
|
{"aeo", {1, 357}},
|
|
{"aep", {2, 357}},
|
|
{"aeq", {4, 357}},
|
|
{"aer", {8, 357}},
|
|
{"aes", {16, 357}},
|
|
{"aet", {32, 357}},
|
|
{"aeu", {64, 357}},
|
|
{"aev", {128, 357}},
|
|
{"aew", {256, 357}},
|
|
{"aex", {512, 357}},
|
|
{"aey", {1024, 357}},
|
|
{"aez", {2048, 357}},
|
|
{"ae0", {4096, 357}},
|
|
{"ae1", {8192, 357}},
|
|
{"ae2", {16384, 357}},
|
|
{"ae3", {32768, 357}},
|
|
{"ae4", {65536, 357}},
|
|
{"ae5", {131072, 357}},
|
|
{"ae6", {262144, 357}},
|
|
};
|
|
|
|
// Gem/Rune Extractors
|
|
static std::unordered_map<std::string, GemType> exTypes = {
|
|
{"g25", {-1, 381}}, // Chipped Amethyst
|
|
{"g24", {-1, 383}}, // Chipped Diamond
|
|
{"ge8", {-1, 384}}, // Chipped Emerald
|
|
{"g22", {-1, 381}}, // Chipped Ruby
|
|
{"g21", {-1, 382}}, // Chipped Sapphire
|
|
{"g15", {-1, 384}}, // Chipped Skull
|
|
{"g14", {-1, 383}}, // Chipped Topaz
|
|
{"gb4", {-3, 378}}, // Flawed Amethyst
|
|
{"g12", {-3, 383}}, // Flawed Diamond
|
|
{"g11", {-3, 384}}, // Flawed Emerald
|
|
{"g30", {-3, 381}}, // Flawed Ruby
|
|
{"g29", {-3, 382}}, // Flawed Sapphire
|
|
{"g28", {-3, 384}}, // Flawed Skull
|
|
{"g27", {-3, 383}}, // Flawed Topaz
|
|
{"g10", {-9, 378}}, // Amethyst
|
|
{"ge9", {-9, 383}}, // Diamond
|
|
{"g23", {-9, 384}}, // Emerald
|
|
{"ge7", {-9, 381}}, // Ruby
|
|
{"ge6", {-9, 382}}, // Sapphire
|
|
{"g35", {-9, 384}}, // Skull
|
|
{"gb5", {-9, 383}}, // Topaz
|
|
{"g18", {-27, 378}}, // Flawless Amethyst
|
|
{"g32", {-27, 383}}, // Flawless Diamond
|
|
{"g31", {-27, 384}}, // Flawless Emerald
|
|
{"ge5", {-27, 381}}, // Flawless Ruby
|
|
{"ge4", {-27, 382}}, // Flawless Sapphire
|
|
{"g13", {-27, 384}}, // Flawless Skull
|
|
{"ge2", {-27, 383}}, // Flawless Topaz
|
|
{"ge1", {-81, 378}}, // Perfect Amethyst
|
|
{"g20", {-81, 383}}, // Perfect Diamond
|
|
{"g19", {-81, 384}}, // Perfect Emerald
|
|
{"ge3", {-81, 381}}, // Perfect Ruby
|
|
{"g17", {-81, 382}}, // Perfect Sapphire
|
|
{"g16", {-81, 384}}, // Perfect Skull
|
|
|
|
{"x01", {-1, 388}}, // El Rune
|
|
{"x02", {-3, 388}}, // Eld Rune
|
|
{"x03", {-9, 388}}, // Tir Rune
|
|
{"x04", {-27, 388}}, // Nef Rune
|
|
{"x05", {-81, 388}}, // Eth Rune
|
|
{"x06", {-243, 388}}, // Ith Rune
|
|
{"x07", {-1, 389}}, // Tal Rune
|
|
{"x08", {-3, 389}}, // Ral Rune
|
|
{"x09", {-9, 389}}, // Ort Rune
|
|
{"x10", {-27, 389}}, // Thul Rune
|
|
{"x11", {-81, 389}}, // Amn Rune
|
|
{"x12", {-243, 389}}, // Sol Rune
|
|
{"x13", {-1, 390}}, // Shael Rune
|
|
{"x14", {-3, 390}}, // Dol Rune
|
|
{"x15", {-9, 390}}, // Hel Rune
|
|
{"x16", {-27, 390}}, // Io Rune
|
|
{"x17", {-81, 390}}, // Lum Rune
|
|
{"x18", {-243, 390}}, // Ko Rune
|
|
{"x19", {-1, 391}}, // Fal Rune
|
|
{"x20", {-3, 391}}, // Lem Rune
|
|
{"x21", {-9, 391}}, // Pul Rune
|
|
{"x22", {-27, 391}}, // Um Rune
|
|
{"x23", {-81, 3901}}, // Mal Rune
|
|
{"x24", {-243, 391}}, // Ist Rune
|
|
{"x25", {-1, 392}}, // Gul Rune
|
|
{"x26", {-3, 392}}, // Vex Rune
|
|
{"x27", {-9, 392}}, // Ohm Rune
|
|
{"x28", {-27, 392}}, // Lo Rune
|
|
{"x29", {-81, 392}}, // Sur Rune
|
|
{"x30", {-243, 392}}, // Ber Rune
|
|
{"x31", {-1, 393}}, // Jah Rune
|
|
{"x32", {-2, 393}}, // Cham Rune
|
|
{"x33", {-4, 393}} // Zod Rune
|
|
};
|
|
|
|
bool isGemOrRuneCode(const char* normCode) {
|
|
// Iterate over the gemRuneCodes array and check if normCode matches any of the codes
|
|
for (const auto& code : ITEMS_gems_and_runes) {
|
|
if (strncmp(normCode, code, 3) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool isArmorOrWeaponCode(const char* normCode) {
|
|
// Iterate over the gemRuneCodes array and check if normCode matches any of the codes
|
|
for (const auto& code : ITEMS_armor_and_weapons) {
|
|
if (strncmp(normCode, code, 3) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool isStoneCode(const char* normCode) {
|
|
// Iterate over the gemRuneCodes array and check if normCode matches any of the codes
|
|
for (const auto& code : ITEMS_Stones) {
|
|
if (strncmp(normCode, code, 3) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
auto D2CLIENT_StoredTickCount1 = GetTickCount();
|
|
|
|
void sendPacketAndUpdateProperty(int gemBagGuid, uint32_t iCode, int prop, int val, int item_guid, diablo2::structures::unit* gemBag) {
|
|
// get item using item guid
|
|
|
|
if (250 < GetTickCount() - D2CLIENT_StoredTickCount1) {
|
|
D2CLIENT_StoredTickCount1 = GetTickCount();
|
|
|
|
// Create the packet
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
packet.bag_guid = gemBagGuid;
|
|
packet.updateBag = 1;
|
|
packet.iCode = iCode;
|
|
packet.prop = prop - 3;
|
|
packet.val = val;
|
|
packet.item_guid = item_guid;
|
|
packet.target_page = 99;
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
|
|
diablo2::structures::D2PropertyStrc itemProperty = {};
|
|
itemProperty.nProperty = prop - 3; // Adjust the property ID
|
|
itemProperty.nLayer = 0;
|
|
itemProperty.nMin = val;
|
|
itemProperty.nMax = val;
|
|
diablo2::d2_common::add_property(gemBag, &itemProperty, 0);
|
|
}
|
|
}
|
|
|
|
LRESULT d2_tweaks::ui::ui_manager::wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
|
static auto& instance = singleton<ui_manager>::instance();
|
|
|
|
bool block;
|
|
|
|
// Send transmute packet
|
|
if (wParam == 'X') {
|
|
diablo2::d2_client::send_to_server_7(0x4F, 0x18, 0, 0);
|
|
block = true; // block the game from processing this key
|
|
}
|
|
|
|
if (wParam == 'V') {
|
|
// Define a cooldown duration in milliseconds
|
|
constexpr int cooldownDuration = 500; // Adjust this value as needed
|
|
|
|
// Get the current time
|
|
auto currentTime = std::chrono::steady_clock::now();
|
|
|
|
// Calculate the time elapsed since the last stash toggle
|
|
auto timeElapsed = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastToggleTime).count();
|
|
|
|
// Check if enough time has elapsed since the last toggle
|
|
if (timeElapsed >= cooldownDuration) {
|
|
// Update the last toggle time
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Send item move packet + transmute packet for certain codes only for runes and gems
|
|
if (wParam == 'Z' || wParam == 'G') {
|
|
// Call the item_click function using the function pointer
|
|
const auto g_hoverItem = (*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4));
|
|
|
|
if (g_hoverItem != 0) {
|
|
char currentPage = diablo2::d2_common::get_item_page(g_hoverItem);
|
|
|
|
// Create the packet
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
packet.item_guid = g_hoverItem->guid;
|
|
|
|
if (currentPage == 0) { //item is in inventory
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH))
|
|
packet.target_page = 4;
|
|
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CUBE))
|
|
packet.target_page = 3;
|
|
}
|
|
else {
|
|
packet.target_page = 0;
|
|
}
|
|
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
}
|
|
|
|
if (g_hoverItem != 0) {
|
|
const auto record = diablo2::d2_common::get_item_record(g_hoverItem->data_record_index);
|
|
char* normCode = record->string_code;
|
|
|
|
// Iterate over the codes array and check if normCode matches any of the codes
|
|
bool found = false;
|
|
for (const auto& code : ITEMS_gems_and_runes) {
|
|
if (strncmp(normCode, code, 3) == 0) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
char currentPage = diablo2::d2_common::get_item_page(g_hoverItem);
|
|
|
|
// Create the packet
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
packet.item_guid = g_hoverItem->guid;
|
|
|
|
if (currentPage == 0) { //item is in inventory
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH))
|
|
packet.target_page = 4;
|
|
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CUBE))
|
|
packet.target_page = 3;
|
|
}
|
|
else {
|
|
packet.target_page = 0;
|
|
}
|
|
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CUBE))
|
|
diablo2::d2_client::send_to_server_7(0x4F, 0x18, 0, 0);
|
|
}
|
|
}
|
|
|
|
block = true; // block the game from processing this key
|
|
}
|
|
|
|
switch (msg) {
|
|
case WM_LBUTTONDOWN:
|
|
{
|
|
block = instance.process_left_mouse(false);
|
|
break;
|
|
}
|
|
|
|
case WM_LBUTTONUP:
|
|
{
|
|
block = instance.process_left_mouse(true);
|
|
break;
|
|
}
|
|
|
|
case WM_RBUTTONDOWN:
|
|
{
|
|
// Get the local player object from the Diablo 2 client
|
|
const auto player = diablo2::d2_client::get_local_player();
|
|
|
|
// Obtain a pointer to the player's inventory
|
|
auto pInventory = player->inventory;
|
|
|
|
// Initialize variables to store GUIDs and coordinates
|
|
int32_t gemBagGuid = 0;
|
|
int32_t harvesterGuid = 0;
|
|
int32_t boxGuid;
|
|
uint32_t boxX;
|
|
uint32_t boxY;
|
|
|
|
// Calculate the memory address of the hover item in the game
|
|
// by adding an offset to the base address of the client
|
|
const auto g_hoverItem = *reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4);
|
|
|
|
if (g_hoverItem != nullptr) {
|
|
// Obtain the item record associated with the hovered item
|
|
const auto record = diablo2::d2_common::get_item_record(g_hoverItem->data_record_index);
|
|
|
|
// Extract the string code of the item record
|
|
char* normCode = record->string_code;
|
|
|
|
// Retrieve the item type record based on the item record's type
|
|
const auto itemtype_record = diablo2::d2_common::get_item_type_record(record->type);
|
|
|
|
// Retrieve item type records corresponding to the equivalent types of the item
|
|
auto itemtype_record_equiv1 = diablo2::d2_common::get_item_type_record(itemtype_record->equiv1);
|
|
auto itemtype_record_equiv2 = diablo2::d2_common::get_item_type_record(itemtype_record->equiv2);
|
|
|
|
// Initialize a vector to store items and pointers to specific items
|
|
std::vector<diablo2::structures::unit*> items;
|
|
diablo2::structures::unit* gemBag{};
|
|
diablo2::structures::unit* box{};
|
|
diablo2::structures::unit* harvester{};
|
|
|
|
// Loop through the items in the player's inventory to find specific items
|
|
for (auto item = player->inventory->first_item; item != nullptr; item = item->item_data->pt_next_item) {
|
|
// Get the item record associated with the current item
|
|
const auto record = diablo2::d2_common::get_item_record(item->data_record_index);
|
|
|
|
// Extract the string code of the item record
|
|
char* normCode1 = record->string_code;
|
|
|
|
// Check if the current item is a gem bag (type 101)
|
|
if (record->type == 101) {
|
|
gemBag = item; // Set gemBag pointer to the current item
|
|
gemBagGuid = gemBag->guid; // Store the GUID of the gem bag
|
|
}
|
|
|
|
// Check if the current item's string code starts with "box"
|
|
if (strncmp(normCode1, "box", 3) == 0) {
|
|
box = item; // Set box pointer to the current item
|
|
boxGuid = box->guid; // Store the GUID of the box
|
|
boxX = player->path->mapx; // Store the player's X coordinate
|
|
boxY = player->path->mapy; // Store the player's Y coordinate
|
|
}
|
|
|
|
// Check if the current item's string code starts with "ib3"
|
|
if (strncmp(normCode1, "ib3", 3) == 0) {
|
|
harvester = item; // Set harvester pointer to the current item
|
|
harvesterGuid = harvester->guid; // Store the GUID of the harvester
|
|
}
|
|
}
|
|
|
|
// Comment: Explanation of the relationship between the row number in properties.txt and the structure definition
|
|
// The row number in properties.txt corresponds to the rowID property in the GemType structure, minus 3
|
|
|
|
// Obtain the current page of the hovered item
|
|
auto currentPage = diablo2::d2_common::get_item_page(g_hoverItem);
|
|
|
|
// Declare a pointer to store the string key
|
|
const char* key;
|
|
|
|
// Check if the current page is the stash or inventory, right click on gem/rune will
|
|
// add it to the cube and send it to page 99 which is non existent
|
|
// (hope it doesn't bloat save file size and actualy disappears from memory)
|
|
/*
|
|
if (currentPage == 0 || currentPage == 4) {
|
|
// Check if the stash or inventory window is open
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH) ||
|
|
diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_INVENTORY)) {
|
|
// Iterate through each gem type in the gemTypes map
|
|
for (const auto& gem : gemTypes) {
|
|
// Accessing the key and value of the gemTypes map
|
|
const std::string& _key = gem.first;
|
|
key = gem.first.c_str();
|
|
|
|
const GemType& value = gem.second;
|
|
|
|
// Check if the code of the hovered item matches the current gem type
|
|
if (strncmp(normCode, key, 3) == 0) {
|
|
// Create a D2PropertyStrc structure to represent the gem property
|
|
diablo2::structures::D2PropertyStrc itemProperty = {};
|
|
itemProperty.nProperty = value.rowID - 3; // Adjust the property ID
|
|
itemProperty.nLayer = 0;
|
|
itemProperty.nMin = value.chippedCount;
|
|
itemProperty.nMax = value.chippedCount;
|
|
|
|
// Add the gem property to the gem bag
|
|
diablo2::d2_common::add_property(gemBag, &itemProperty, 0);
|
|
|
|
// Play the drop sound associated with the hovered item
|
|
diablo2::d2_client::play_sound(record->drop_sound, nullptr, 0, 0, 0);
|
|
|
|
// Create and send a packet to the server to move the item
|
|
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);
|
|
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
|
|
// Clear the hovered item after processing
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
}
|
|
}
|
|
}
|
|
// Check if the cube window is open and the current page is 3 (gen/rune is in cube)
|
|
// move the item back to inventory
|
|
else if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CUBE) && currentPage == 3) {
|
|
// Iterate through each gem type in the gemTypes map
|
|
for (const auto& gem : gemTypes) {
|
|
// Accessing the key and value of the gemTypes map
|
|
const std::string& _key = gem.first;
|
|
key = gem.first.c_str();
|
|
|
|
const GemType& value = gem.second;
|
|
|
|
// Check if the code of the hovered item matches the current gem type
|
|
if (strncmp(normCode, key, 3) == 0) {
|
|
// Move the item to the inventory
|
|
char currentPage = diablo2::d2_common::get_item_page(g_hoverItem);
|
|
|
|
// Create and send a packet to the server to move the item to the inventory
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
packet.item_guid = g_hoverItem->guid;
|
|
packet.target_page = 0;
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
|
|
// Clear the hovered item after processing
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
}
|
|
}
|
|
}
|
|
// Check if the cube window is open and the current page is 0 (gem/rune is in inventory)
|
|
// on right click add it to the gembag and send the original gem/rune to page 99
|
|
else if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CUBE) && currentPage == 0) {
|
|
// Iterate through each gem type in the gemTypes map
|
|
for (const auto& gem : gemTypes) {
|
|
// Accessing the key and value of the gemTypes map
|
|
const std::string& _key = gem.first;
|
|
key = gem.first.c_str();
|
|
|
|
const GemType& value = gem.second;
|
|
|
|
// Check if the code of the hovered item matches the current gem type
|
|
if (strncmp(normCode, key, 3) == 0) {
|
|
// Create a D2PropertyStrc structure to represent the gem property
|
|
diablo2::structures::D2PropertyStrc itemProperty = {};
|
|
itemProperty.nProperty = value.rowID - 3; // Adjust the property ID
|
|
itemProperty.nLayer = 0;
|
|
itemProperty.nMin = value.chippedCount;
|
|
itemProperty.nMax = value.chippedCount;
|
|
|
|
// Add the gem property to the gem bag
|
|
diablo2::d2_common::add_property(gemBag, &itemProperty, 0);
|
|
|
|
// Play the drop sound associated with the hovered item
|
|
diablo2::d2_client::play_sound(record->drop_sound, nullptr, 0, 0, 0);
|
|
|
|
// Create and send a packet to the server to move the item
|
|
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);
|
|
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
|
|
// Clear the hovered item after processing
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// For gem/rune extractors, on right click, move the bag and extractor to the cube, send transmute packet
|
|
// Check if the current page is the inventory, cube, or stash
|
|
if (currentPage == 0 || currentPage == 3 || currentPage == 4) {
|
|
// Check if the stash, cube, or inventory window is open
|
|
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)) {
|
|
// Iterate through each gem type in the exTypes map
|
|
for (const auto& gem : exTypes) {
|
|
// Accessing the key and value of the exTypes map
|
|
const std::string& _key = gem.first;
|
|
key = gem.first.c_str();
|
|
|
|
const GemType& value = gem.second;
|
|
|
|
// Check if the code of the hovered item matches the current gem type
|
|
if (strncmp(normCode, key, 3) == 0) {
|
|
// Open the cube
|
|
struct D2GSPacketClt20 {
|
|
uint8_t PacketId; // Packet identifier
|
|
uint32_t guid; // GUID of the cube item
|
|
uint32_t tx; // X-coordinate of the cube's location
|
|
uint32_t ty; // Y-coordinate of the cube's location
|
|
};
|
|
D2GSPacketClt20 D2GSPacketClt20;
|
|
D2GSPacketClt20.PacketId = 0x20; // Packet ID for cube opening
|
|
D2GSPacketClt20.guid = boxGuid; // GUID of the cube item
|
|
D2GSPacketClt20.tx = player->path->mapx; // X-coordinate of the player's location
|
|
D2GSPacketClt20.ty = player->path->mapy; // Y-coordinate of the player's location
|
|
diablo2::d2_client::send_to_server(&D2GSPacketClt20, sizeof D2GSPacketClt20);
|
|
|
|
// Wait for 100 milliseconds for the cube to open
|
|
Sleep(100);
|
|
|
|
// Get the current page of the hovered item
|
|
char currentPage = diablo2::d2_common::get_item_page(g_hoverItem);
|
|
|
|
// Create a packet to move the hovered item to the cube
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
packet.item_guid = g_hoverItem->guid;
|
|
packet.target_page = 3; // Target page for the cube
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
|
|
// Create a packet to move the gem bag to the cube
|
|
static d2_tweaks::common::item_move_cs packetBag;
|
|
packetBag.item_guid = gemBag->guid;
|
|
packetBag.target_page = 3; // Target page for the cube
|
|
diablo2::d2_client::send_to_server(&packetBag, sizeof packetBag);
|
|
|
|
// Send a packet to activate the transmute button in the cube
|
|
diablo2::d2_client::send_to_server_7(0x4F, 0x18, 0, 0);
|
|
|
|
// Clear the hovered item after processing
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Move gems/runes from the cube to the inventory
|
|
if (isGemOrRuneCode(normCode)) {
|
|
// Get the local player object
|
|
const auto player = diablo2::d2_client::get_local_player();
|
|
|
|
// Loop through the items in the player's inventory
|
|
for (auto item = player->inventory->first_item; item != nullptr; item = item->item_data->pt_next_item) {
|
|
// Get the current page of the item
|
|
currentPage = diablo2::d2_common::get_item_page(item);
|
|
|
|
// Check if the item is in the cube (page 3)
|
|
if (currentPage == 3) {
|
|
// Get the item record associated with the item
|
|
const auto record = diablo2::d2_common::get_item_record(item->data_record_index);
|
|
char* normCode = record->string_code;
|
|
|
|
// If the item code starts with "ib1", skip sending the item back to inventory
|
|
if (strncmp(normCode, "ib1", 3) == 0) {
|
|
continue; // Skip to the next iteration of the loop
|
|
}
|
|
else {
|
|
// Create a packet to move the item from the cube to the inventory
|
|
static d2_tweaks::common::item_move_cs movePacket;
|
|
movePacket.item_guid = item->guid;
|
|
movePacket.target_page = 0; // Move to inventory
|
|
diablo2::d2_client::send_to_server(&movePacket, sizeof movePacket);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// For armor and weapon codes, right click will move the item to the stash or cube and transmute
|
|
if (isArmorOrWeaponCode(normCode)
|
|
|| record->type == 61 - 3 // jewel
|
|
|| record->type == 43 - 3 // key
|
|
|| record->type == 109
|
|
|| record->type == 111
|
|
|| record->type == 112
|
|
|| record->type == 113
|
|
|| record->type == 120
|
|
|| record->type == 113
|
|
|| record->type == 122
|
|
|| record->type == 123
|
|
|| record->type == 123 - 3 // sum0
|
|
|| record->type == 125
|
|
|| record->type == 126 - 3
|
|
|| record->type == 128 - 3
|
|
|| record->type == 4 - 3
|
|
|| record->type == 5 - 3
|
|
|| record->type == 17 - 3
|
|
|| record->type == 18 - 3
|
|
|| record->type == 21 - 3
|
|
|| record->type == 26 - 3
|
|
|| record->type == 27 - 3
|
|
|| record->type == 28 - 3
|
|
|| record->type == 29 - 3
|
|
|| record->type == 30 - 3
|
|
|| record->type == 31 - 3
|
|
|| record->type == 32 - 3) {
|
|
// Create a packet to move an item
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
|
|
// Set the GUID of the item to be moved
|
|
packet.item_guid = g_hoverItem->guid;
|
|
|
|
// Check if the item is currently in the inventory (page 0)
|
|
if (currentPage == 0) {
|
|
// If the inventory is open and stash is open, set target page to stash (page 4)
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH))
|
|
packet.target_page = 4;
|
|
|
|
// If the inventory is open and cube is open, set target page to cube (page 3)
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CUBE))
|
|
packet.target_page = 3;
|
|
}
|
|
// If the item is not in the inventory, set target page to inventory (page 0)
|
|
else {
|
|
packet.target_page = 0;
|
|
}
|
|
|
|
// Send the item move packet to the server
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
|
|
// Send a packet to activate the transmute button in the cube
|
|
// diablo2::d2_client::send_to_server_7(0x4F, 0x18, 0, 0);
|
|
|
|
// Clear the hovered item after processing
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
}
|
|
|
|
if (strncmp(normCode, "ib1", 3) == 0) {
|
|
// we need to get instance of loot_filter_settings_menu class singleton
|
|
auto& toggle_menu = singleton<d2_tweaks::client::modules::loot_filter_settings_toggle_menu>::instance();
|
|
|
|
toggle_menu.m_show = !toggle_menu.m_show;
|
|
|
|
m_stats_enabled = !m_stats_enabled;
|
|
|
|
toggle_menu.m_filter_settings_menu->set_enabled(toggle_menu.m_show);
|
|
toggle_menu.m_filter_settings_menu->set_visible(toggle_menu.m_show);
|
|
}
|
|
|
|
|
|
if (strncmp(normCode, "r01", 3) == 0) {
|
|
auto localPlayer = diablo2::d2_client::get_local_player();
|
|
diablo2::structures::path* playerPath = localPlayer->path;
|
|
//diablo2::structures::room* pRoom = playerPath->pt_room;
|
|
//diablo2::structures::game* pGame = player->game;
|
|
//struct D2UnkMonCreateStrc
|
|
//{
|
|
// diablo2::structures::game* pGame; //0x00
|
|
// diablo2::structures::room* pRoom; //0x04
|
|
// DWORD pRoomCoordList; //0x08
|
|
// int32_t nMonsterId; //0x0C
|
|
// int32_t nAnimMode; //0x10
|
|
// int32_t nUnitGUID; //0x14
|
|
// int32_t nX; //0x18
|
|
// int32_t nY; //0x1C
|
|
// int32_t field_20; //0x20
|
|
// int16_t nFlags; //0x24
|
|
//};
|
|
//auto nX = playerPath->mapx + 50;
|
|
//auto nY = playerPath->mapy + 50;
|
|
////auto nMonsterId = 1272;
|
|
////int32_t nMode = 1;
|
|
////auto rubyGolem = diablo2::d2_game::D2GAME_SpawnMonster_6FC69F10(pGame, pRoom, nX, nY, nMonsterId, nMode, -1, 0);
|
|
|
|
//// Create a packet to move an item
|
|
//static d2_tweaks::common::item_move_cs packet;
|
|
//packet.item_guid = g_hoverItem->guid;
|
|
//packet.item_code = normCode;
|
|
//packet.target_page = 99;
|
|
//packet.summon = 1;
|
|
//packet.x = nX;
|
|
//packet.y = nY;
|
|
//diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
//diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
|
|
//// Clear the hovered item after processing
|
|
//(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
block = instance.process_right_mouse(false);
|
|
break;
|
|
}
|
|
|
|
case WM_RBUTTONUP:
|
|
{
|
|
block = instance.process_right_mouse(true);
|
|
break;
|
|
}
|
|
|
|
// Handle the WM_MOUSEWHEEL message
|
|
case WM_MOUSEWHEEL:
|
|
{
|
|
// Extract the distance the wheel is rotated from the message
|
|
short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
|
|
|
|
// Check if the wheel is scrolled upwards
|
|
if (zDelta > 0) {
|
|
// Process the mouse wheel input by scrolling upwards
|
|
|
|
// Calculate the memory address of the hover item in the game
|
|
// by adding an offset to the base address of the client
|
|
const auto g_hoverItem = *reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4);
|
|
|
|
// Get the local player object from the Diablo 2 client
|
|
const auto player = diablo2::d2_client::get_local_player();
|
|
|
|
// Obtain a pointer to the player's inventory
|
|
auto pInventory = player->inventory;
|
|
|
|
if (g_hoverItem != nullptr) {
|
|
// Obtain the item record associated with the hovered item
|
|
const auto record = diablo2::d2_common::get_item_record(g_hoverItem->data_record_index);
|
|
|
|
// Extract the string code of the item record
|
|
char* normCode = record->string_code;
|
|
|
|
// Create the packet
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
packet.item_guid = g_hoverItem->guid;
|
|
packet.target_page = 0;
|
|
packet.tmog = 1;
|
|
packet.item_code = normCode;
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
}
|
|
block = instance.process_mouse_wheel(true);
|
|
}
|
|
// Check if the wheel is scrolled downwards
|
|
else if (zDelta < 0) {
|
|
// Process the mouse wheel input by scrolling downwards
|
|
|
|
// Calculate the memory address of the hover item in the game
|
|
// by adding an offset to the base address of the client
|
|
const auto g_hoverItem = *reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4);
|
|
|
|
// Get the local player object from the Diablo 2 client
|
|
const auto player = diablo2::d2_client::get_local_player();
|
|
|
|
// Obtain a pointer to the player's inventory
|
|
auto pInventory = player->inventory;
|
|
|
|
if (g_hoverItem != nullptr) {
|
|
// Obtain the item record associated with the hovered item
|
|
const auto record = diablo2::d2_common::get_item_record(g_hoverItem->data_record_index);
|
|
|
|
// Extract the string code of the item record
|
|
char* normCode = record->string_code;
|
|
|
|
// Create the packet
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
packet.item_guid = g_hoverItem->guid;
|
|
packet.target_page = 0;
|
|
packet.tmog = 1;
|
|
packet.item_code = normCode;
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
}
|
|
block = instance.process_mouse_wheel(true);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_MBUTTONUP:
|
|
{
|
|
block = instance.process_middle_mouse(true);
|
|
break;
|
|
}
|
|
|
|
case WM_MBUTTONDOWN:
|
|
{
|
|
// Define a cooldown duration in milliseconds
|
|
constexpr int cooldownDuration = 500; // Adjust this value as needed
|
|
|
|
// Get the current time
|
|
auto currentTime = std::chrono::steady_clock::now();
|
|
|
|
// Calculate the time elapsed since the last stash toggle
|
|
auto timeElapsed = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastToggleTime).count();
|
|
|
|
// Get the local player object from the Diablo 2 client
|
|
const auto player = diablo2::d2_client::get_local_player();
|
|
|
|
// Obtain a pointer to the player's inventory
|
|
auto pInventory = player->inventory;
|
|
|
|
// Initialize variables to store GUIDs and coordinates
|
|
int32_t gemBagGuid = 0;
|
|
int32_t harvesterGuid = 0;
|
|
int32_t boxGuid;
|
|
uint32_t boxX;
|
|
uint32_t boxY;
|
|
|
|
// Calculate the memory address of the hover item in the game
|
|
// by adding an offset to the base address of the client
|
|
const auto g_hoverItem = *reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4);
|
|
|
|
if (g_hoverItem != nullptr) {
|
|
// Obtain the item record associated with the hovered item
|
|
const auto record = diablo2::d2_common::get_item_record(g_hoverItem->data_record_index);
|
|
|
|
// Extract the string code of the item record
|
|
char* normCode = record->string_code;
|
|
|
|
// Retrieve the item type record based on the item record's type
|
|
const auto itemtype_record = diablo2::d2_common::get_item_type_record(record->type);
|
|
|
|
// Retrieve item type records corresponding to the equivalent types of the item
|
|
auto itemtype_record_equiv1 = diablo2::d2_common::get_item_type_record(itemtype_record->equiv1);
|
|
auto itemtype_record_equiv2 = diablo2::d2_common::get_item_type_record(itemtype_record->equiv2);
|
|
|
|
// Initialize a vector to store items and pointers to specific items
|
|
std::vector<diablo2::structures::unit*> items;
|
|
diablo2::structures::unit* gemBag{};
|
|
diablo2::structures::unit* box{};
|
|
diablo2::structures::unit* harvester{};
|
|
|
|
// get the gembag 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);
|
|
char* normCode1 = record->string_code;
|
|
if (record->type == 101) {
|
|
gemBag = item;
|
|
gemBagGuid = gemBag->guid;
|
|
}
|
|
if (strncmp(normCode1, "box", 3) == 0) {
|
|
box = item;
|
|
boxGuid = box->guid;
|
|
boxX = player->path->mapx;
|
|
boxY = player->path->mapy;
|
|
}
|
|
if (strncmp(normCode1, "ib3", 3) == 0) {
|
|
harvester = item;
|
|
harvesterGuid = harvester->guid;
|
|
}
|
|
}
|
|
|
|
if (strncmp(normCode, "rvs", 3) == 0) {
|
|
// Create the packet
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'rvs ', 396, 1000, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
if (strncmp(normCode, "rvl", 3) == 0) {
|
|
// Create the packet
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'rvl ', 396, 3000, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "hp1", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'hp1 ', 397, 1, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "mp1", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'mp1 ', 398, 1, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "hp2", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'hp2 ', 397, 3, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "mp2", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'mp2 ', 398, 3, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "hp3", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'hp3 ', 397, 9, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "mp3", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'mp3 ', 398, 9, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "hp4", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'hp4 ', 397, 27, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "mp4", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'mp4 ', 398, 27, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "hp5", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'hp5 ', 397, 81, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "mp5", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'mp5 ', 398, 81, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
// add if block for the following codes: vps, yps, wms, frp, lrp, crp, prp, mrp
|
|
if (strncmp(normCode, "vps", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'vps ', 396, 5, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "yps", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'yps ', 396, 10, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "wms", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'wms ', 396, 15, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "frp", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'frp ', 396, 50, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "lrp", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'lrp ', 396, 50, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "crp", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'crp ', 396, 50, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "prp", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'prp ', 396, 50, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
if (strncmp(normCode, "mrp", 3) == 0) {
|
|
sendPacketAndUpdateProperty(gemBagGuid, 'mrp ', 396, 50, g_hoverItem->guid, gemBag);
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
}
|
|
|
|
|
|
const char* key;
|
|
// Iterate through each gem type in the gemTypes map
|
|
for (const auto& gem : gemTypes) {
|
|
// Accessing the key and value of the gemTypes map
|
|
const std::string& _key = gem.first;
|
|
key = gem.first.c_str();
|
|
|
|
const GemType& value = gem.second;
|
|
|
|
// Check if the code of the hovered item matches the current gem type
|
|
if (strncmp(normCode, key, 3) == 0) {
|
|
// Create a D2PropertyStrc structure to represent the gem property
|
|
diablo2::structures::D2PropertyStrc itemProperty = {};
|
|
itemProperty.nProperty = value.rowID - 3; // Adjust the property ID
|
|
itemProperty.nLayer = 0;
|
|
itemProperty.nMin = value.chippedCount;
|
|
itemProperty.nMax = value.chippedCount;
|
|
|
|
// Add the gem property to the gem bag
|
|
diablo2::d2_common::add_property(gemBag, &itemProperty, 0);
|
|
|
|
// Play the drop sound associated with the hovered item
|
|
diablo2::d2_client::play_sound(record->drop_sound, nullptr, 0, 0, 0);
|
|
|
|
// Create and send a packet to the server to move the item
|
|
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);
|
|
|
|
diablo2::d2_common::inv_remove_item(player->inventory, g_hoverItem);
|
|
|
|
// Clear the hovered item after processing
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
}
|
|
}
|
|
|
|
if (isArmorOrWeaponCode(normCode)
|
|
|| record->type == 61 - 3 // jewel
|
|
|| record->type == 43 - 3 // key
|
|
|| record->type == 109
|
|
|| record->type == 111
|
|
|| record->type == 112
|
|
|| record->type == 113
|
|
|| record->type == 120
|
|
|| record->type == 113
|
|
|| record->type == 122
|
|
|| record->type == 123
|
|
|| record->type == 123 - 3 // sum0
|
|
|| record->type == 125
|
|
|| record->type == 126 - 3
|
|
|| record->type == 128 - 3
|
|
|| record->type == 4 - 3
|
|
|| record->type == 5 - 3
|
|
|| record->type == 17 - 3
|
|
|| record->type == 18 - 3
|
|
|| record->type == 21 - 3
|
|
|| record->type == 26 - 3
|
|
|| record->type == 27 - 3
|
|
|| record->type == 28 - 3
|
|
|| record->type == 29 - 3
|
|
|| record->type == 30 - 3
|
|
|| record->type == 31 - 3
|
|
|| record->type == 32 - 3) {
|
|
char currentPage;
|
|
|
|
// open the cube
|
|
struct D2GSPacketClt20 {
|
|
uint8_t PacketId; // 0x01
|
|
uint32_t guid; // 0x06
|
|
uint32_t tx; // 0x07
|
|
uint32_t ty; // 0x09
|
|
};
|
|
D2GSPacketClt20 D2GSPacketClt20;
|
|
D2GSPacketClt20.PacketId = 0x20;
|
|
D2GSPacketClt20.guid = boxGuid;
|
|
D2GSPacketClt20.tx = player->path->mapx;
|
|
D2GSPacketClt20.ty = player->path->mapy;
|
|
diablo2::d2_client::send_to_server(&D2GSPacketClt20, sizeof D2GSPacketClt20);
|
|
|
|
Sleep(100);
|
|
|
|
// Check if enough time has elapsed since the last toggle
|
|
if (timeElapsed >= cooldownDuration) {
|
|
// Update the last toggle time
|
|
lastToggleTime = currentTime;
|
|
|
|
// now move the harvester guid to the cube
|
|
// Create the packet
|
|
static d2_tweaks::common::item_move_cs hpacket;
|
|
hpacket.item_guid = harvesterGuid;
|
|
hpacket.target_page = 3;
|
|
diablo2::d2_client::send_to_server(&hpacket, sizeof hpacket);
|
|
|
|
currentPage = diablo2::d2_common::get_item_page(g_hoverItem);
|
|
// Create the packet
|
|
static d2_tweaks::common::item_move_cs packet;
|
|
packet.item_guid = g_hoverItem->guid;
|
|
if (currentPage == 0) { //item is in inventory
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_STASH))
|
|
packet.target_page = 4;
|
|
if (diablo2::d2_client::get_ui_window_state(diablo2::UI_WINDOW_CUBE))
|
|
packet.target_page = 3;
|
|
}
|
|
else {
|
|
packet.target_page = 0;
|
|
}
|
|
diablo2::d2_client::send_to_server(&packet, sizeof packet);
|
|
|
|
diablo2::d2_client::send_to_server_7(0x4F, 0x18, 0, 0);
|
|
|
|
// now move the harvester back to the inv
|
|
//static d2_tweaks::common::item_move_cs h1packet;
|
|
//h1packet.item_guid = harvesterGuid;
|
|
//h1packet.target_page = 0;
|
|
//diablo2::d2_client::send_to_server(&h1packet, sizeof h1packet);
|
|
|
|
(*reinterpret_cast<diablo2::structures::unit**>(diablo2::d2_client::get_base() + 0x1158F4)) = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
block = instance.process_middle_mouse(false);
|
|
break;
|
|
}
|
|
|
|
// Handling Windows messages related to key presses and releases.
|
|
// These cases deal with key down and key up events.
|
|
|
|
// When a system key down or key down message is received,
|
|
case WM_SYSKEYDOWN:
|
|
case WM_KEYDOWN:
|
|
{
|
|
// Call the process_key_event function to handle the key down event.
|
|
// Pass wParam (the virtual-key code) and false (indicating it's a key down event) as parameters.
|
|
block = instance.process_key_event(wParam, false);
|
|
break;
|
|
}
|
|
|
|
// When a system key up or key up message is received,
|
|
case WM_SYSKEYUP:
|
|
case WM_KEYUP:
|
|
{
|
|
// Call the process_key_event function to handle the key up event.
|
|
// Pass wParam (the virtual-key code) and true (indicating it's a key up event) as parameters.
|
|
block = instance.process_key_event(wParam, true);
|
|
break;
|
|
}
|
|
|
|
// If the message is not related to key events, return the original window procedure.
|
|
default:
|
|
// Call the original window procedure to handle the message.
|
|
// Pass the window handle (hWnd), the message (msg), wParam, and lParam.
|
|
return g_wnd_proc_original(hWnd, msg, wParam, lParam);
|
|
}
|
|
|
|
if (block)
|
|
return 0;
|
|
|
|
return g_wnd_proc_original(hWnd, msg, wParam, lParam);
|
|
}
|
|
// This function, belonging to the 'ui_manager' class within the 'ui' namespace of the 'd2_tweaks' namespace, is responsible for processing user inputs.
|
|
void d2_tweaks::ui::ui_manager::process_inputs() {
|
|
// Check if the left mouse button is pressed asynchronously.
|
|
if (GetAsyncKeyState(VK_LBUTTON)) {
|
|
// If the left mouse button was not previously pressed (indicating a new press event),
|
|
if (!m_was_down_before_left) {
|
|
// Set the flag indicating that the left mouse button was pressed before.
|
|
m_was_down_before_left = true;
|
|
// Set the state of the left mouse button to true (pressed).
|
|
m_mouse_state_left = true;
|
|
|
|
// Call the function to process the left mouse button event with the parameter indicating whether it's an up event (false for down event).
|
|
process_left_mouse(false);
|
|
}
|
|
}
|
|
// If the left mouse button is not currently pressed,
|
|
else if (m_was_down_before_left) {
|
|
// Reset the flag indicating that the left mouse button was pressed before.
|
|
m_was_down_before_left = false;
|
|
// Set the state of the left mouse button to false (not pressed).
|
|
m_mouse_state_left = false;
|
|
|
|
// Call the function to process the left mouse button event with the parameter indicating it's an up event (true for up event).
|
|
process_left_mouse(true);
|
|
}
|
|
|
|
// Check if the right mouse button is pressed asynchronously.
|
|
if (GetAsyncKeyState(VK_RBUTTON)) {
|
|
// If the right mouse button was not previously pressed (indicating a new press event),
|
|
if (!m_was_down_before_right) {
|
|
// Set the flag indicating that the right mouse button was pressed before.
|
|
m_was_down_before_right = true;
|
|
// Set the state of the right mouse button to true (pressed).
|
|
m_mouse_state_right = true;
|
|
|
|
// Call the function to process the right mouse button event with the parameter indicating whether it's an up event (false for down event).
|
|
process_right_mouse(false);
|
|
}
|
|
}
|
|
// If the right mouse button is not currently pressed,
|
|
else if (m_was_down_before_right) {
|
|
// Reset the flag indicating that the right mouse button was pressed before.
|
|
m_was_down_before_right = false;
|
|
// Set the state of the right mouse button to false (not pressed).
|
|
m_mouse_state_right = false;
|
|
|
|
// Call the function to process the right mouse button event with the parameter indicating it's an up event (true for up event).
|
|
process_right_mouse(true);
|
|
}
|
|
}
|
|
|
|
// This function processes the left mouse button event, either up or down.
|
|
bool d2_tweaks::ui::ui_manager::process_left_mouse(bool up) {
|
|
// Initialize a flag to determine if the event was handled or not.
|
|
auto block = false;
|
|
|
|
// Iterate through all menus in the list of menus.
|
|
for (auto menu : m_menus) {
|
|
// If the menu is not enabled, skip to the next one.
|
|
if (!menu->get_enabled())
|
|
continue;
|
|
|
|
// Call the left mouse button event handler of the current menu and update the block flag.
|
|
block |= menu->left_mouse(up);
|
|
}
|
|
|
|
// Return the final block flag indicating whether the event was handled or not.
|
|
return block;
|
|
}
|
|
|
|
// Similar to the previous function, this one processes the middle mouse button event.
|
|
bool d2_tweaks::ui::ui_manager::process_middle_mouse(bool up) {
|
|
auto block = false;
|
|
|
|
for (auto menu : m_menus) {
|
|
if (!menu->get_enabled())
|
|
continue;
|
|
|
|
block |= menu->middle_mouse(up);
|
|
}
|
|
|
|
return block;
|
|
}
|
|
|
|
// This function processes the mouse wheel event.
|
|
bool d2_tweaks::ui::ui_manager::process_mouse_wheel(bool up) {
|
|
auto block = false;
|
|
|
|
for (auto menu : m_menus) {
|
|
if (!menu->get_enabled())
|
|
continue;
|
|
|
|
block |= menu->mouse_wheel(up);
|
|
}
|
|
|
|
return block;
|
|
}
|
|
|
|
// This function processes the right mouse button event, either up or down.
|
|
bool d2_tweaks::ui::ui_manager::process_right_mouse(bool up) {
|
|
auto block = false;
|
|
|
|
for (auto menu : m_menus) {
|
|
if (!menu->get_enabled())
|
|
continue;
|
|
|
|
block |= menu->right_mouse(up);
|
|
}
|
|
|
|
return block;
|
|
}
|
|
|
|
// This function processes key events (e.g., keyboard keys pressed or released).
|
|
bool d2_tweaks::ui::ui_manager::process_key_event(uint32_t key, bool up) {
|
|
auto block = false;
|
|
|
|
for (auto menu : m_menus) {
|
|
if (!menu->get_enabled())
|
|
continue;
|
|
|
|
block |= menu->key_event(key, up);
|
|
}
|
|
|
|
return block;
|
|
}
|
|
|
|
#pragma pack(pop) |