mirror of
https://gitlab.com/hashborgir/plugy.git
synced 2025-04-28 07:15:37 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e89cfad117 | ||
|
f3b0abf9ab | ||
|
9a858693c5 | ||
|
6bef4f86c8 | ||
|
3b06e3ad08 | ||
|
8a3841f49b | ||
|
64792db947 | ||
|
e9fe6cb433 | ||
|
a1e3cac784 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -38,3 +38,5 @@
|
|||||||
**/*.VC.VC.opendb
|
**/*.VC.VC.opendb
|
||||||
**/UpgradeLog*
|
**/UpgradeLog*
|
||||||
/PlugYRun/PlugYRun.aps
|
/PlugYRun/PlugYRun.aps
|
||||||
|
PlugY/Debug/
|
||||||
|
|
||||||
|
286
ASLR_fix.patch
Normal file
286
ASLR_fix.patch
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
diff --git a/PlugY/D2wrapper.cpp b/PlugY/D2wrapper.cpp
|
||||||
|
index d13608e..ffd02f2 100644
|
||||||
|
--- a/PlugY/D2wrapper.cpp
|
||||||
|
+++ b/PlugY/D2wrapper.cpp
|
||||||
|
@@ -291,6 +291,7 @@ void loadCustomLibraries()
|
||||||
|
log_msg("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
void loadLibrary(LPCSTR libName, int* libVersion, DWORD* libOffset, int shift, DWORD v109b, DWORD v109d, DWORD v110, DWORD v111, DWORD v111b, DWORD v112, DWORD v113c)
|
||||||
|
{
|
||||||
|
*libOffset = (DWORD)LoadLibrary(libName);
|
||||||
|
@@ -386,6 +387,273 @@ void initD2modules()
|
||||||
|
|
||||||
|
log_msg("\n\n");
|
||||||
|
}
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+IMAGE_NT_HEADERS* GetHeader(LPBYTE pBase) {
|
||||||
|
+ if (pBase == NULL)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pBase;
|
||||||
|
+
|
||||||
|
+ if (IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ IMAGE_NT_HEADERS* pHeader = (IMAGE_NT_HEADERS*)(pBase + pDosHeader->e_lfanew);
|
||||||
|
+ if (IsBadReadPtr(pHeader, sizeof(IMAGE_NT_HEADERS)))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ if (pHeader->Signature != IMAGE_NT_SIGNATURE)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ return pHeader;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void initD2modules()
|
||||||
|
+{
|
||||||
|
+ log_msg("***** Get D2 Modules address and version *****\n\n");
|
||||||
|
+
|
||||||
|
+ offset_D2Client = (DWORD)LoadLibrary("D2Client.dll");
|
||||||
|
+ offset_D2CMP = (DWORD)LoadLibrary("D2CMP.dll");
|
||||||
|
+ offset_D2Common = (DWORD)LoadLibrary("D2Common.dll");
|
||||||
|
+ offset_D2Game = (DWORD)LoadLibrary("D2Game.dll");
|
||||||
|
+ offset_D2gfx = (DWORD)LoadLibrary("D2gfx.dll");
|
||||||
|
+ offset_D2Lang = (DWORD)LoadLibrary("D2Lang.dll");
|
||||||
|
+ offset_D2Launch = (DWORD)LoadLibrary("D2Launch.dll");
|
||||||
|
+ offset_D2Net = (DWORD)LoadLibrary("D2Net.dll");
|
||||||
|
+ offset_D2Win = (DWORD)LoadLibrary("D2Win.dll");
|
||||||
|
+ offset_Fog = (DWORD)LoadLibrary("Fog.dll");
|
||||||
|
+ offset_Storm = (DWORD)LoadLibrary("Storm.dll");
|
||||||
|
+
|
||||||
|
+ int count_109b = 0;
|
||||||
|
+ int count_109d = 0;
|
||||||
|
+ int count_110f = 0;
|
||||||
|
+ int count_111 = 0;
|
||||||
|
+ int count_111b = 0;
|
||||||
|
+ int count_112a = 0;
|
||||||
|
+ int count_113c = 0;
|
||||||
|
+ int count_113d = 0;
|
||||||
|
+ int count_114a = 0;
|
||||||
|
+ int count_114b = 0;
|
||||||
|
+ int count_114c = 0;
|
||||||
|
+ int count_114d = 0;
|
||||||
|
+
|
||||||
|
+ IMAGE_NT_HEADERS* pHeader;
|
||||||
|
+
|
||||||
|
+ if (offset_D2Client != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2Client);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C234D) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C16CD) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C1C1D) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045E6) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045EE) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045FA) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045F6) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045DE) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_D2CMP != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2CMP);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00011361) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00011361) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00010E61) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_D2Common != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2Common);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00074D1D) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00074E2D) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000856DD) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C94) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C8D) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C97) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C8F) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000047C7) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_D2Game != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2Game);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C66AC) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C6D5C) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000EDC2C) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000036E6) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000373D) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000374B) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000373C) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003747) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_D2gfx != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2gfx);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000054EB) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000054EB) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000054A5) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_D2Lang != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2Lang);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00005148) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00005138) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00005048) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A6A) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A5B) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A75) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A71) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A5A) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_D2Launch != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2Launch);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000172C3) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00017243) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00018DC7) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A84) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A85) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A85) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A87) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A84) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_D2Net != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2Net);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002BCE) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002BCE) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C6E) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001676) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001676) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000167E) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001676) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000167E) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_D2Win != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_D2Win);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00014F38) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00014F38) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00012EC0) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000187E) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000187E) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000188E) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000187E) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001887) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_Fog != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_Fog);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00013658) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000142E7) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000162B0) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003159) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003142) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000314A) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003162) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003142) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (offset_Storm != NULL) {
|
||||||
|
+ pHeader = GetHeader((LPBYTE)offset_Storm);
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00013658) count_109b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000142E7) count_109d++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000162B0) count_110f++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003159) count_111++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003142) count_111b++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000314A) count_112a++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003162) count_113c++;
|
||||||
|
+ if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0003C3E0) count_113d++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ int minimum_match_dll = 7;
|
||||||
|
+
|
||||||
|
+ if (count_109b >= minimum_match_dll) version_Game = V109b;
|
||||||
|
+ if (count_109d >= minimum_match_dll) version_Game = V109d;
|
||||||
|
+ if (count_110f >= minimum_match_dll) version_Game = V110;
|
||||||
|
+ if (count_111 >= minimum_match_dll) version_Game = V111;
|
||||||
|
+ if (count_111b >= minimum_match_dll) version_Game = V111b;
|
||||||
|
+ if (count_112a >= minimum_match_dll) version_Game = V112;
|
||||||
|
+ if (count_113c >= minimum_match_dll) version_Game = V113c;
|
||||||
|
+ if (count_113d >= minimum_match_dll) version_Game = V113d;
|
||||||
|
+
|
||||||
|
+ //version_SmackW32 = version_Game;
|
||||||
|
+ version_D2Common = version_Game;
|
||||||
|
+ //version_ijl11 = version_Game;
|
||||||
|
+ //version_D2Gdi = version_Game;
|
||||||
|
+ version_D2Win = version_Game;
|
||||||
|
+ //version_D2sound = version_Game;
|
||||||
|
+ //version_D2MCPCLI = version_Game;
|
||||||
|
+ version_D2Launch = version_Game;
|
||||||
|
+ version_D2gfx = version_Game;
|
||||||
|
+ version_D2Client = version_Game;
|
||||||
|
+ version_D2Net = version_Game;
|
||||||
|
+ version_D2Lang = version_Game;
|
||||||
|
+ version_D2Game = version_Game;
|
||||||
|
+ version_D2CMP = version_Game;
|
||||||
|
+ //version_Bnclient = version;
|
||||||
|
+ version_Fog = version_Game;
|
||||||
|
+ version_Storm = version_Game;
|
||||||
|
+
|
||||||
|
+ log_msg("DLL match for version 1.09b :\t%d\n", count_109b);
|
||||||
|
+ log_msg("DLL match for version 1.09d :\t%d\n", count_109d);
|
||||||
|
+ log_msg("DLL match for version 1.10f :\t%d\n", count_110f);
|
||||||
|
+ log_msg("DLL match for version 1.11 :\t%d\n", count_111);
|
||||||
|
+ log_msg("DLL match for version 1.11b :\t%d\n", count_111b);
|
||||||
|
+ log_msg("DLL match for version 1.12a :\t%d\n", count_112a);
|
||||||
|
+ log_msg("DLL match for version 1.13c :\t%d\n", count_113c);
|
||||||
|
+ log_msg("\n");
|
||||||
|
+
|
||||||
|
+ offset_Game = (DWORD)GetModuleHandle("Game.exe");
|
||||||
|
+ if (offset_Game != NULL) {
|
||||||
|
+ version_Game = GetD2Version((HMODULE)offset_Game);
|
||||||
|
+ log_msg("Game.exe loaded at:\t%08X (%s)\n", offset_Game, GetVersionString(version_Game));
|
||||||
|
+ if (version_Game >= V114a)
|
||||||
|
+ {
|
||||||
|
+ //version_SmackW32 = version_Game;
|
||||||
|
+ version_D2Common = version_Game;
|
||||||
|
+ //version_ijl11 = version_Game;
|
||||||
|
+ //version_D2Gdi = version_Game;
|
||||||
|
+ version_D2Win = version_Game;
|
||||||
|
+ //version_D2sound = version_Game;
|
||||||
|
+ //version_D2MCPCLI = version_Game;
|
||||||
|
+ version_D2Launch = version_Game;
|
||||||
|
+ version_D2gfx = version_Game;
|
||||||
|
+ version_D2Client = version_Game;
|
||||||
|
+ version_D2Net = version_Game;
|
||||||
|
+ version_D2Lang = version_Game;
|
||||||
|
+ version_D2Game = version_Game;
|
||||||
|
+ version_D2CMP = version_Game;
|
||||||
|
+ //version_Bnclient = version;
|
||||||
|
+ version_Fog = version_Game;
|
||||||
|
+ version_Storm = version_Game;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ //if (offset_Game != NULL) {
|
||||||
|
+ // pHeader = GetHeader((LPBYTE)offset_Game);
|
||||||
|
+ // if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00291342) count_114a++;
|
||||||
|
+ // if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x002854F2) count_114b++;
|
||||||
|
+ // if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x002850E2) count_114c++;
|
||||||
|
+ // if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00282985) count_114d++;
|
||||||
|
+ //}
|
||||||
|
+
|
||||||
|
+ log_msg("Version game is:\t(%s)\n\n", GetVersionString(version_Game));
|
||||||
|
+
|
||||||
|
+ if (version_Game == UNKNOWN)
|
||||||
|
+ {
|
||||||
|
+ MessageBoxA(NULL, "This version of Diablo II is not supported by Plugy. Please upgrade or downgrade to a supported version.", "Plugy 14.03", MB_OK);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
//////////////////////////////////// EXPORTS FUNCTIONS ////////////////////////////////////
|
||||||
|
|
||||||
|
|
@ -549,6 +549,12 @@ F8(FAST, D2Win, 10131,10131,10131,00000,00000,00000,00000,00000,00000, void, D2
|
|||||||
F8(FAST, D2Win, 10132,10132,10132,00000,00000,00000,00000,00000,00000, DWORD, D2PrintTextPopup,(LPWSTR s, DWORD x, DWORD y, DWORD uk, DWORD type, DWORD color) );//6F8AB080
|
F8(FAST, D2Win, 10132,10132,10132,00000,00000,00000,00000,00000,00000, DWORD, D2PrintTextPopup,(LPWSTR s, DWORD x, DWORD y, DWORD uk, DWORD type, DWORD color) );//6F8AB080
|
||||||
F8(STD, D2Win, 10017,10017,10017,10147,10113,10098,10098,10164,F93C0, void*, D2CreateTextBox,(DWORD* data) );
|
F8(STD, D2Win, 10017,10017,10017,10147,10113,10098,10098,10164,F93C0, void*, D2CreateTextBox,(DWORD* data) );
|
||||||
|
|
||||||
|
// Add a call wrapper for the following:
|
||||||
|
// D2Win.0x6F8AA2A0 (#10121) // int __fastcall D2Win_10121_GetTextWidth(const Unicode* wszText)
|
||||||
|
F8(FAST, D2Win, 10121, 10121, 10121, 10121, 10121, 10121, 10121, 10121, AA2A0, DWORD, D2Win_GetTextWidth, (const wchar_t* wszText));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//D2CMP : ????0000
|
//D2CMP : ????0000
|
||||||
|
887
HD_fix.patch
Normal file
887
HD_fix.patch
Normal file
@ -0,0 +1,887 @@
|
|||||||
|
diff --git a/PlugY/InfinityStash.cpp b/PlugY/InfinityStash.cpp
|
||||||
|
index 22e9c35..ea09d36 100644
|
||||||
|
--- a/PlugY/InfinityStash.cpp
|
||||||
|
+++ b/PlugY/InfinityStash.cpp
|
||||||
|
@@ -26,6 +26,7 @@ bool active_sharedStash = false;
|
||||||
|
bool separateHardSoftStash = false;
|
||||||
|
bool active_sharedGold=false;
|
||||||
|
char* sharedStashFilename = NULL;
|
||||||
|
+DWORD saveFileStackSize = 0x2000;
|
||||||
|
|
||||||
|
typedef int (*TchangeToSelectedStash)(Unit* ptChar, Stash* newStash, DWORD bOnlyItems, DWORD bIsClient);
|
||||||
|
|
||||||
|
@@ -422,7 +423,7 @@ void saveStashList(Unit* ptChar, Stash* ptStash, BYTE** data, DWORD* maxSize, DW
|
||||||
|
|
||||||
|
while(ptStash)
|
||||||
|
{
|
||||||
|
- if (*curSize + 0x2000 > *maxSize)
|
||||||
|
+ if (*curSize + saveFileStackSize > *maxSize)
|
||||||
|
{
|
||||||
|
BYTE* oldData = *data;
|
||||||
|
*maxSize *= 2;
|
||||||
|
diff --git a/PlugY/Interface_Skills.cpp b/PlugY/Interface_Skills.cpp
|
||||||
|
index 90178f7..8a07c2a 100644
|
||||||
|
--- a/PlugY/Interface_Skills.cpp
|
||||||
|
+++ b/PlugY/Interface_Skills.cpp
|
||||||
|
@@ -49,9 +49,10 @@ Unit* STDCALL skillsPageMouseDown(sWinMessage* msg)
|
||||||
|
if (active_SkillsPoints && !onRealm && D2isLODGame() && isOnButtonUnassignSkill(D2GetMouseX(),D2GetMouseY()))
|
||||||
|
{
|
||||||
|
log_msg("push down left button unassign skill\n");
|
||||||
|
- btnSkillIsDown = 1;
|
||||||
|
+ //btnSkillIsDown = 1;
|
||||||
|
D2PlaySound(4,0,0,0,0);
|
||||||
|
freeMessage(msg);
|
||||||
|
+ updateServer(US_UNASSIGN_SKILLS);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ptChar;
|
||||||
|
@@ -233,6 +234,7 @@ void Install_InterfaceSkills()
|
||||||
|
//6FAE1112 > C745 18 00000000 MOV DWORD PTR SS:[EBP+18],0
|
||||||
|
//004ABC1A |> C746 18 00000000 MOV DWORD PTR DS:[ESI+18],0
|
||||||
|
|
||||||
|
+ /* Conflicts with D2ExpRes
|
||||||
|
// Manage mouse up
|
||||||
|
mem_seek R8(D2Client, 7BC40, 7BC40, 78466, 17558, 8C078, 80248, 795F8, 30AA8, ABC96);
|
||||||
|
MEMJ_REF4( D2FreeWinMessage, caller_skillsPageMouseUp);//0xFFF93B0A
|
||||||
|
@@ -243,6 +245,7 @@ void Install_InterfaceSkills()
|
||||||
|
//6FB295F7 .^E9 8828F9FF JMP <JMP.&Storm.#511>
|
||||||
|
//6FAE0AA7 .^E9 E0B2FDFF JMP <JMP.&Storm.#511>
|
||||||
|
//004ABC95 |. E8 F645F7FF CALL Game.00420290
|
||||||
|
+ */
|
||||||
|
|
||||||
|
log_msg("\n");
|
||||||
|
|
||||||
|
diff --git a/PlugY/Interface_Stats.cpp b/PlugY/Interface_Stats.cpp
|
||||||
|
index 85e6029..1d3a4cf 100644
|
||||||
|
--- a/PlugY/Interface_Stats.cpp
|
||||||
|
+++ b/PlugY/Interface_Stats.cpp
|
||||||
|
@@ -13,6 +13,7 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
+/*
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
union{
|
||||||
|
@@ -35,6 +36,7 @@ static struct
|
||||||
|
#define getYNextPageBtn() RY(D2GetResolution()?0x40:0x70)
|
||||||
|
#define getHNextPageBtn() 32
|
||||||
|
#define isOnNextPageBtn(x,y) isOnRect(x, y, getXNextPageBtn(), getYNextPageBtn(), getLNextPageBtn(), getHNextPageBtn())
|
||||||
|
+*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -49,7 +51,7 @@ void STDCALL printStatsPageBtns()
|
||||||
|
sDrawImageInfo data;
|
||||||
|
ZeroMemory(&data,sizeof(data));
|
||||||
|
|
||||||
|
- if (printBackgroundOnMainPage && D2GetResolution())
|
||||||
|
+ if (printBackgroundOnMainPage)
|
||||||
|
{
|
||||||
|
setImage(&data, statsBackgroundImages);
|
||||||
|
setFrame(&data, 1);
|
||||||
|
@@ -57,16 +59,14 @@ void STDCALL printStatsPageBtns()
|
||||||
|
}
|
||||||
|
|
||||||
|
setImage(&data, D2LoadBuySelBtn());
|
||||||
|
- if (D2GetResolution())
|
||||||
|
- {
|
||||||
|
- setFrame(&data, 12 + isDownBtn.previousPage);
|
||||||
|
- D2PrintImage(&data, getXPreviousPageBtn(), getYPreviousPageBtn(), -1, 5, 0);
|
||||||
|
- }
|
||||||
|
+ setFrame(&data, 12 + isDownBtn.previousPage);
|
||||||
|
+ D2PrintImage(&data, getXPreviousPageBtn(), getYPreviousPageBtn(), -1, 5, 0);
|
||||||
|
+
|
||||||
|
setFrame(&data, 14 + isDownBtn.nextPage);
|
||||||
|
D2PrintImage(&data, getXNextPageBtn(), getYNextPageBtn(), -1, 5, 0);
|
||||||
|
|
||||||
|
D2SetFont(1);
|
||||||
|
- if (D2GetResolution() && isOnPreviousPageBtn(mx,my)) //print popup "previous page"
|
||||||
|
+ if (isOnPreviousPageBtn(mx,my)) //print popup "previous page"
|
||||||
|
{
|
||||||
|
lpText = getLocalString(STR_PREVIOUS_PAGE);
|
||||||
|
D2PrintPopup(lpText, getXPreviousPageBtn()+getLPreviousPageBtn()/2, getYPreviousPageBtn()-getHPreviousPageBtn(), WHITE, 1);
|
||||||
|
@@ -84,6 +84,12 @@ Unit* STDCALL statsPageMouseDown(sWinMessage* msg)
|
||||||
|
|
||||||
|
if (!active_newInterfaces || !D2isLODGame() ) return ptChar;
|
||||||
|
|
||||||
|
+ if (statsLeftDown(msg)) {
|
||||||
|
+ freeMessage(msg);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
if (D2GetResolution() && isOnPreviousPageBtn(msg->x,msg->y))
|
||||||
|
{
|
||||||
|
log_msg("push down left button previous page\n");
|
||||||
|
@@ -100,6 +106,7 @@ Unit* STDCALL statsPageMouseDown(sWinMessage* msg)
|
||||||
|
freeMessage(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
+ */
|
||||||
|
return ptChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -110,6 +117,13 @@ Unit* STDCALL statsPageMouseUp(sWinMessage* msg)
|
||||||
|
|
||||||
|
if (!active_newInterfaces || !D2isLODGame() ) return ptChar;
|
||||||
|
|
||||||
|
+ if (statsLeftUp(msg)) {
|
||||||
|
+ isDownBtn.all=0;
|
||||||
|
+ freeMessage(msg);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
if (D2GetResolution() && isOnPreviousPageBtn(msg->x,msg->y))
|
||||||
|
{
|
||||||
|
log_msg("push up left button previous page\n");
|
||||||
|
@@ -134,6 +148,7 @@ Unit* STDCALL statsPageMouseUp(sWinMessage* msg)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ */
|
||||||
|
|
||||||
|
isDownBtn.all=0;
|
||||||
|
return ptChar;
|
||||||
|
diff --git a/PlugY/LocalizedStrings.cpp b/PlugY/LocalizedStrings.cpp
|
||||||
|
index 70595ee..3c76d87 100644
|
||||||
|
--- a/PlugY/LocalizedStrings.cpp
|
||||||
|
+++ b/PlugY/LocalizedStrings.cpp
|
||||||
|
@@ -51,7 +51,7 @@ LPCWSTR getLocalTypeString(DWORD code)
|
||||||
|
{
|
||||||
|
if (sLocalizedTypeStrings[i].code == code)
|
||||||
|
{
|
||||||
|
- log_msg("Code=%08X\n", code);
|
||||||
|
+ //log_msg("Code=%08X\n", code);
|
||||||
|
if (sLocalizedTypeStrings[i].itemStr)
|
||||||
|
return StripGender(D2GetStringFromString(sLocalizedTypeStrings[i].itemStr));
|
||||||
|
LPWSTR text = StripGender(sLocalizedTypeStrings[i].typeLocalizedString);
|
||||||
|
@@ -300,6 +300,8 @@ void loadLocalizedStrings(int language)
|
||||||
|
LOAD(STR_SHARED_GOLD_QUANTITY);
|
||||||
|
LOAD(STR_PREVIOUS_PAGE);
|
||||||
|
LOAD(STR_NEXT_PAGE);
|
||||||
|
+ LOAD(STR_PREVIOUS_RUNE);
|
||||||
|
+ LOAD(STR_NEXT_RUNE);
|
||||||
|
LOAD(STR_ITEM_LEVEL);
|
||||||
|
LOAD(STR_PAGE_TYPE_CHANGE);
|
||||||
|
|
||||||
|
diff --git a/PlugY/LocalizedStrings.h b/PlugY/LocalizedStrings.h
|
||||||
|
index 9fb08e7..0e7b83d 100644
|
||||||
|
--- a/PlugY/LocalizedStrings.h
|
||||||
|
+++ b/PlugY/LocalizedStrings.h
|
||||||
|
@@ -37,6 +37,8 @@ enum eStringList
|
||||||
|
STR_SHARED_GOLD_QUANTITY,
|
||||||
|
STR_PREVIOUS_PAGE,
|
||||||
|
STR_NEXT_PAGE,
|
||||||
|
+ STR_PREVIOUS_RUNE,
|
||||||
|
+ STR_NEXT_RUNE,
|
||||||
|
STR_ITEM_LEVEL,
|
||||||
|
STR_PAGE_TYPE_CHANGE,
|
||||||
|
//
|
||||||
|
diff --git a/PlugY/NewInterface_CubeListing.cpp b/PlugY/NewInterface_CubeListing.cpp
|
||||||
|
index 1c54331..d50c8bc 100644
|
||||||
|
--- a/PlugY/NewInterface_CubeListing.cpp
|
||||||
|
+++ b/PlugY/NewInterface_CubeListing.cpp
|
||||||
|
@@ -233,12 +233,6 @@ DWORD print(CubeMainBIN* curForm, LPWSTR buf, LPINT len, DWORD)//maxsize)
|
||||||
|
printInputItem(&curForm->input6, buf, len, &realNbInputs);
|
||||||
|
printInputItem(&curForm->input7, buf, len, &realNbInputs);
|
||||||
|
|
||||||
|
- if (realNbInputs != curForm->numinputs)
|
||||||
|
- {
|
||||||
|
- PRINT(BUF, L" *** ERROR : numInputs(%d) != realNbInputs(%d) ***", curForm->numinputs, realNbInputs);
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
PRINT(BUF,L" => ");
|
||||||
|
int realNbOutputs=0;
|
||||||
|
|
||||||
|
@@ -269,6 +263,9 @@ DWORD print(CubeMainBIN* curForm, LPWSTR buf, LPINT len, DWORD)//maxsize)
|
||||||
|
// if (curForm->version == 100)
|
||||||
|
// sprintf(BUF, " [expansion only]");
|
||||||
|
|
||||||
|
+ if (realNbInputs != curForm->numinputs)
|
||||||
|
+ PRINT(BUF, L" *** ERROR : numInputs(%d) != realNbInputs(%d) ***", curForm->numinputs, realNbInputs);
|
||||||
|
+
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#undef BUF
|
||||||
|
diff --git a/PlugY/NewInterface_Runewords.cpp b/PlugY/NewInterface_Runewords.cpp
|
||||||
|
index 99d1f38..13efd9f 100644
|
||||||
|
--- a/PlugY/NewInterface_Runewords.cpp
|
||||||
|
+++ b/PlugY/NewInterface_Runewords.cpp
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
+/*
|
||||||
|
#define NB_RUNES_PER_PAGE 25
|
||||||
|
|
||||||
|
#define getXCloseBtn() 360
|
||||||
|
@@ -53,6 +54,7 @@ static struct
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} isDownBtn;
|
||||||
|
+*/
|
||||||
|
|
||||||
|
|
||||||
|
void printRuneword(RunesBIN* runesData, DWORD pos)
|
||||||
|
@@ -64,7 +66,7 @@ void printRuneword(RunesBIN* runesData, DWORD pos)
|
||||||
|
D2SetFont(6);
|
||||||
|
DWORD nbPixel = D2GetPixelLen(lpText);
|
||||||
|
DWORD x1 = (nbPixel >= 195) ? 0 : 195-nbPixel;
|
||||||
|
- D2PrintString(lpText, x1, 10 + pos*20, GOLD, 0);//MILIEU(0x00,0x70,nbPixel)
|
||||||
|
+ D2PrintString(lpText, posXRunesList + RX(x1), posYRunesList + 10 + pos*20, GOLD, 0);//MILIEU(0x00,0x70,nbPixel)
|
||||||
|
|
||||||
|
typesList[0]=L'\0';
|
||||||
|
DWORD numItype=0;
|
||||||
|
@@ -80,7 +82,7 @@ void printRuneword(RunesBIN* runesData, DWORD pos)
|
||||||
|
}
|
||||||
|
nbPixel = D2GetPixelLen(typesList);
|
||||||
|
x1 = (nbPixel >= 195) ? 0 : 195-nbPixel;
|
||||||
|
- D2PrintString(typesList, x1, 20 + pos*20, WHITE, 0);//MILIEU(0x70,0xA0,nbPixel)
|
||||||
|
+ D2PrintString(typesList, posXRunesList + RX(x1), posYRunesList + 20 + pos*20, WHITE, 0);//MILIEU(0x70,0xA0,nbPixel)
|
||||||
|
|
||||||
|
runesList[0]=L'\0';
|
||||||
|
DWORD numRune=0;
|
||||||
|
@@ -115,7 +117,7 @@ void printRuneword(RunesBIN* runesData, DWORD pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
// x1 = (nbPixel < 145) ? 155 : 300-nbPixel;
|
||||||
|
- D2PrintString(runesList, x1, y1 + pos*20, WHITE, 0);//MILIEU(0xD0,0xA0,nbPixel)
|
||||||
|
+ D2PrintString(runesList, posXRunesList + RX(x1), posYRunesList + y1 + pos*20, WHITE, 0);//MILIEU(0xD0,0xA0,nbPixel)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -123,48 +125,58 @@ void printRuneword(RunesBIN* runesData, DWORD pos)
|
||||||
|
//6FB21FAA
|
||||||
|
void STDCALL printRunewordsPage()
|
||||||
|
{
|
||||||
|
- if (!D2isLODGame() || !D2GetResolution()) return D2PrintStatsPage();
|
||||||
|
+ if (!D2isLODGame()) return D2PrintStatsPage();
|
||||||
|
|
||||||
|
LPWSTR lpText;
|
||||||
|
- bDontPrintBorder = true;
|
||||||
|
+ bDontPrintBorder = D2GetResolution()? true : false;
|
||||||
|
|
||||||
|
//Init data for print image
|
||||||
|
sDrawImageInfo data;
|
||||||
|
ZeroMemory(&data,sizeof(data));
|
||||||
|
|
||||||
|
//print background
|
||||||
|
-/* setImage(&data, newStatsInterfaceImages);
|
||||||
|
+ fillRect(RX(0), RY(ResolutionY), 512, 768, 0, 5);
|
||||||
|
+ setImage(&data, newStatsInterfaceImages);
|
||||||
|
setFrame(&data, 0);
|
||||||
|
- D2PrintImage(&data, 0, 256, -1, 5, 0);
|
||||||
|
+ D2PrintImage(&data, RX(0), RY(ResolutionY-256), -1, 5, 0);
|
||||||
|
setFrame(&data, 1);
|
||||||
|
- D2PrintImage(&data, 256,256, -1, 5, 0);
|
||||||
|
+ D2PrintImage(&data, RX(256),RY(ResolutionY-256), -1, 5, 0);
|
||||||
|
setFrame(&data, 2);
|
||||||
|
- D2PrintImage(&data, 0, 512, -1, 5, 0);
|
||||||
|
+ D2PrintImage(&data, RX(0), RY(ResolutionY-256*2), -1, 5, 0);
|
||||||
|
setFrame(&data, 3);
|
||||||
|
- D2PrintImage(&data, 256,512, -1, 5, 0);
|
||||||
|
+ D2PrintImage(&data, RX(256),RY(ResolutionY-256*2), -1, 5, 0);
|
||||||
|
setFrame(&data, 4);
|
||||||
|
- D2PrintImage(&data, 0, 552, -1, 5, 0);
|
||||||
|
+ D2PrintImage(&data, RX(0), RY(ResolutionY-256*3), -1, 5, 0);
|
||||||
|
setFrame(&data, 5);
|
||||||
|
- D2PrintImage(&data, 256,552, -1, 5, 0);
|
||||||
|
-*/
|
||||||
|
- fillRect(0,0,400,552,0,5);
|
||||||
|
+ D2PrintImage(&data, RX(256),RY(ResolutionY-256*3), -1, 5, 0);
|
||||||
|
+
|
||||||
|
+ if (printBackgroundOnMainPage)
|
||||||
|
+ {
|
||||||
|
+ setImage(&data, statsBackgroundImages);
|
||||||
|
+ setFrame(&data, 1);
|
||||||
|
+ D2PrintImage(&data, getXPreviousPageBtn()-7, getYPreviousPageBtn()+8, -1, 5, 0);
|
||||||
|
+ D2PrintImage(&data, getXPrevRunesBtn()-7, getYPrevRunesBtn()+8, -1, 5, 0);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
//print button close
|
||||||
|
setImage(&data, D2LoadBuySelBtn());
|
||||||
|
setFrame(&data, 10 + isDownBtn.close);
|
||||||
|
D2PrintImage(&data, getXCloseBtn(), getYCloseBtn(), -1, 5, 0);
|
||||||
|
|
||||||
|
+ //print previous page button
|
||||||
|
+ setFrame(&data, 12 + isDownBtn.previousPage);
|
||||||
|
+ D2PrintImage(&data, getXPreviousPageBtn(), getYPreviousPageBtn(), -1, 5, 0);
|
||||||
|
+
|
||||||
|
//print next page button
|
||||||
|
- setFrame(&data, isDownBtn.nextPage);
|
||||||
|
+ setFrame(&data, 14 + isDownBtn.nextPage);
|
||||||
|
D2PrintImage(&data, getXNextPageBtn(), getYNextPageBtn(), -1, 5, 0);
|
||||||
|
|
||||||
|
//print previous runes button
|
||||||
|
- setImage(&data, stashBtnsImages);
|
||||||
|
- setFrame(&data, isDownBtn.prevRunes);
|
||||||
|
+ setFrame(&data, 12 + isDownBtn.prevRunes);
|
||||||
|
D2PrintImage(&data, getXPrevRunesBtn(), getYPrevRunesBtn(), -1, 5, 0);
|
||||||
|
|
||||||
|
//print previous runes button
|
||||||
|
- setFrame(&data, 2 + isDownBtn.nextRunes);
|
||||||
|
+ setFrame(&data, 14 + isDownBtn.nextRunes);
|
||||||
|
D2PrintImage(&data, getXNextRunesBtn(), getYNextRunesBtn(), -1, 5, 0);
|
||||||
|
|
||||||
|
D2SetFont(6);
|
||||||
|
@@ -181,11 +193,11 @@ void STDCALL printRunewordsPage()
|
||||||
|
{
|
||||||
|
if (!runesData->Complete || runesData->Server) continue;
|
||||||
|
nbRunesCompleted++;
|
||||||
|
- if ( (curRunesPage * NB_RUNES_PER_PAGE < nbRunesCompleted) &&
|
||||||
|
- (nbRunesCompleted <= (curRunesPage+1) * NB_RUNES_PER_PAGE) )
|
||||||
|
+ if ( (curRunesPage * runesPerPage < nbRunesCompleted) &&
|
||||||
|
+ (nbRunesCompleted <= (curRunesPage+1) * runesPerPage) )
|
||||||
|
printRuneword(runesData, curNbRunes++);
|
||||||
|
}
|
||||||
|
- maxRunesPage = nbRunesCompleted ? (nbRunesCompleted-1) / NB_RUNES_PER_PAGE : 0;
|
||||||
|
+ maxRunesPage = nbRunesCompleted ? (nbRunesCompleted-1) / runesPerPage : 0;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////// POPUP PRINTING ////////////////////
|
||||||
|
@@ -197,11 +209,26 @@ void STDCALL printRunewordsPage()
|
||||||
|
{
|
||||||
|
D2PrintPopup(D2GetStringFromIndex(0x1030), getXCloseBtn()+getLCloseBtn()/2, getYCloseBtn()-getHCloseBtn(), WHITE, 1);
|
||||||
|
}
|
||||||
|
+ else if (isOnPreviousPageBtn(x,y)) //print popup "previous page"
|
||||||
|
+ {
|
||||||
|
+ lpText = getLocalString(STR_PREVIOUS_PAGE);
|
||||||
|
+ D2PrintPopup(lpText, getXPreviousPageBtn()+getLPreviousPageBtn()/2, getYPreviousPageBtn()-getHPreviousPageBtn(), WHITE, 1);
|
||||||
|
+ }
|
||||||
|
else if (isOnNextPageBtn(x,y)) // print popup "next page"
|
||||||
|
{
|
||||||
|
lpText = getLocalString(STR_NEXT_PAGE);
|
||||||
|
D2PrintPopup(lpText, getXNextPageBtn()+getLNextPageBtn()/2, getYNextPageBtn()-getHNextPageBtn(), WHITE, 1);
|
||||||
|
}
|
||||||
|
+ else if (isOnPrevRunesBtn(x,y)) // print popup "previous rune"
|
||||||
|
+ {
|
||||||
|
+ lpText = getLocalString(STR_PREVIOUS_RUNE);
|
||||||
|
+ D2PrintPopup(lpText, getXPrevRunesBtn()+getLPrevRunesBtn()/2, getYPrevRunesBtn()-getHPrevRunesBtn(), WHITE, 1);
|
||||||
|
+ }
|
||||||
|
+ else if (isOnNextRunesBtn(x,y)) // print popup "next rune"
|
||||||
|
+ {
|
||||||
|
+ lpText = getLocalString(STR_NEXT_RUNE);
|
||||||
|
+ D2PrintPopup(lpText, getXNextRunesBtn()+getLNextRunesBtn()/2, getYNextRunesBtn()-getHNextRunesBtn(), WHITE, 1);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
diff --git a/PlugY/NewInterface_Stats.cpp b/PlugY/NewInterface_Stats.cpp
|
||||||
|
index 10fa32d..d73c5da 100644
|
||||||
|
--- a/PlugY/NewInterface_Stats.cpp
|
||||||
|
+++ b/PlugY/NewInterface_Stats.cpp
|
||||||
|
@@ -13,6 +13,7 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
+/*
|
||||||
|
#define getXCloseBtn() 360
|
||||||
|
#define getLCloseBtn() 32
|
||||||
|
#define getYCloseBtn() (ResolutionY - 60)
|
||||||
|
@@ -92,6 +93,7 @@ void** ptD2AssignStatsPointsBtnImages = (void**)0x6FBB5BB4;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
+/*
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
union{
|
||||||
|
@@ -111,6 +113,7 @@ static struct
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} isDownBtn;
|
||||||
|
+*/
|
||||||
|
|
||||||
|
|
||||||
|
void print2Lines(WORD id, LPWSTR lpText, DWORD x, DWORD l, DWORD y)
|
||||||
|
diff --git a/PlugY/NewInterface_StatsPageTwo.cpp b/PlugY/NewInterface_StatsPageTwo.cpp
|
||||||
|
index dfdc8a1..6215dd6 100644
|
||||||
|
--- a/PlugY/NewInterface_StatsPageTwo.cpp
|
||||||
|
+++ b/PlugY/NewInterface_StatsPageTwo.cpp
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
+/*
|
||||||
|
#define getXCloseBtn() RX(0x110)
|
||||||
|
#define getLCloseBtn() 32
|
||||||
|
#define getYCloseBtn() RY(0x40)
|
||||||
|
@@ -29,11 +30,13 @@
|
||||||
|
#define getYNextPageBtn() RY(0x40)
|
||||||
|
#define getHNextPageBtn() 32
|
||||||
|
#define isOnNextPageBtn(x,y) isOnRect(x, y, getXNextPageBtn(), getYNextPageBtn(), getLNextPageBtn(), getHNextPageBtn())
|
||||||
|
+*/
|
||||||
|
|
||||||
|
const char * STATS_INTERFACE_FILENAME = "PlugY\\statsinterface.txt";
|
||||||
|
|
||||||
|
#define BUFSIZE 0x400
|
||||||
|
|
||||||
|
+/*
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
union{
|
||||||
|
@@ -45,6 +48,7 @@ static struct
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} isDownBtn;
|
||||||
|
+*/
|
||||||
|
|
||||||
|
|
||||||
|
struct statsInterfaceBIN
|
||||||
|
@@ -337,8 +341,7 @@ void STDCALL printNewStatsPageTwo(int currentPage)
|
||||||
|
|
||||||
|
WCHAR text[BUFSIZE];
|
||||||
|
LPWSTR lpText;
|
||||||
|
- bDontPrintBorder = false;
|
||||||
|
-
|
||||||
|
+ bDontPrintBorder = D2GetResolution()? true : false;
|
||||||
|
Unit* ptChar = D2GetClientPlayer();
|
||||||
|
|
||||||
|
d2_assert(!ptChar, "Printing stats page : no character selected",__FILE__,__LINE__);
|
||||||
|
@@ -349,16 +352,20 @@ void STDCALL printNewStatsPageTwo(int currentPage)
|
||||||
|
ZeroMemory(&data,sizeof(data));
|
||||||
|
|
||||||
|
//print background
|
||||||
|
- fillRect(RX(0),RY(480),320,432,0,5);//552
|
||||||
|
+ fillRect(RX(0), RY(ResolutionY), 512, 768, 0, 5);
|
||||||
|
setImage(&data, newStatsInterfaceImages);
|
||||||
|
setFrame(&data, 0);
|
||||||
|
- D2PrintImage(&data, RX(0), RY(224), -1, 5, 0);
|
||||||
|
+ D2PrintImage(&data, RX(0), RY(ResolutionY-256), -1, 5, 0);
|
||||||
|
setFrame(&data, 1);
|
||||||
|
- D2PrintImage(&data, RX(256),RY(224), -1, 5, 0);//256
|
||||||
|
+ D2PrintImage(&data, RX(256),RY(ResolutionY-256), -1, 5, 0);
|
||||||
|
setFrame(&data, 2);
|
||||||
|
- D2PrintImage(&data, RX(0), RY(48), -1, 5, 0);//432
|
||||||
|
+ D2PrintImage(&data, RX(0), RY(ResolutionY-256*2), -1, 5, 0);
|
||||||
|
setFrame(&data, 3);
|
||||||
|
- D2PrintImage(&data, RX(256),RY(48), -1, 5, 0);
|
||||||
|
+ D2PrintImage(&data, RX(256),RY(ResolutionY-256*2), -1, 5, 0);
|
||||||
|
+ setFrame(&data, 4);
|
||||||
|
+ D2PrintImage(&data, RX(0), RY(ResolutionY-256*3), -1, 5, 0);
|
||||||
|
+ setFrame(&data, 5);
|
||||||
|
+ D2PrintImage(&data, RX(256),RY(ResolutionY-256*3), -1, 5, 0);
|
||||||
|
|
||||||
|
D2SetFont(1);
|
||||||
|
for (int i=0; i<nbStatsInterface; i++)
|
||||||
|
@@ -392,10 +399,12 @@ void STDCALL printNewStatsPageTwo(int currentPage)
|
||||||
|
D2PrintString(text, x, y, WHITE, 0);
|
||||||
|
*/
|
||||||
|
|
||||||
|
- //print background previous/next page buttons
|
||||||
|
- setImage(&data, statsBackgroundImages);
|
||||||
|
- setFrame(&data, D2GetResolution()?1:0);
|
||||||
|
- D2PrintImage(&data, getXPreviousPageBtn()-7, getYPreviousPageBtn()+8, -1, 5, 0);
|
||||||
|
+ if (printBackgroundOnMainPage) {
|
||||||
|
+ //print background previous/next page buttons
|
||||||
|
+ setImage(&data, statsBackgroundImages);
|
||||||
|
+ setFrame(&data, 1);
|
||||||
|
+ D2PrintImage(&data, getXPreviousPageBtn()-7, getYPreviousPageBtn()+8, -1, 5, 0);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
//print button close
|
||||||
|
setImage(&data, D2LoadBuySelBtn());
|
||||||
|
diff --git a/PlugY/NewInterfaces.cpp b/PlugY/NewInterfaces.cpp
|
||||||
|
index 2bcb2f1..91003fb 100644
|
||||||
|
--- a/PlugY/NewInterfaces.cpp
|
||||||
|
+++ b/PlugY/NewInterfaces.cpp
|
||||||
|
@@ -22,11 +22,39 @@ bool active_newInterfaces=false;
|
||||||
|
bool selectMainPageOnOpenning=true;
|
||||||
|
bool printBackgroundOnMainPage=true;
|
||||||
|
|
||||||
|
+int posXNextPageBtn = -1;
|
||||||
|
+int posYNextPageBtn = -1;
|
||||||
|
+int posXPrevPageBtn = -1;
|
||||||
|
+int posYPrevPageBtn = -1;
|
||||||
|
+int posXClosePageBtn = -1;
|
||||||
|
+int posYClosePageBtn = -1;
|
||||||
|
+int posXNextRuneBtn = -1;
|
||||||
|
+int posYNextRuneBtn = -1;
|
||||||
|
+int posXPrevRuneBtn = -1;
|
||||||
|
+int posYPrevRuneBtn = -1;
|
||||||
|
+int posXRunesList = -1;
|
||||||
|
+int posYRunesList = -1;
|
||||||
|
+int runesPerPage = -1;
|
||||||
|
+
|
||||||
|
+DWORD getXNextPageBtn() {return RX(posXNextPageBtn);}
|
||||||
|
+DWORD getYNextPageBtn() {return RY(posYNextPageBtn);}
|
||||||
|
+DWORD getXPreviousPageBtn() {return RX(posXPrevPageBtn);}
|
||||||
|
+DWORD getYPreviousPageBtn() {return RY(posYPrevPageBtn);}
|
||||||
|
+DWORD getXCloseBtn() {return RX(posXClosePageBtn);}
|
||||||
|
+DWORD getYCloseBtn() {return RY(posYClosePageBtn);}
|
||||||
|
+DWORD getXNextRunesBtn() {return RX(posXNextRuneBtn);}
|
||||||
|
+DWORD getYNextRunesBtn() {return RY(posYNextRuneBtn);}
|
||||||
|
+DWORD getXPrevRunesBtn() {return RX(posXPrevRuneBtn);}
|
||||||
|
+DWORD getYPrevRunesBtn() {return RY(posYPrevRuneBtn);}
|
||||||
|
+
|
||||||
|
DWORD bDontPrintBorder=false;
|
||||||
|
|
||||||
|
int selectedPage=0;
|
||||||
|
int lastPage=0;
|
||||||
|
int extraHiddenPage=0;
|
||||||
|
+int curRunesPage=0;
|
||||||
|
+int maxRunesPage=0xFFFF;
|
||||||
|
+BtnState isDownBtn={0};
|
||||||
|
|
||||||
|
void GoNextStatPage()
|
||||||
|
{
|
||||||
|
@@ -44,8 +72,12 @@ void GoPreviousStatPage()
|
||||||
|
|
||||||
|
void GoStatPage(int page)
|
||||||
|
{
|
||||||
|
- if ( (page >= 0) && (page <= lastPage + (D2GetResolution()? extraHiddenPage : 0)) )
|
||||||
|
+ if ( (page >= 0) && (page <= (lastPage + extraHiddenPage)) )
|
||||||
|
selectedPage = page;
|
||||||
|
+ else if (page < 0)
|
||||||
|
+ selectedPage = lastPage + extraHiddenPage;
|
||||||
|
+ else
|
||||||
|
+ selectedPage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetCurrentPage()
|
||||||
|
@@ -83,6 +115,16 @@ DWORD STDCALL mouseCustomPageLeftDown(sWinMessage* msg)
|
||||||
|
DWORD STDCALL mouseCustomPageLeftUp(sWinMessage* msg)
|
||||||
|
{
|
||||||
|
if(onRealm) return -1;
|
||||||
|
+
|
||||||
|
+ if (selectedPage == 0) return -1;
|
||||||
|
+ if (!isOnStatsPage(msg->x,msg->y)) return 1;
|
||||||
|
+ statsLeftUp(msg);
|
||||||
|
+ D2CleanStatMouseUp();
|
||||||
|
+ freeMessage(msg);
|
||||||
|
+ isDownBtn.all=0;
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
if ( (selectedPage > 0) && (selectedPage <= lastPage) )
|
||||||
|
return mouseNewStatsPageTwoLeftUp(msg);
|
||||||
|
else if (selectedPage == lastPage+1)
|
||||||
|
@@ -91,6 +133,87 @@ DWORD STDCALL mouseCustomPageLeftUp(sWinMessage* msg)
|
||||||
|
return mouseNewStatsPageLeftUp(msg);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
+ */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DWORD STDCALL statsLeftDown(sWinMessage* msg)
|
||||||
|
+{
|
||||||
|
+ if (isOnCloseBtn(msg->x,msg->y) && selectedPage != 0)
|
||||||
|
+ {
|
||||||
|
+ log_msg("push down left button close\n");
|
||||||
|
+ isDownBtn.close = 1;
|
||||||
|
+ D2PlaySound(4,0,0,0,0);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else if (isOnPreviousPageBtn(msg->x,msg->y))
|
||||||
|
+ {
|
||||||
|
+ log_msg("push down left button previous page\n");
|
||||||
|
+ isDownBtn.previousPage = 1;
|
||||||
|
+ D2PlaySound(4,0,0,0,0);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else if (isOnNextPageBtn(msg->x,msg->y))
|
||||||
|
+ {
|
||||||
|
+ log_msg("push down left button next page\n");
|
||||||
|
+ isDownBtn.nextPage = 1;
|
||||||
|
+ D2PlaySound(4,0,0,0,0);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else if (isOnPrevRunesBtn(msg->x,msg->y) && selectedPage == (lastPage + extraHiddenPage))
|
||||||
|
+ {
|
||||||
|
+ log_msg("push down left button prev runes\n");
|
||||||
|
+ isDownBtn.prevRunes = 1;
|
||||||
|
+ D2PlaySound(4,0,0,0,0);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else if (isOnNextRunesBtn(msg->x,msg->y) && selectedPage == (lastPage + extraHiddenPage))
|
||||||
|
+ {
|
||||||
|
+ log_msg("push down left button next runes\n");
|
||||||
|
+ isDownBtn.nextRunes = 1;
|
||||||
|
+ D2PlaySound(4,0,0,0,0);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DWORD STDCALL statsLeftUp(sWinMessage* msg)
|
||||||
|
+{
|
||||||
|
+ if (isOnCloseBtn(msg->x,msg->y) && selectedPage != 0)
|
||||||
|
+ {
|
||||||
|
+ log_msg("push up left button close\n");
|
||||||
|
+ if (isDownBtn.close)
|
||||||
|
+ D2TogglePage(2,1,0);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else if (isOnPreviousPageBtn(msg->x,msg->y))
|
||||||
|
+ {
|
||||||
|
+ log_msg("push up left button previous page\n");
|
||||||
|
+ if (isDownBtn.previousPage)
|
||||||
|
+ GoStatPage(selectedPage-1);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else if (isOnNextPageBtn(msg->x,msg->y))
|
||||||
|
+ {
|
||||||
|
+ log_msg("push up left button next page\n");
|
||||||
|
+ if (isDownBtn.nextPage)
|
||||||
|
+ GoStatPage(selectedPage+1);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else if (isOnPrevRunesBtn(msg->x,msg->y) && selectedPage == (lastPage + extraHiddenPage))
|
||||||
|
+ {
|
||||||
|
+ log_msg("push up left button prev runes\n");
|
||||||
|
+ if (isDownBtn.prevRunes && curRunesPage)
|
||||||
|
+ curRunesPage--;
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else if (isOnNextRunesBtn(msg->x,msg->y) && selectedPage == (lastPage + extraHiddenPage))
|
||||||
|
+ {
|
||||||
|
+ log_msg("push up left button next runes\n");
|
||||||
|
+ if (isDownBtn.nextRunes && (curRunesPage < maxRunesPage))
|
||||||
|
+ curRunesPage++;
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FCT_ASM ( caller_DontPrintBorder_114 )
|
||||||
|
@@ -474,6 +597,7 @@ void Install_NewInterfaces()
|
||||||
|
//00498636 |. 6A 48 PUSH 48
|
||||||
|
//00498638 |. 8D45 B8 LEA EAX,DWORD PTR SS:[EBP-48]
|
||||||
|
|
||||||
|
+ /* Conflicts with D2ExpRes
|
||||||
|
// Manage mouse down (Play sound)
|
||||||
|
mem_seek R8(D2Client, 2A9DC, 2A9CC, 312A5, 82736, 891B6, 6B116, BCD36, BF4D6, A7731);
|
||||||
|
memt_byte( 0x8D, 0xE8 ); // CALL
|
||||||
|
@@ -486,6 +610,7 @@ void Install_NewInterfaces()
|
||||||
|
//6FB6CD36 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
||||||
|
//6FB6F4D6 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
||||||
|
//004A7731 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
||||||
|
+ */
|
||||||
|
|
||||||
|
// Manage mouse up
|
||||||
|
mem_seek R8(D2Client, 2ABBB, 2ABAB, 3148D, 836D9, 8A159, 6C0B9, BDCB9, C0459, A78DA);
|
||||||
|
diff --git a/PlugY/Parameters.cpp b/PlugY/Parameters.cpp
|
||||||
|
index b4dc915..392c112 100644
|
||||||
|
--- a/PlugY/Parameters.cpp
|
||||||
|
+++ b/PlugY/Parameters.cpp
|
||||||
|
@@ -58,6 +58,7 @@ const char* S_dllFilenames2 = "DllToLoad2";
|
||||||
|
const char* S_active_Commands = "ActiveCommands";
|
||||||
|
const char* S_active_CheckMemory = "ActiveCheckMemory";
|
||||||
|
const char* S_active_othersFeatures = "ActiveAllOthersFeatures";
|
||||||
|
+const char* S_saveFileStackSize = "SaveFileStackSize";
|
||||||
|
|
||||||
|
const char* S_WINDOWED = "WINDOWED";
|
||||||
|
const char* S_ActiveWindowed = "ActiveWindowed";
|
||||||
|
@@ -214,6 +215,19 @@ const char* S_INTERFACE = "INTERFACE";
|
||||||
|
const char* S_active_newInterfaces = "ActiveNewStatsInterface";
|
||||||
|
const char* S_selectMainPageOnOpenning = "SelectMainPageOnOpenning";
|
||||||
|
const char* S_printBackgroundOnMainPage = "PrintButtonsBackgroundOnMainStatsPage";
|
||||||
|
+const char* S_posXNextPageBtn = "PosXNextPageBtn";
|
||||||
|
+const char* S_posYNextPageBtn = "PosYNextPageBtn";
|
||||||
|
+const char* S_posXPrevPageBtn = "PosXPrevPageBtn";
|
||||||
|
+const char* S_posYPrevPageBtn = "PosYPrevPageBtn";
|
||||||
|
+const char* S_posXClosePageBtn = "PosXClosePageBtn";
|
||||||
|
+const char* S_posYClosePageBtn = "PosYClosePageBtn";
|
||||||
|
+const char* S_posXNextRuneBtn = "PosXNextRuneBtn";
|
||||||
|
+const char* S_posYNextRuneBtn = "PosYNextRuneBtn";
|
||||||
|
+const char* S_posXPrevRuneBtn = "PosXPrevRuneBtn";
|
||||||
|
+const char* S_posYPrevRuneBtn = "PosYPrevRuneBtn";
|
||||||
|
+const char* S_posXRunesList = "PosXRunesList";
|
||||||
|
+const char* S_posYRunesList = "PosYRunesList";
|
||||||
|
+const char* S_runesPerPage = "RunesPerPage";
|
||||||
|
|
||||||
|
const char* S_EXTRA = "EXTRA";
|
||||||
|
const char* S_active_RunLODs = "ActiveLaunchAnyNumberOfLOD";
|
||||||
|
@@ -316,6 +330,10 @@ void init_General(INIFile* iniFile, INIFile* iniFixedFile, INIFile* iniDefaultFi
|
||||||
|
active_othersFeatures = atoi(buffer) != 0;
|
||||||
|
log_msg("active_othersFeatures\t\t= %u\n", active_othersFeatures);
|
||||||
|
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_GENERAL, S_saveFileStackSize, "8192");
|
||||||
|
+ saveFileStackSize = atoi(buffer);
|
||||||
|
+ log_msg("SaveFileStackSize\t\t\t= %u\n", saveFileStackSize);
|
||||||
|
+
|
||||||
|
log_msg("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1032,6 +1050,52 @@ void init_NewInterfaces(INIFile* iniFile, INIFile* iniFixedFile, INIFile* iniDef
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_printBackgroundOnMainPage, "1");
|
||||||
|
printBackgroundOnMainPage = atoi(buffer) != 0;
|
||||||
|
log_msg("printBackgroundOnMainPage\t= %u\n", printBackgroundOnMainPage);
|
||||||
|
+
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXNextPageBtn, "161");
|
||||||
|
+ posXNextPageBtn = atoi(buffer);
|
||||||
|
+ log_msg("posXNextPageBtn\t= %d\n", posXNextPageBtn);
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYNextPageBtn, "64");
|
||||||
|
+ posYNextPageBtn = atoi(buffer);
|
||||||
|
+ log_msg("posYNextPageBtn\t= %d\n", posYNextPageBtn);
|
||||||
|
+
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXPrevPageBtn, "119");
|
||||||
|
+ posXPrevPageBtn = atoi(buffer);
|
||||||
|
+ log_msg("posXPrevPageBtn\t= %d\n", posXPrevPageBtn);
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYPrevPageBtn, "64");
|
||||||
|
+ posYPrevPageBtn = atoi(buffer);
|
||||||
|
+ log_msg("posYPrevPageBtn\t= %d\n", posYPrevPageBtn);
|
||||||
|
+
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXClosePageBtn, "360");
|
||||||
|
+ posXClosePageBtn = atoi(buffer);
|
||||||
|
+ log_msg("posXClosePageBtn\t= %d\n", posXClosePageBtn);
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYClosePageBtn, "64");
|
||||||
|
+ posYClosePageBtn = atoi(buffer);
|
||||||
|
+ log_msg("posYClosePageBtn\t= %d\n", posYClosePageBtn);
|
||||||
|
+
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXNextRuneBtn, "302");
|
||||||
|
+ posXNextRuneBtn = atoi(buffer);
|
||||||
|
+ log_msg("posXNextRuneBtn\t= %d\n", posXNextRuneBtn);
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYNextRuneBtn, "64");
|
||||||
|
+ posYNextRuneBtn = atoi(buffer);
|
||||||
|
+ log_msg("posYNextRuneBtn\t= %d\n", posYNextRuneBtn);
|
||||||
|
+
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXPrevRuneBtn, "260");
|
||||||
|
+ posXPrevRuneBtn = atoi(buffer);
|
||||||
|
+ log_msg("posXPrevRuneBtn\t= %d\n", posXPrevRuneBtn);
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYPrevRuneBtn, "64");
|
||||||
|
+ posYPrevRuneBtn = atoi(buffer);
|
||||||
|
+ log_msg("posYPrevRuneBtn\t= %d\n", posYPrevRuneBtn);
|
||||||
|
+
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXRunesList, "50");
|
||||||
|
+ posXRunesList = atoi(buffer);
|
||||||
|
+ log_msg("posXRunesList\t= %d\n", posXRunesList);
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYRunesList, "45");
|
||||||
|
+ posYRunesList = atoi(buffer);
|
||||||
|
+ log_msg("posYRunesList\t= %d\n", posYRunesList);
|
||||||
|
+
|
||||||
|
+ GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_runesPerPage, "30");
|
||||||
|
+ runesPerPage = atoi(buffer);
|
||||||
|
+ log_msg("runesPerPage\t= %d\n", runesPerPage);
|
||||||
|
}
|
||||||
|
log_msg("\n");
|
||||||
|
}
|
||||||
|
diff --git a/PlugY/infinityStash.h b/PlugY/infinityStash.h
|
||||||
|
index 0ca6b4d..123705d 100644
|
||||||
|
--- a/PlugY/infinityStash.h
|
||||||
|
+++ b/PlugY/infinityStash.h
|
||||||
|
@@ -18,6 +18,7 @@ extern bool active_sharedStash;
|
||||||
|
extern bool active_sharedGold;
|
||||||
|
extern bool separateHardSoftStash;
|
||||||
|
extern char* sharedStashFilename;
|
||||||
|
+extern DWORD saveFileStackSize;
|
||||||
|
|
||||||
|
extern bool displaySharedSetItemNameInGreen;
|
||||||
|
extern int posXPreviousBtn;
|
||||||
|
diff --git a/PlugY/newInterfaces.h b/PlugY/newInterfaces.h
|
||||||
|
index de51f26..c4c4ff3 100644
|
||||||
|
--- a/PlugY/newInterfaces.h
|
||||||
|
+++ b/PlugY/newInterfaces.h
|
||||||
|
@@ -9,20 +9,94 @@
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define MILIEU(X,L,N) (X + ((N<L)? (L-N)/2 : 0))
|
||||||
|
-#define isOnStatsPage(x,y) ((x<400) && (y<553))
|
||||||
|
+#define isOnStatsPage(x,y) (x<RX(512))
|
||||||
|
|
||||||
|
extern DWORD bDontPrintBorder;
|
||||||
|
+extern int selectedPage;
|
||||||
|
extern int extraHiddenPage;
|
||||||
|
+extern int curRunesPage;
|
||||||
|
+extern int maxRunesPage;
|
||||||
|
|
||||||
|
void GoNextStatPage();
|
||||||
|
void GoPreviousStatPage();
|
||||||
|
void GoStatPage(int page);
|
||||||
|
int GetCurrentPage();
|
||||||
|
|
||||||
|
+struct BtnState
|
||||||
|
+{
|
||||||
|
+ union{
|
||||||
|
+ DWORD all;
|
||||||
|
+ struct{
|
||||||
|
+ DWORD AssSTR:1;
|
||||||
|
+ DWORD AssDEX:1;
|
||||||
|
+ DWORD AssVIT:1;
|
||||||
|
+ DWORD AssENE:1;
|
||||||
|
+ DWORD UnaSTR:1;
|
||||||
|
+ DWORD UnaDEX:1;
|
||||||
|
+ DWORD UnaVIT:1;
|
||||||
|
+ DWORD UnaENE:1;
|
||||||
|
+ DWORD close:1;
|
||||||
|
+ DWORD previousPage:1;
|
||||||
|
+ DWORD nextPage:1;
|
||||||
|
+ DWORD prevRunes:1;
|
||||||
|
+ DWORD nextRunes:1;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+};
|
||||||
|
+extern BtnState isDownBtn;
|
||||||
|
+
|
||||||
|
extern bool active_newInterfaces;
|
||||||
|
extern bool selectMainPageOnOpenning;
|
||||||
|
extern bool printBackgroundOnMainPage;
|
||||||
|
|
||||||
|
+extern int posXNextPageBtn;
|
||||||
|
+extern int posYNextPageBtn;
|
||||||
|
+extern int posXPrevPageBtn;
|
||||||
|
+extern int posYPrevPageBtn;
|
||||||
|
+extern int posXClosePageBtn;
|
||||||
|
+extern int posYClosePageBtn;
|
||||||
|
+extern int posXNextRuneBtn;
|
||||||
|
+extern int posYNextRuneBtn;
|
||||||
|
+extern int posXPrevRuneBtn;
|
||||||
|
+extern int posYPrevRuneBtn;
|
||||||
|
+extern int posXRunesList;
|
||||||
|
+extern int posYRunesList;
|
||||||
|
+extern int runesPerPage;
|
||||||
|
+
|
||||||
|
+DWORD getXNextPageBtn();
|
||||||
|
+DWORD getYNextPageBtn();
|
||||||
|
+DWORD getXPreviousPageBtn();
|
||||||
|
+DWORD getYPreviousPageBtn();
|
||||||
|
+DWORD getXCloseBtn();
|
||||||
|
+DWORD getYCloseBtn();
|
||||||
|
+DWORD getXNextRunesBtn();
|
||||||
|
+DWORD getYNextRunesBtn();
|
||||||
|
+DWORD getXPrevRunesBtn();
|
||||||
|
+DWORD getYPrevRunesBtn();
|
||||||
|
+
|
||||||
|
+#define getLCloseBtn() 32
|
||||||
|
+#define getHCloseBtn() 32
|
||||||
|
+#define isOnCloseBtn(x,y) isOnRect(x, y, getXCloseBtn(), getYCloseBtn(), getLCloseBtn(), getHCloseBtn())
|
||||||
|
+
|
||||||
|
+#define getLPreviousPageBtn() 32
|
||||||
|
+#define getHPreviousPageBtn() 32
|
||||||
|
+#define isOnPreviousPageBtn(x,y) isOnRect(x, y, getXPreviousPageBtn(), getYPreviousPageBtn(), getLPreviousPageBtn(), getHPreviousPageBtn())
|
||||||
|
+
|
||||||
|
+#define getLNextPageBtn() 32
|
||||||
|
+#define getHNextPageBtn() 32
|
||||||
|
+#define isOnNextPageBtn(x,y) isOnRect(x, y, getXNextPageBtn(), getYNextPageBtn(), getLNextPageBtn(), getHNextPageBtn())
|
||||||
|
+
|
||||||
|
+#define getLPrevRunesBtn() 32
|
||||||
|
+#define getHPrevRunesBtn() 32
|
||||||
|
+#define isOnPrevRunesBtn(x,y) isOnRect(x, y, getXPrevRunesBtn(), getYPrevRunesBtn(), getLPrevRunesBtn(), getHPrevRunesBtn())
|
||||||
|
+
|
||||||
|
+#define getLNextRunesBtn() 32
|
||||||
|
+#define getHNextRunesBtn() 32
|
||||||
|
+#define isOnNextRunesBtn(x,y) isOnRect(x, y, getXNextRunesBtn(), getYNextRunesBtn(), getLNextRunesBtn(), getHNextRunesBtn())
|
||||||
|
+
|
||||||
|
+DWORD STDCALL statsLeftDown(sWinMessage* msg);
|
||||||
|
+DWORD STDCALL statsLeftUp(sWinMessage* msg);
|
||||||
|
+
|
||||||
|
void Install_NewInterfaces();
|
||||||
|
|
||||||
|
/*================================= END OF FILE =================================*/
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/PlugY/parameters.h b/PlugY/parameters.h
|
||||||
|
index d426c99..1cf884c 100644
|
||||||
|
--- a/PlugY/parameters.h
|
||||||
|
+++ b/PlugY/parameters.h
|
||||||
|
@@ -6,7 +6,7 @@
|
||||||
|
=================================================================*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
-#define PLUGY_VERSION "14.03"
|
||||||
|
+#define PLUGY_VERSION "14.03 HD"
|
||||||
|
|
||||||
|
enum TargetMod
|
||||||
|
{
|
20
PlugY/Backup/PlugY.sln
Normal file
20
PlugY/Backup/PlugY.sln
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
|
# Visual C++ Express 2008
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PlugY", "PlugY.vcproj", "{EB63DF4E-A019-4522-A140-9E8C7350B331}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{EB63DF4E-A019-4522-A140-9E8C7350B331}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{EB63DF4E-A019-4522-A140-9E8C7350B331}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{EB63DF4E-A019-4522-A140-9E8C7350B331}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{EB63DF4E-A019-4522-A140-9E8C7350B331}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@ -291,6 +291,7 @@ void loadCustomLibraries()
|
|||||||
log_msg("\n\n");
|
log_msg("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void loadLibrary(LPCSTR libName, int* libVersion, DWORD* libOffset, int shift, DWORD v109b, DWORD v109d, DWORD v110, DWORD v111, DWORD v111b, DWORD v112, DWORD v113c)
|
void loadLibrary(LPCSTR libName, int* libVersion, DWORD* libOffset, int shift, DWORD v109b, DWORD v109d, DWORD v110, DWORD v111, DWORD v111b, DWORD v112, DWORD v113c)
|
||||||
{
|
{
|
||||||
*libOffset = (DWORD)LoadLibrary(libName);
|
*libOffset = (DWORD)LoadLibrary(libName);
|
||||||
@ -386,6 +387,273 @@ void initD2modules()
|
|||||||
|
|
||||||
log_msg("\n\n");
|
log_msg("\n\n");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
IMAGE_NT_HEADERS* GetHeader(LPBYTE pBase) {
|
||||||
|
if (pBase == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pBase;
|
||||||
|
|
||||||
|
if (IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
IMAGE_NT_HEADERS* pHeader = (IMAGE_NT_HEADERS*)(pBase + pDosHeader->e_lfanew);
|
||||||
|
if (IsBadReadPtr(pHeader, sizeof(IMAGE_NT_HEADERS)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (pHeader->Signature != IMAGE_NT_SIGNATURE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return pHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initD2modules()
|
||||||
|
{
|
||||||
|
log_msg("***** Get D2 Modules address and version *****\n\n");
|
||||||
|
|
||||||
|
offset_D2Client = (DWORD)LoadLibrary("D2Client.dll");
|
||||||
|
offset_D2CMP = (DWORD)LoadLibrary("D2CMP.dll");
|
||||||
|
offset_D2Common = (DWORD)LoadLibrary("D2Common.dll");
|
||||||
|
offset_D2Game = (DWORD)LoadLibrary("D2Game.dll");
|
||||||
|
offset_D2gfx = (DWORD)LoadLibrary("D2gfx.dll");
|
||||||
|
offset_D2Lang = (DWORD)LoadLibrary("D2Lang.dll");
|
||||||
|
offset_D2Launch = (DWORD)LoadLibrary("D2Launch.dll");
|
||||||
|
offset_D2Net = (DWORD)LoadLibrary("D2Net.dll");
|
||||||
|
offset_D2Win = (DWORD)LoadLibrary("D2Win.dll");
|
||||||
|
offset_Fog = (DWORD)LoadLibrary("Fog.dll");
|
||||||
|
offset_Storm = (DWORD)LoadLibrary("Storm.dll");
|
||||||
|
|
||||||
|
int count_109b = 0;
|
||||||
|
int count_109d = 0;
|
||||||
|
int count_110f = 0;
|
||||||
|
int count_111 = 0;
|
||||||
|
int count_111b = 0;
|
||||||
|
int count_112a = 0;
|
||||||
|
int count_113c = 0;
|
||||||
|
int count_113d = 0;
|
||||||
|
int count_114a = 0;
|
||||||
|
int count_114b = 0;
|
||||||
|
int count_114c = 0;
|
||||||
|
int count_114d = 0;
|
||||||
|
|
||||||
|
IMAGE_NT_HEADERS* pHeader;
|
||||||
|
|
||||||
|
if (offset_D2Client != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2Client);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C234D) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C16CD) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C1C1D) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045E6) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045EE) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045FA) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045F6) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000045DE) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_D2CMP != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2CMP);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00011361) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00011361) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00010E61) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C23) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_D2Common != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2Common);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00074D1D) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00074E2D) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000856DD) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C94) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C8D) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C97) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C8F) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000047C7) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_D2Game != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2Game);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C66AC) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000C6D5C) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000EDC2C) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000036E6) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000373D) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000374B) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000373C) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003747) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_D2gfx != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2gfx);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000054EB) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000054EB) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000054A5) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001807) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_D2Lang != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2Lang);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00005148) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00005138) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00005048) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A6A) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A5B) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A75) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A71) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A5A) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_D2Launch != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2Launch);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000172C3) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00017243) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00018DC7) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A84) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A85) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A85) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A87) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001A84) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_D2Net != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2Net);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002BCE) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002BCE) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00002C6E) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001676) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001676) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000167E) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001676) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000167E) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_D2Win != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_D2Win);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00014F38) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00014F38) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00012EC0) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000187E) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000187E) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000188E) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000187E) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00001887) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_Fog != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_Fog);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00013658) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000142E7) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000162B0) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003159) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003142) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000314A) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003162) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003142) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_Storm != NULL) {
|
||||||
|
pHeader = GetHeader((LPBYTE)offset_Storm);
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00013658) count_109b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000142E7) count_109d++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x000162B0) count_110f++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003159) count_111++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003142) count_111b++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0000314A) count_112a++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00003162) count_113c++;
|
||||||
|
if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x0003C3E0) count_113d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minimum_match_dll = 7;
|
||||||
|
|
||||||
|
if (count_109b >= minimum_match_dll) version_Game = V109b;
|
||||||
|
if (count_109d >= minimum_match_dll) version_Game = V109d;
|
||||||
|
if (count_110f >= minimum_match_dll) version_Game = V110;
|
||||||
|
if (count_111 >= minimum_match_dll) version_Game = V111;
|
||||||
|
if (count_111b >= minimum_match_dll) version_Game = V111b;
|
||||||
|
if (count_112a >= minimum_match_dll) version_Game = V112;
|
||||||
|
if (count_113c >= minimum_match_dll) version_Game = V113c;
|
||||||
|
if (count_113d >= minimum_match_dll) version_Game = V113d;
|
||||||
|
|
||||||
|
//version_SmackW32 = version_Game;
|
||||||
|
version_D2Common = version_Game;
|
||||||
|
//version_ijl11 = version_Game;
|
||||||
|
//version_D2Gdi = version_Game;
|
||||||
|
version_D2Win = version_Game;
|
||||||
|
//version_D2sound = version_Game;
|
||||||
|
//version_D2MCPCLI = version_Game;
|
||||||
|
version_D2Launch = version_Game;
|
||||||
|
version_D2gfx = version_Game;
|
||||||
|
version_D2Client = version_Game;
|
||||||
|
version_D2Net = version_Game;
|
||||||
|
version_D2Lang = version_Game;
|
||||||
|
version_D2Game = version_Game;
|
||||||
|
version_D2CMP = version_Game;
|
||||||
|
//version_Bnclient = version;
|
||||||
|
version_Fog = version_Game;
|
||||||
|
version_Storm = version_Game;
|
||||||
|
|
||||||
|
log_msg("DLL match for version 1.09b :\t%d\n", count_109b);
|
||||||
|
log_msg("DLL match for version 1.09d :\t%d\n", count_109d);
|
||||||
|
log_msg("DLL match for version 1.10f :\t%d\n", count_110f);
|
||||||
|
log_msg("DLL match for version 1.11 :\t%d\n", count_111);
|
||||||
|
log_msg("DLL match for version 1.11b :\t%d\n", count_111b);
|
||||||
|
log_msg("DLL match for version 1.12a :\t%d\n", count_112a);
|
||||||
|
log_msg("DLL match for version 1.13c :\t%d\n", count_113c);
|
||||||
|
log_msg("\n");
|
||||||
|
|
||||||
|
offset_Game = (DWORD)GetModuleHandle("Game.exe");
|
||||||
|
if (offset_Game != NULL) {
|
||||||
|
version_Game = GetD2Version((HMODULE)offset_Game);
|
||||||
|
log_msg("Game.exe loaded at:\t%08X (%s)\n", offset_Game, GetVersionString(version_Game));
|
||||||
|
if (version_Game >= V114a)
|
||||||
|
{
|
||||||
|
//version_SmackW32 = version_Game;
|
||||||
|
version_D2Common = version_Game;
|
||||||
|
//version_ijl11 = version_Game;
|
||||||
|
//version_D2Gdi = version_Game;
|
||||||
|
version_D2Win = version_Game;
|
||||||
|
//version_D2sound = version_Game;
|
||||||
|
//version_D2MCPCLI = version_Game;
|
||||||
|
version_D2Launch = version_Game;
|
||||||
|
version_D2gfx = version_Game;
|
||||||
|
version_D2Client = version_Game;
|
||||||
|
version_D2Net = version_Game;
|
||||||
|
version_D2Lang = version_Game;
|
||||||
|
version_D2Game = version_Game;
|
||||||
|
version_D2CMP = version_Game;
|
||||||
|
//version_Bnclient = version;
|
||||||
|
version_Fog = version_Game;
|
||||||
|
version_Storm = version_Game;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (offset_Game != NULL) {
|
||||||
|
// pHeader = GetHeader((LPBYTE)offset_Game);
|
||||||
|
// if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00291342) count_114a++;
|
||||||
|
// if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x002854F2) count_114b++;
|
||||||
|
// if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x002850E2) count_114c++;
|
||||||
|
// if (pHeader->OptionalHeader.AddressOfEntryPoint == 0x00282985) count_114d++;
|
||||||
|
//}
|
||||||
|
|
||||||
|
log_msg("Version game is:\t(%s)\n\n", GetVersionString(version_Game));
|
||||||
|
|
||||||
|
if (version_Game == UNKNOWN)
|
||||||
|
{
|
||||||
|
MessageBoxA(NULL, "This version of Diablo II is not supported by Plugy. Please upgrade or downgrade to a supported version.", "Plugy 14.03", MB_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////// EXPORTS FUNCTIONS ////////////////////////////////////
|
//////////////////////////////////// EXPORTS FUNCTIONS ////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ bool active_sharedStash = false;
|
|||||||
bool separateHardSoftStash = false;
|
bool separateHardSoftStash = false;
|
||||||
bool active_sharedGold=false;
|
bool active_sharedGold=false;
|
||||||
char* sharedStashFilename = NULL;
|
char* sharedStashFilename = NULL;
|
||||||
|
DWORD saveFileStackSize = 0x2000;
|
||||||
|
|
||||||
typedef int (*TchangeToSelectedStash)(Unit* ptChar, Stash* newStash, DWORD bOnlyItems, DWORD bIsClient);
|
typedef int (*TchangeToSelectedStash)(Unit* ptChar, Stash* newStash, DWORD bOnlyItems, DWORD bIsClient);
|
||||||
|
|
||||||
@ -355,11 +356,7 @@ DWORD loadStashList(Unit* ptChar, BYTE* data, DWORD maxSize, DWORD* curSize, boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbStash == 1)
|
changeToSelectedStash(ptChar, isShared?PCPY->sharedStash:PCPY->selfStash, 0, false);
|
||||||
{
|
|
||||||
newStash = addStash(ptChar, isShared, true, newStash);
|
|
||||||
changeToSelectedStash(ptChar, newStash, 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -426,7 +423,7 @@ void saveStashList(Unit* ptChar, Stash* ptStash, BYTE** data, DWORD* maxSize, DW
|
|||||||
|
|
||||||
while(ptStash)
|
while(ptStash)
|
||||||
{
|
{
|
||||||
if (*curSize + 0x2000 > *maxSize)
|
if (*curSize + saveFileStackSize > *maxSize)
|
||||||
{
|
{
|
||||||
BYTE* oldData = *data;
|
BYTE* oldData = *data;
|
||||||
*maxSize *= 2;
|
*maxSize *= 2;
|
||||||
@ -1160,7 +1157,8 @@ FCT_ASM ( caller_carry1OutOfStash_114 )
|
|||||||
CALL D2ItemGetPage
|
CALL D2ItemGetPage
|
||||||
CMP AL,4
|
CMP AL,4
|
||||||
JNZ continue_carry1OutOfStash
|
JNZ continue_carry1OutOfStash
|
||||||
SUB DWORD PTR SS:[ESP],0xC
|
//SUB DWORD PTR SS:[ESP],0xC
|
||||||
|
ADD DWORD PTR SS:[ESP],0x17D
|
||||||
RETN
|
RETN
|
||||||
continue_carry1OutOfStash:
|
continue_carry1OutOfStash:
|
||||||
MOV EDI,DWORD PTR SS:[EBP-4]
|
MOV EDI,DWORD PTR SS:[EBP-4]
|
||||||
|
@ -49,9 +49,10 @@ Unit* STDCALL skillsPageMouseDown(sWinMessage* msg)
|
|||||||
if (active_SkillsPoints && !onRealm && D2isLODGame() && isOnButtonUnassignSkill(D2GetMouseX(),D2GetMouseY()))
|
if (active_SkillsPoints && !onRealm && D2isLODGame() && isOnButtonUnassignSkill(D2GetMouseX(),D2GetMouseY()))
|
||||||
{
|
{
|
||||||
log_msg("push down left button unassign skill\n");
|
log_msg("push down left button unassign skill\n");
|
||||||
btnSkillIsDown = 1;
|
//btnSkillIsDown = 1;
|
||||||
D2PlaySound(4,0,0,0,0);
|
D2PlaySound(4,0,0,0,0);
|
||||||
freeMessage(msg);
|
freeMessage(msg);
|
||||||
|
updateServer(US_UNASSIGN_SKILLS);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return ptChar;
|
return ptChar;
|
||||||
@ -233,6 +234,7 @@ void Install_InterfaceSkills()
|
|||||||
//6FAE1112 > C745 18 00000000 MOV DWORD PTR SS:[EBP+18],0
|
//6FAE1112 > C745 18 00000000 MOV DWORD PTR SS:[EBP+18],0
|
||||||
//004ABC1A |> C746 18 00000000 MOV DWORD PTR DS:[ESI+18],0
|
//004ABC1A |> C746 18 00000000 MOV DWORD PTR DS:[ESI+18],0
|
||||||
|
|
||||||
|
/* Conflicts with D2ExpRes
|
||||||
// Manage mouse up
|
// Manage mouse up
|
||||||
mem_seek R8(D2Client, 7BC40, 7BC40, 78466, 17558, 8C078, 80248, 795F8, 30AA8, ABC96);
|
mem_seek R8(D2Client, 7BC40, 7BC40, 78466, 17558, 8C078, 80248, 795F8, 30AA8, ABC96);
|
||||||
MEMJ_REF4( D2FreeWinMessage, caller_skillsPageMouseUp);//0xFFF93B0A
|
MEMJ_REF4( D2FreeWinMessage, caller_skillsPageMouseUp);//0xFFF93B0A
|
||||||
@ -243,6 +245,7 @@ void Install_InterfaceSkills()
|
|||||||
//6FB295F7 .^E9 8828F9FF JMP <JMP.&Storm.#511>
|
//6FB295F7 .^E9 8828F9FF JMP <JMP.&Storm.#511>
|
||||||
//6FAE0AA7 .^E9 E0B2FDFF JMP <JMP.&Storm.#511>
|
//6FAE0AA7 .^E9 E0B2FDFF JMP <JMP.&Storm.#511>
|
||||||
//004ABC95 |. E8 F645F7FF CALL Game.00420290
|
//004ABC95 |. E8 F645F7FF CALL Game.00420290
|
||||||
|
*/
|
||||||
|
|
||||||
log_msg("\n");
|
log_msg("\n");
|
||||||
|
|
||||||
|
@ -13,6 +13,13 @@
|
|||||||
#include "plugYFiles.h" // Install_PlugYImagesFiles()
|
#include "plugYFiles.h" // Install_PlugYImagesFiles()
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <ctime> // Include ctime for srand and rand functions
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
@ -69,6 +76,9 @@ int posYStashGoldField = -1;
|
|||||||
int posWStashGoldField = 152;
|
int posWStashGoldField = 152;
|
||||||
int posHStashGoldField = 18;
|
int posHStashGoldField = 18;
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DWORD PersonalNormalPageColor = WHITE;
|
DWORD PersonalNormalPageColor = WHITE;
|
||||||
DWORD PersonalIndexPageColor = DARK_GREEN;
|
DWORD PersonalIndexPageColor = DARK_GREEN;
|
||||||
@ -331,6 +341,671 @@ DWORD STDCALL manageBtnUp(sWinMessage* msg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int frame = 0;
|
||||||
|
long nEndTime = 0;
|
||||||
|
int nTip = 0;
|
||||||
|
long DURATION = 15000;
|
||||||
|
std::vector<std::wstring> diablo2Tips = {
|
||||||
|
L"Consume spirits like potions to increase Spirits Quaffed stat in character stat sheet page.",
|
||||||
|
L"Cube Souls with Energy Sphere to capture Soul Energy and use it to create powerful items. Recipes will come later.",
|
||||||
|
L"Collect Demon souls from demons and regular souls from monsters; Demon souls morph you into the demon whose soul you have.",
|
||||||
|
L"Spirits can be consumed like potions or put on as rings to add to Souls Consumed count.",
|
||||||
|
L"Cube underused magic, rare, set, unique items with Energy Sphere to collect their magic energy for creating new items.",
|
||||||
|
L"Cube white items with Energy Sphere to break down into simple item parts for creating base item types with smithing hammers.",
|
||||||
|
L"Use Rare Shard, Set Stone, or Unique Particle with smithing hammers and Energy Sphere to create rare, set, unique items.",
|
||||||
|
L"Acquire smithing hammers to create base item types, each requiring X number of collected item parts.",
|
||||||
|
L"Capture Talisman of Corruption and cube to corrupt items for new magical properties; a gamble with potential rewards.",
|
||||||
|
L"Use Experience Book for extra experience, Infinite Mana Elixir for massive mana regeneration, and Regeneration Elixir for life regeneration.",
|
||||||
|
L"Use Elixirs to permanently boost stats like Strength, Dexterity, Health, Stamina, Mana, and resistances.",
|
||||||
|
L"Equip Sling Stone for increased throwing potion damage, various elemental stones for resistance boosts, and Mastery Stones for skill damage boosts.",
|
||||||
|
L"Use Portable Shrines for temporary buffs like increased defense, damage, experience gained, mana regeneration, and skill levels.",
|
||||||
|
L"In Ironman, gold is nonexistent, town portals are disabled; rely on items, waypoints, and strategic gameplay to progress.",
|
||||||
|
L"Inventory management is critical; use items conservatively and intelligently switch gear based on monster types and situations.",
|
||||||
|
L"Hybrid character builds and creative weapon choices are encouraged in Ironman; experiment and adapt strategies accordingly.",
|
||||||
|
L"Protect hirelings actively as they are essential allies; they can be hired for 0 gold but lose items if they die.",
|
||||||
|
L"Coordinate with teammates in MultiPlayer; teamwork, resource sharing, and strategy are key to success in Ironman.",
|
||||||
|
L"In Hardcore Ironman, caution and careful planning are crucial; falling back, potion management, and adaptability are essential for survival.",
|
||||||
|
L"Utilize waypoints for inter-level travel in Ironman; waypoints become crucial for navigating the game world.",
|
||||||
|
L"Always have backup gear in your backpack in Ironman; switch out gear intelligently based on monster types and challenges.",
|
||||||
|
L"Experiment with different weapons and gear in Ironman; adapt your strategies to overcome various monster types and situations.",
|
||||||
|
L"Keep a close watch on your hirelings' health in Ironman; losing a hireling means losing their equipped items as well.",
|
||||||
|
L"Plan and communicate effectively in MultiPlayer Ironman games; teamwork and coordination are key to overcoming challenges.",
|
||||||
|
L"Be conservative with resources in Hardcore Ironman; strategic planning and careful execution are vital for survival.",
|
||||||
|
L"Craft rare, set, unique items using collected item parts and smithing hammers in Ironman; choose item types wisely for your build.",
|
||||||
|
L"Capture and corrupt items using Talisman of Corruption for new magical properties in Ironman; take calculated risks for potential rewards.",
|
||||||
|
L"Use Portable Shrines strategically in Ironman for temporary buffs; timing and placement of shrines can turn the tide of battle.",
|
||||||
|
L"Keep track of Souls Consumed and Spirits Quaffed stats in Ironman; they reflect your progress and resource utilization in the game.",
|
||||||
|
L"Enhance your character with Elixirs and Stones for permanent stat boosts and bonuses in Ironman; plan your upgrades wisely.",
|
||||||
|
L"Master the art of retreating and regrouping in Hardcore Ironman; strategic fallbacks can save your character's life in tough situations.",
|
||||||
|
L"Stay vigilant and adapt your strategies in MultiPlayer Ironman games; synergy and cooperation with teammates are essential for success.",
|
||||||
|
L"Experiment with different skill synergies and builds in Ironman; explore the full potential of your character's abilities.",
|
||||||
|
L"Craft and equip powerful unique items using collected Magic Essence Points and recipes in Ironman; customize your gear for optimal performance.",
|
||||||
|
L"Explore new areas and challenges in Ironman; discover hidden secrets and encounters by venturing off the beaten path.",
|
||||||
|
L"Combine different magic, rare, set, unique items with the Energy Sphere to collect their magic energy in Ironman.",
|
||||||
|
L"Cube white items with the Energy Sphere to break them down into simple item parts for crafting in Ironman.",
|
||||||
|
L"Use smithing hammers with the Energy Sphere to create base item types for crafting in Ironman.",
|
||||||
|
L"Combine Rare Shard, Set Stone, or Unique Particle with base item types and Magic Essence Points to create rare, set, unique, items in Ironman.",
|
||||||
|
L"Cube Souls with the Energy Sphere to capture their energy and use it for creating more powerful items in Ironman.",
|
||||||
|
|
||||||
|
L"Prioritize survivability over damage output. In Hardcore Ironman, staying alive is paramount.",
|
||||||
|
L"Scout ahead before engaging enemies. Knowing what's coming can help you prepare and avoid deadly surprises.",
|
||||||
|
L"Always have an escape route planned. Without town portals, strategic positioning and waypoints are your lifelines.",
|
||||||
|
L"Collect and hoard potions. You never know when you'll need a sudden burst of healing or mana.",
|
||||||
|
L"Experiment with different skill combinations. Adaptability is key to overcoming the diverse challenges of Hardcore mode.",
|
||||||
|
L"Know your enemy. Understanding monster types and behaviors can give you a significant advantage in combat.",
|
||||||
|
L"Stock up on antidote and thawing potions. Poison and cold damage are particularly deadly in Hardcore.",
|
||||||
|
L"Maintain a diverse arsenal of weapons and armor. You never know when you'll need a specific resistance or damage type.",
|
||||||
|
L"Train your mercenary well. They can be a valuable asset in battles, providing support and distraction when needed.",
|
||||||
|
L"Don't be afraid to retreat. Sometimes, discretion is the better part of valor in Hardcore Ironman.",
|
||||||
|
L"Watch your surroundings. Traps and ambushes can quickly turn a routine exploration into a fight for survival.",
|
||||||
|
L"Stay informed about the latest patches and updates. Changes to game mechanics can have a significant impact on Hardcore gameplay.",
|
||||||
|
L"Join Hardcore Ironman communities. Sharing tips and strategies with fellow players can enhance your survival chances.",
|
||||||
|
L"Back up your save files regularly. Losing a Hardcore character to a technical glitch can be devastating.",
|
||||||
|
L"Practice patience and caution. Rushing into battles recklessly is a surefire way to meet an untimely demise.",
|
||||||
|
L"Embrace the challenge. Hardcore Ironman may be unforgiving, but overcoming its trials is immensely rewarding.",
|
||||||
|
L"Develop a keen eye for loot. Every item could be the difference between life and death in Hardcore mode.",
|
||||||
|
L"Learn from your mistakes. Each death is an opportunity to refine your strategies and become a better Hardcore player.",
|
||||||
|
L"Respect your limits. Sometimes, it's better to retreat and live to fight another day than to press on recklessly.",
|
||||||
|
L"Communicate with your party. Clear communication can prevent misunderstandings and ensure everyone's safety.",
|
||||||
|
L"Stay focused. Even the smallest lapse in concentration can be fatal in Hardcore Ironman.",
|
||||||
|
L"Build a strong network of allies. Having friends to watch your back can make all the difference in Hardcore mode.",
|
||||||
|
L"Experiment with different character builds. There's no one-size-fits-all approach to Hardcore survival.",
|
||||||
|
L"Avoid unnecessary risks. The thrill of danger may be tempting, but it's not worth losing your Hardcore character over.",
|
||||||
|
L"Take breaks when needed. Hardcore Ironman can be mentally exhausting, so don't hesitate to step away and recharge.",
|
||||||
|
L"Stay vigilant at all times. Complacency is the enemy of survival in Hardcore mode.",
|
||||||
|
L"Adapt to changing circumstances. Flexibility is key to thriving in the ever-evolving world of Hardcore Ironman.",
|
||||||
|
L"Trust your instincts. Sometimes, your gut feeling is your best guide in Hardcore survival.",
|
||||||
|
L"Never underestimate your enemies. Even the weakest foes can pose a threat in Hardcore mode.",
|
||||||
|
L"Explore every corner of the map. You never know what valuable resources or hidden dangers you might uncover.",
|
||||||
|
L"Prepare for the worst. Always have a backup plan in case things go south in Hardcore Ironman.",
|
||||||
|
L"Keep your equipment in top condition. A well-maintained arsenal can mean the difference between victory and defeat.",
|
||||||
|
L"Study the terrain. Knowing the lay of the land can give you a strategic advantage in Hardcore battles.",
|
||||||
|
L"Coordinate your attacks with your party members. Working together is essential for success in Hardcore mode.",
|
||||||
|
L"Be mindful of your surroundings. Environmental hazards can be just as deadly as enemy attacks in Hardcore Ironman.",
|
||||||
|
L"Stay cool under pressure. Panicking will only lead to mistakes and, ultimately, your demise in Hardcore mode.",
|
||||||
|
L"Focus on survival skills first. Offensive prowess means nothing if you can't stay alive in Hardcore Ironman.",
|
||||||
|
L"Be wary of traps and ambushes. The world of Hardcore is full of dangers lurking around every corner.",
|
||||||
|
L"Pay attention to your health and mana reserves. Running out at the wrong moment can be fatal in Hardcore mode.",
|
||||||
|
L"Plan your routes carefully. Avoiding unnecessary risks is crucial in Hardcore Ironman.",
|
||||||
|
L"Learn from the mistakes of others. Watching other Hardcore players can provide valuable insights into effective survival strategies.",
|
||||||
|
L"Stay disciplined in your gameplay. Taking unnecessary risks can quickly lead to your demise in Hardcore mode.",
|
||||||
|
L"Keep a clear head. Emotional decisions are rarely the right ones in Hardcore Ironman.",
|
||||||
|
L"Learn to prioritize threats. Not every enemy is worth engaging in Hardcore mode.",
|
||||||
|
L"Practice patience. Rushing into battles blindly is a surefire way to meet a premature end in Hardcore Ironman.",
|
||||||
|
L"Stockpile essential supplies. You never know when you'll need that extra potion or scroll in Hardcore mode.",
|
||||||
|
L"Be proactive in your approach. Waiting for danger to come to you is a recipe for disaster in Hardcore Ironman.",
|
||||||
|
L"Stay informed about the latest strategies and tactics. Knowledge is power in Hardcore mode.",
|
||||||
|
L"Stay humble. Arrogance is a sure path to failure in Hardcore Ironman.",
|
||||||
|
L"Trust your instincts. If something feels wrong, it probably is in Hardcore mode.",
|
||||||
|
L"Take calculated risks. Sometimes, a bold move is necessary to secure victory in Hardcore Ironman.",
|
||||||
|
L"Keep your wits about you. Panic is the enemy of survival in Hardcore mode.",
|
||||||
|
L"Never let your guard down. Complacency is a luxury you can't afford in Hardcore Ironman.",
|
||||||
|
L"Respect the power of your enemies. Underestimating them is a sure path to defeat in Hardcore mode.",
|
||||||
|
L"Stay focused on your goals. Losing sight of your objectives can lead to costly mistakes in Hardcore Ironman.",
|
||||||
|
L"Adapt to adversity. Flexibility is key to surviving the ever-changing challenges of Hardcore mode.",
|
||||||
|
L"Stay vigilant. Danger can lurk around every corner in Hardcore Ironman.",
|
||||||
|
L"Know when to retreat. Sometimes, discretion is the better part of valor in Hardcore mode.",
|
||||||
|
L"Be mindful of your surroundings. Environmental hazards can be just as deadly as enemy attacks in Hardcore Ironman.",
|
||||||
|
L"Stay cool under pressure. Panicking will only lead to mistakes and, ultimately, your demise in Hardcore mode.",
|
||||||
|
L"Focus on survival skills first. Offensive prowess means nothing if you can't stay alive in Hardcore Ironman.",
|
||||||
|
L"Be wary of traps and ambushes. The world of Hardcore is full of dangers lurking around every corner.",
|
||||||
|
L"Pay attention to your health and mana reserves. Running out at the wrong moment can be fatal in Hardcore mode.",
|
||||||
|
L"Plan your routes carefully. Avoiding unnecessary risks is crucial in Hardcore Ironman.",
|
||||||
|
L"Learn from the mistakes of others. Watching other Hardcore players can provide valuable insights into effective survival strategies.",
|
||||||
|
L"Stay disciplined in your gameplay. Taking unnecessary risks can quickly lead to your demise in Hardcore mode.",
|
||||||
|
L"Keep a clear head. Emotional decisions are rarely the right ones in Hardcore Ironman.",
|
||||||
|
L"Learn to prioritize threats. Not every enemy is worth engaging in Hardcore mode.",
|
||||||
|
L"Practice patience. Rushing into battles blindly is a surefire way to meet a premature end in Hardcore Ironman.",
|
||||||
|
L"Stockpile essential supplies. You never know when you'll need that extra potion or scroll in Hardcore mode.",
|
||||||
|
L"Be proactive in your approach. Waiting for danger to come to you is a recipe for disaster in Hardcore Ironman.",
|
||||||
|
L"Stay informed about the latest strategies and tactics. Knowledge is power in Hardcore mode.",
|
||||||
|
L"Stay humble. Arrogance is a sure path to failure in Hardcore Ironman.",
|
||||||
|
L"Trust your instincts. If something feels wrong, it probably is in Hardcore mode.",
|
||||||
|
L"Take calculated risks. Sometimes, a bold move is necessary to secure victory in Hardcore Ironman.",
|
||||||
|
L"Keep your wits about you. Panic is the enemy of survival in Hardcore mode.",
|
||||||
|
L"Never let your guard down. Complacency is a luxury you can't afford in Hardcore Ironman.",
|
||||||
|
L"Respect the power of your enemies. Underestimating them is a sure path to defeat in Hardcore mode.",
|
||||||
|
L"Stay focused on your goals. Losing sight of your objectives can lead to costly mistakes in Hardcore Ironman.",
|
||||||
|
L"Adapt to adversity. Flexibility is key to surviving the ever-changing challenges of Hardcore mode.",
|
||||||
|
L"Stay vigilant. Danger can lurk around every corner in Hardcore Ironman.",
|
||||||
|
L"Know when to retreat. Sometimes, discretion is the better part of valor in Hardcore mode.",
|
||||||
|
|
||||||
|
L"In Hardcore Ironman, survival is your top priority. Every decision you make should revolve around keeping your character alive in the harsh world of Diablo 2.",
|
||||||
|
L"Take your time to carefully explore each area, scanning for potential threats and planning your route accordingly. Rushing into battles or unknown territory is a surefire way to meet an untimely demise.",
|
||||||
|
L"Without the safety net of town portals, strategic planning is essential. Always have an escape route in mind, whether it's a nearby waypoint or a path back to a safe area.",
|
||||||
|
L"Inventory management is critical in Hardcore mode. Keep your inventory organized and prioritize essential items like potions, scrolls, and emergency gear.",
|
||||||
|
L"Be cautious when engaging enemies. Assess their strengths and weaknesses before committing to battle, and don't hesitate to retreat if the odds are against you.",
|
||||||
|
L"Experiment with different skill combinations and character builds to find what works best for your playstyle. Adaptability is key to surviving the challenges of Hardcore Ironman.",
|
||||||
|
L"Study your surroundings and learn to anticipate potential dangers. Traps, ambushes, and environmental hazards can quickly turn a routine exploration into a fight for survival.",
|
||||||
|
L"Maintain a diverse arsenal of weapons and armor to handle a variety of threats. Prioritize gear that boosts your resistances and provides additional layers of protection.",
|
||||||
|
L"Train your mercenary companion well and equip them with gear that complements your own strengths and weaknesses. They can provide invaluable support in battles and serve as a valuable distraction for enemies.",
|
||||||
|
L"Communication is key, especially in multiplayer games. Coordinate with your party members and share information about enemy locations, tactics, and potential dangers.",
|
||||||
|
L"Stay informed about the latest strategies, tactics, and updates. Knowledge is power in Hardcore mode, and being aware of changes to the game can give you a significant advantage.",
|
||||||
|
L"Develop a backup plan for emergencies. Whether it's a stash of emergency potions or a hidden escape route, always have a contingency plan in place.",
|
||||||
|
L"Practice patience and resilience. Setbacks and challenges are inevitable in Hardcore Ironman, but perseverance will ultimately lead to success.",
|
||||||
|
L"Build a network of allies and fellow Hardcore players. Sharing tips, strategies, and experiences can help you learn and grow as a player.",
|
||||||
|
L"Trust your instincts and intuition. If something feels wrong or too risky, it's better to err on the side of caution.",
|
||||||
|
L"Embrace the challenge of Hardcore Ironman and enjoy the thrill of survival. The adrenaline rush of narrowly escaping death is what makes Hardcore mode so rewarding.",
|
||||||
|
L"Stay disciplined in your gameplay and avoid taking unnecessary risks. Remember, one wrong move can cost you your character in Hardcore mode.",
|
||||||
|
L"Keep a cool head and stay focused, especially in intense or dangerous situations. Panic and fear are your worst enemies in Hardcore Ironman.",
|
||||||
|
L"Learn from your mistakes and use them as opportunities for growth. Every death is a chance to refine your strategies and improve your gameplay.",
|
||||||
|
L"Be mindful of your surroundings at all times. Even the smallest oversight can prove fatal in Hardcore mode.",
|
||||||
|
L"Prioritize defensive stats and survival skills over offensive abilities. A strong defense is crucial for staying alive in Hardcore Ironman.",
|
||||||
|
L"Stockpile essential supplies like potions, scrolls, and emergency gear. You never know when you'll need them in Hardcore mode.",
|
||||||
|
L"Plan your routes carefully and avoid unnecessary risks. Rushing headlong into danger is a recipe for disaster in Hardcore Ironman.",
|
||||||
|
L"Stay adaptable and be prepared to adjust your tactics on the fly. The ability to think quickly and react to changing situations is essential for survival in Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and work together to overcome challenges. Teamwork is key to success in Hardcore Ironman.",
|
||||||
|
L"Be cautious when exploring new areas, especially in Hardcore mode. Unknown dangers lurk around every corner, and it's better to proceed with caution than to rush in blindly.",
|
||||||
|
L"Equip gear that complements your playstyle and provides the best possible protection against enemy attacks. Prioritize resistances and defensive bonuses over offensive stats in Hardcore mode.",
|
||||||
|
L"Stay informed about the strengths and weaknesses of different enemy types. Knowing your foes is essential for developing effective strategies and staying alive in Hardcore Ironman.",
|
||||||
|
L"Practice patience and perseverance in Hardcore mode. Success often requires multiple attempts and learning from your mistakes.",
|
||||||
|
L"Develop a backup plan for emergencies, such as a stash of emergency potions or a hidden escape route. Always have a contingency plan in place in Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and communicate effectively to overcome challenges together. Teamwork is essential for survival in Hardcore Ironman.",
|
||||||
|
L"Stay vigilant and be prepared for anything in Hardcore mode. Unexpected dangers and challenges can arise at any moment, and it's important to stay alert.",
|
||||||
|
L"Learn from your mistakes and use them as opportunities for growth. Every death is a chance to refine your strategies and become a better Hardcore player.",
|
||||||
|
L"Stock up on essential supplies like potions, scrolls, and emergency gear. You never know when you'll need them in Hardcore mode.",
|
||||||
|
L"Plan your routes carefully and avoid unnecessary risks. Rushing into danger blindly is a surefire way to meet an untimely demise in Hardcore Ironman.",
|
||||||
|
L"Stay adaptable and be prepared to adjust your tactics on the fly. Flexibility is key to surviving the ever-changing challenges of Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and work together to overcome challenges. Teamwork is essential for success in Hardcore Ironman.",
|
||||||
|
L"Be cautious when exploring new areas, especially in Hardcore mode. Unknown dangers lurk around every corner, and it's better to proceed with caution than to rush in blindly.",
|
||||||
|
L"Equip gear that complements your playstyle and provides the best possible protection against enemy attacks. Prioritize defensive bonuses and resistances over offensive stats in Hardcore mode.",
|
||||||
|
L"Stay informed about the strengths and weaknesses of different enemy types. Knowing your foes is essential for developing effective strategies and staying alive in Hardcore Ironman.",
|
||||||
|
L"Practice patience and perseverance in Hardcore mode. Success often requires multiple attempts and learning from your mistakes.",
|
||||||
|
L"Develop a backup plan for emergencies, such as a stash of emergency potions or a hidden escape route. Always have a contingency plan in place in Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and communicate effectively to overcome challenges together. Teamwork is essential for survival in Hardcore Ironman.",
|
||||||
|
L"Stay vigilant and be prepared for anything in Hardcore mode. Unexpected dangers and challenges can arise at any moment, and it's important to stay alert.",
|
||||||
|
L"Learn from your mistakes and use them as opportunities for growth. Every death is a chance to refine your strategies and become a better Hardcore player.",
|
||||||
|
L"Stock up on essential supplies like potions, scrolls, and emergency gear. You never know when you'll need them in Hardcore mode.",
|
||||||
|
L"Plan your routes carefully and avoid unnecessary risks. Rushing into danger blindly is a surefire way to meet an untimely demise in Hardcore Ironman.",
|
||||||
|
L"Stay adaptable and be prepared to adjust your tactics on the fly. Flexibility is key to surviving the ever-changing challenges of Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and work together to overcome challenges. Teamwork is essential for success in Hardcore Ironman.",
|
||||||
|
L"Be cautious when exploring new areas, especially in Hardcore mode. Unknown dangers lurk around every corner, and it's better to proceed with caution than to rush in blindly.",
|
||||||
|
L"Equip gear that complements your playstyle and provides the best possible protection against enemy attacks. Prioritize defensive bonuses and resistances over offensive stats in Hardcore mode.",
|
||||||
|
L"Stay informed about the strengths and weaknesses of different enemy types. Knowing your foes is essential for developing effective strategies and staying alive in Hardcore Ironman.",
|
||||||
|
L"Practice patience and perseverance in Hardcore mode. Success often requires multiple attempts and learning from your mistakes.",
|
||||||
|
L"Develop a backup plan for emergencies, such as a stash of emergency potions or a hidden escape route. Always have a contingency plan in place in Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and communicate effectively to overcome challenges together. Teamwork is essential for survival in Hardcore Ironman.",
|
||||||
|
L"Stay vigilant and be prepared for anything in Hardcore mode. Unexpected dangers and challenges can arise at any moment, and it's important to stay alert.",
|
||||||
|
L"Learn from your mistakes and use them as opportunities for growth. Every death is a chance to refine your strategies and become a better Hardcore player.",
|
||||||
|
L"Stock up on essential supplies like potions, scrolls, and emergency gear. You never know when you'll need them in Hardcore mode.",
|
||||||
|
L"Plan your routes carefully and avoid unnecessary risks. Rushing into danger blindly is a surefire way to meet an untimely demise in Hardcore Ironman.",
|
||||||
|
L"Stay adaptable and be prepared to adjust your tactics on the fly. Flexibility is key to surviving the ever-changing challenges of Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and work together to overcome challenges. Teamwork is essential for success in Hardcore Ironman.",
|
||||||
|
L"Be cautious when exploring new areas, especially in Hardcore mode. Unknown dangers lurk around every corner, and it's better to proceed with caution than to rush in blindly.",
|
||||||
|
L"Equip gear that complements your playstyle and provides the best possible protection against enemy attacks. Prioritize defensive bonuses and resistances over offensive stats in Hardcore mode.",
|
||||||
|
L"Stay informed about the strengths and weaknesses of different enemy types. Knowing your foes is essential for developing effective strategies and staying alive in Hardcore Ironman.",
|
||||||
|
L"Practice patience and perseverance in Hardcore mode. Success often requires multiple attempts and learning from your mistakes.",
|
||||||
|
L"Develop a backup plan for emergencies, such as a stash of emergency potions or a hidden escape route. Always have a contingency plan in place in Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and communicate effectively to overcome challenges together. Teamwork is essential for survival in Hardcore Ironman.",
|
||||||
|
L"Stay vigilant and be prepared for anything in Hardcore mode. Unexpected dangers and challenges can arise at any moment, and it's important to stay alert.",
|
||||||
|
L"Learn from your mistakes and use them as opportunities for growth. Every death is a chance to refine your strategies and become a better Hardcore player.",
|
||||||
|
L"Stock up on essential supplies like potions, scrolls, and emergency gear. You never know when you'll need them in Hardcore mode.",
|
||||||
|
L"Plan your routes carefully and avoid unnecessary risks. Rushing into danger blindly is a surefire way to meet an untimely demise in Hardcore Ironman.",
|
||||||
|
L"Stay adaptable and be prepared to adjust your tactics on the fly. Flexibility is key to surviving the ever-changing challenges of Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and work together to overcome challenges. Teamwork is essential for success in Hardcore Ironman.",
|
||||||
|
L"Be cautious when exploring new areas, especially in Hardcore mode. Unknown dangers lurk around every corner, and it's better to proceed with caution than to rush in blindly.",
|
||||||
|
L"Equip gear that complements your playstyle and provides the best possible protection against enemy attacks. Prioritize defensive bonuses and resistances over offensive stats in Hardcore mode.",
|
||||||
|
L"Stay informed about the strengths and weaknesses of different enemy types. Knowing your foes is essential for developing effective strategies and staying alive in Hardcore Ironman.",
|
||||||
|
L"Practice patience and perseverance in Hardcore mode. Success often requires multiple attempts and learning from your mistakes.",
|
||||||
|
L"Develop a backup plan for emergencies, such as a stash of emergency potions or a hidden escape route. Always have a contingency plan in place in Hardcore mode.",
|
||||||
|
L"Coordinate your actions with your party members and communicate effectively to overcome challenges together. Teamwork is essential for survival in Hardcore Ironman.",
|
||||||
|
L"Stay vigilant and be prepared for anything in Hardcore mode. Unexpected dangers and challenges can arise at any moment, and it's important to stay alert.",
|
||||||
|
L"Learn from your mistakes and use them as opportunities for growth. Every death is a chance to refine your strategies and become a better Hardcore player.",
|
||||||
|
|
||||||
|
L"Stock up on essential supplies like potions, scrolls, and emergency gear. You never know when you'll need them in Hardcore mode.",
|
||||||
|
|
||||||
|
L"In Hardcore Ironman, your character's survival is paramount above all else. Every decision you make, every action you take, should be with the singular goal of keeping your character alive in the unforgiving world of Diablo 2.",
|
||||||
|
L"Before engaging enemies or venturing into unknown territory, take the time to thoroughly scout your surroundings. Look for potential threats, plan escape routes, and assess the level of danger you may face.",
|
||||||
|
L"With town portals disabled, strategic planning becomes even more critical. Always have a backup plan in place for emergencies, whether it's knowing the location of the nearest waypoint or having a stash of emergency supplies hidden away.",
|
||||||
|
L"Effective inventory management can mean the difference between life and death in Hardcore mode. Organize your inventory carefully, prioritize essential items such as potions and scrolls, and be mindful of your carrying capacity at all times.",
|
||||||
|
L"When facing challenging foes or uncertain situations, don't hesitate to retreat and regroup if necessary. Survival in Hardcore Ironman requires patience, caution, and a willingness to make strategic withdrawals when the odds are against you.",
|
||||||
|
L"Experiment with different skill builds and character setups to find what works best for your playstyle and the challenges you face. Adaptability and versatility are key attributes for success in Hardcore mode.",
|
||||||
|
L"Stay vigilant and be constantly aware of your surroundings. Traps, ambushes, and environmental hazards can pose just as much of a threat as enemy attacks, so always proceed with caution and remain alert.",
|
||||||
|
L"Equip gear that emphasizes defense and survivability over offensive power. Prioritize items with high resistances, damage reduction, and life-saving bonuses to maximize your chances of survival in Hardcore Ironman.",
|
||||||
|
L"Your mercenary companion can be a valuable asset in Hardcore mode, providing additional firepower, support, and distraction in battle. Invest in their equipment and skills wisely to ensure they can effectively complement your own abilities.",
|
||||||
|
L"In multiplayer games, effective communication and cooperation are essential for survival. Coordinate with your party members, share information about enemy locations and tactics, and work together to overcome challenges.",
|
||||||
|
|
||||||
|
L"Stay informed about the latest updates, patches, and strategies in the Diablo 2 community. Knowledge is power in Hardcore mode, and staying up-to-date with the latest developments can give you a significant advantage.",
|
||||||
|
L"Develop a contingency plan for emergencies. Whether it's having a reserve of emergency potions, escape routes planned out in advance, or backup characters ready to take over in case of death, always be prepared for the worst-case scenario.",
|
||||||
|
L"Practice patience and resilience in the face of adversity. Setbacks and challenges are inevitable in Hardcore Ironman, but maintaining a positive mindset and persevering through tough times is key to ultimate success.",
|
||||||
|
L"Build connections with other Hardcore players and join communities or forums where you can share tips, strategies, and experiences. Learning from the insights of others can help you improve your own Hardcore gameplay.",
|
||||||
|
L"Trust your instincts and intuition when navigating the dangers of Hardcore mode. If something feels too risky or dangerous, don't hesitate to err on the side of caution and take a safer approach.",
|
||||||
|
L"Embrace the thrill and challenge of Hardcore Ironman, and savor the adrenaline rush that comes with narrowly escaping death. The high stakes and permanent consequences make every victory all the more rewarding in Hardcore mode.",
|
||||||
|
L"Maintain discipline and avoid taking unnecessary risks that could jeopardize your character's survival. Exercise caution in all your actions, and remember that one careless mistake could cost you dearly in Hardcore Ironman.",
|
||||||
|
L"Keep a clear mind and remain focused, especially during intense or dangerous situations. Panic and anxiety can cloud your judgment and lead to fatal errors in Hardcore mode, so strive to stay calm and composed at all times.",
|
||||||
|
L"Learn from your mistakes and use each death as an opportunity for growth and improvement. Analyze what went wrong, identify areas for improvement, and apply those lessons to future gameplay to become a stronger Hardcore player.",
|
||||||
|
L"Be vigilant and attentive to your surroundings, as danger can lurk around every corner in Hardcore mode. Take nothing for granted, and always be prepared to react quickly to unexpected threats or challenges.",
|
||||||
|
L"Prioritize defensive capabilities and survival skills when choosing gear and allocating skill points. A sturdy defense and reliable survivability are essential for weathering the dangers of Hardcore Ironman.",
|
||||||
|
L"Stock up on essential supplies such as potions, scrolls, and emergency gear to ensure you're always prepared for whatever challenges may arise in Hardcore mode. It's better to have too much than too little when your life is on the line.",
|
||||||
|
L"Plan your routes and engagements carefully, avoiding unnecessary risks and ensuring you always have a viable escape plan. Rushing headlong into danger is a surefire way to meet an untimely end in Hardcore Ironman.",
|
||||||
|
L"Remain adaptable and flexible in your approach, adjusting your tactics and strategies as needed to overcome the ever-changing challenges of Hardcore mode. The ability to think on your feet and adapt to new situations is crucial for survival.",
|
||||||
|
L"Communicate effectively with your party members in multiplayer games, coordinating your actions and sharing information to maximize your chances of success. Teamwork is essential for conquering the toughest challenges in Hardcore Ironman.",
|
||||||
|
L"Exercise caution and prudence when exploring new areas, taking care to avoid potential traps, ambushes, and other hazards that could spell doom for your character. Proceed with caution and always be prepared for the unexpected.",
|
||||||
|
L"Equip gear that emphasizes defensive bonuses and survivability over raw offensive power, prioritizing items that offer high resistances, damage reduction, and other life-saving properties. In Hardcore mode, staying alive is the ultimate goal.",
|
||||||
|
L"Study the strengths and weaknesses of different enemy types, learning their attack patterns and behaviors to better anticipate and counter their threats. Knowledge is power in Hardcore Ironman, and understanding your foes is key to victory.",
|
||||||
|
L"Embrace the virtues of patience and perseverance, knowing that success in Hardcore mode often requires multiple attempts and learning from your mistakes. Stay determined and keep pushing forward, even in the face of adversity.",
|
||||||
|
L"Develop a backup plan for emergencies, ensuring you have contingencies in place for unexpected situations such as running out of potions or finding yourself cornered by powerful enemies. Preparation is key to survival in Hardcore Ironman.",
|
||||||
|
L"Coordinate your actions with your party members, leveraging each other's strengths and abilities to overcome challenges that would be insurmountable alone. In Hardcore mode, teamwork can mean the difference between life and death.",
|
||||||
|
L"Remain vigilant and alert at all times, keeping a watchful eye on your surroundings and being prepared to react swiftly to any threats or dangers that may arise. In Hardcore Ironman, constant vigilance is essential for survival.",
|
||||||
|
L"Learn from your mistakes and use each death as an opportunity for growth and improvement. Analyze what went wrong, identify areas for improvement, and apply those lessons to your future gameplay to become a stronger and more resilient Hardcore player.",
|
||||||
|
L"Stock up on essential supplies such as potions, scrolls, and emergency gear to ensure you're always prepared for whatever challenges may arise in Hardcore mode. It's better to have too much than too little when your life is on the line.",
|
||||||
|
L"Plan your routes and engagements carefully, avoiding unnecessary risks and ensuring you always have a viable escape plan. Rushing headlong into danger is a surefire way to meet an untimely end in Hardcore Ironman.",
|
||||||
|
L"Remain adaptable and flexible in your approach, adjusting your tactics and strategies as needed to overcome the ever-changing challenges of Hardcore mode. The ability to think on your feet and adapt to new situations is crucial for survival.",
|
||||||
|
L"Communicate effectively with your party members in multiplayer games, coordinating your actions and sharing information to maximize your chances of success. Teamwork is essential for conquering the toughest challenges in Hardcore Ironman.",
|
||||||
|
L"Exercise caution and prudence when exploring new areas, taking care to avoid potential traps, ambushes, and other hazards that could spell doom for your character. Proceed with caution and always be prepared for the unexpected.",
|
||||||
|
L"Equip gear that emphasizes defensive bonuses and survivability over raw offensive power, prioritizing items that offer high resistances, damage reduction, and other life-saving properties. In Hardcore mode, staying alive is the ultimate goal.",
|
||||||
|
L"Study the strengths and weaknesses of different enemy types, learning their attack patterns and behaviors to better anticipate and counter their threats. Knowledge is power in Hardcore Ironman, and understanding your foes is key to victory.",
|
||||||
|
L"Embrace the virtues of patience and perseverance, knowing that success in Hardcore mode often requires multiple attempts and learning from your mistakes. Stay determined and keep pushing forward, even in the face of adversity.",
|
||||||
|
L"Develop a backup plan for emergencies, ensuring you have contingencies in place for unexpected situations such as running out of potions or finding yourself cornered by powerful enemies. Preparation is key to survival in Hardcore Ironman.",
|
||||||
|
L"Coordinate your actions with your party members, leveraging each other's strengths and abilities to overcome challenges that would be insurmountable alone. In Hardcore mode, teamwork can mean the difference between life and death.",
|
||||||
|
L"Remain vigilant and alert at all times, keeping a watchful eye on your surroundings and being prepared to react swiftly to any threats or dangers that may arise. In Hardcore Ironman, constant vigilance is essential for survival.",
|
||||||
|
|
||||||
|
L"In Hardcore Ironman, survival is your top priority. Every decision you make, every action you take, should be with the singular goal of keeping your character alive in the unforgiving world of Diablo 2.",
|
||||||
|
L"Before engaging enemies or venturing into unknown territory, take the time to thoroughly scout your surroundings. Look for potential threats, plan escape routes, and assess the level of danger you may face.",
|
||||||
|
L"With town portals disabled, strategic planning becomes even more critical. Always have a backup plan in place for emergencies, whether it's knowing the location of the nearest waypoint or having a stash of emergency supplies hidden away.",
|
||||||
|
L"Effective inventory management can mean the difference between life and death in Hardcore mode. Organize your inventory carefully, prioritize essential items such as potions and scrolls, and be mindful of your carrying capacity at all times.",
|
||||||
|
L"When facing challenging foes or uncertain situations, don't hesitate to retreat and regroup if necessary. Survival in Hardcore Ironman requires patience, caution, and a willingness to make strategic withdrawals when the odds are against you.",
|
||||||
|
L"Experiment with different skill builds and character setups to find what works best for your playstyle and the challenges you face. Adaptability and versatility are key attributes for success in Hardcore mode.",
|
||||||
|
L"Stay vigilant and be constantly aware of your surroundings. Traps, ambushes, and environmental hazards can pose just as much of a threat as enemy attacks, so always proceed with caution and remain alert.",
|
||||||
|
L"Equip gear that emphasizes defense and survivability over offensive power. Prioritize items with high resistances, damage reduction, and life-saving bonuses to maximize your chances of survival in Hardcore Ironman.",
|
||||||
|
L"Your mercenary companion can be a valuable asset in Hardcore mode, providing additional firepower, support, and distraction in battle. Invest in their equipment and skills wisely to ensure they can effectively complement your own abilities.",
|
||||||
|
L"In multiplayer games, effective communication and cooperation are essential for survival. Coordinate with your party members, share information about enemy locations and tactics, and work together to overcome challenges and dangers.",
|
||||||
|
L"Stay informed about the latest updates, patches, and strategies in the Diablo 2 community. Knowledge is power in Hardcore mode, and staying up-to-date with the latest developments can give you a significant advantage.",
|
||||||
|
L"Develop a contingency plan for emergencies. Whether it's having a reserve of emergency potions, escape routes planned out in advance, or backup characters ready to take over in case of death, always be prepared for the worst-case scenario.",
|
||||||
|
L"Practice patience and resilience in the face of adversity. Setbacks and challenges are inevitable in Hardcore Ironman, but maintaining a positive mindset and persevering through tough times is key to ultimate success.",
|
||||||
|
L"Build connections with other Hardcore players and join communities or forums where you can share tips, strategies, and experiences. Learning from the insights of others can help you improve your own Hardcore gameplay.",
|
||||||
|
L"Trust your instincts and intuition when navigating the dangers of Hardcore mode. If something feels too risky or dangerous, don't hesitate to err on the side of caution and take a safer approach.",
|
||||||
|
L"Embrace the thrill and challenge of Hardcore Ironman, and savor the adrenaline rush that comes with narrowly escaping death. The high stakes and permanent consequences make every victory all the more rewarding in Hardcore mode.",
|
||||||
|
L"Maintain discipline and avoid taking unnecessary risks that could jeopardize your character's survival. Exercise caution in all your actions, and remember that one careless mistake could cost you dearly in Hardcore Ironman.",
|
||||||
|
L"Keep a clear mind and remain focused, especially during intense or dangerous situations. Panic and anxiety can cloud your judgment and lead to fatal errors in Hardcore mode, so strive to stay calm and composed at all times.",
|
||||||
|
L"Learn from your mistakes and use each death as an opportunity for growth and improvement. Analyze what went wrong, identify areas for improvement, and apply those lessons to future gameplay to become a stronger Hardcore player.",
|
||||||
|
L"Be vigilant and attentive to your surroundings, as danger can lurk around every corner in Hardcore mode. Take nothing for granted, and always be prepared to react quickly to unexpected threats or challenges.",
|
||||||
|
L"Prioritize defensive capabilities and survival skills when choosing gear and allocating skill points. A sturdy defense and reliable survivability are essential for weathering the dangers of Hardcore Ironman.",
|
||||||
|
L"Stock up on essential supplies such as potions, scrolls, and emergency gear to ensure you're always prepared for whatever challenges may arise in Hardcore mode. It's better to have too much than too little when your life is on the line.",
|
||||||
|
L"Plan your routes and engagements carefully, avoiding unnecessary risks and ensuring you always have a viable escape plan. Rushing headlong into danger is a surefire way to meet an untimely end in Hardcore Ironman.",
|
||||||
|
L"Remain adaptable and flexible in your approach, adjusting your tactics and strategies as needed to overcome the ever-changing challenges of Hardcore mode. The ability to think on your feet and adapt to new situations is crucial for survival.",
|
||||||
|
L"Communicate effectively with your party members in multiplayer games, coordinating your actions and sharing information to maximize your chances of success. Teamwork is essential for conquering the toughest challenges in Hardcore Ironman.",
|
||||||
|
L"Exercise caution and prudence when exploring new areas, taking care to avoid potential traps, ambushes, and other hazards that could spell doom for your character. Proceed with caution and always be prepared for the unexpected.",
|
||||||
|
L"Equip gear that emphasizes defensive bonuses and survivability over raw offensive power, prioritizing items that offer high resistances, damage reduction, and other life-saving properties. In Hardcore mode, staying alive is the ultimate goal.",
|
||||||
|
L"Study the strengths and weaknesses of different enemy types, learning their attack patterns and behaviors to better anticipate and counter their threats. Knowledge is power in Hardcore Ironman, and understanding your foes is key to victory.",
|
||||||
|
L"Embrace the virtues of patience and perseverance, knowing that success in Hardcore mode often requires multiple attempts and learning from your mistakes. Stay determined and keep pushing forward, even in the face of adversity.",
|
||||||
|
L"Develop a backup plan for emergencies, ensuring you have contingencies in place for unexpected situations such as running out of potions or finding yourself cornered by powerful enemies. Preparation is key to survival in Hardcore Ironman.",
|
||||||
|
L"Coordinate your actions with your party members, leveraging each other's strengths and abilities to overcome challenges that would be insurmountable alone. In Hardcore mode, teamwork can mean the difference between life and death.",
|
||||||
|
L"Remain vigilant and alert at all times, keeping a watchful eye on your surroundings and being prepared to react swiftly to any threats or dangers that may arise. In Hardcore Ironman, constant vigilance is essential for survival.",
|
||||||
|
L"Learn from your mistakes and use each death as an opportunity for growth and improvement. Analyze what went wrong, identify areas for improvement, and apply those lessons to your future gameplay to become a stronger and more resilient Hardcore player.",
|
||||||
|
L"Stock up on essential supplies such as potions, scrolls, and emergency gear to ensure you're always prepared for whatever challenges may arise in Hardcore mode. It's better to have too much than too little when your life is on the line.",
|
||||||
|
L"Plan your routes and engagements carefully, avoiding unnecessary risks and ensuring you always have a viable escape plan. Rushing headlong into danger is a surefire way to meet an untimely end in Hardcore Ironman.",
|
||||||
|
L"Remain adaptable and flexible in your approach, adjusting your tactics and strategies as needed to overcome the ever-changing challenges of Hardcore mode. The ability to think on your feet and adapt to new situations is crucial for survival.",
|
||||||
|
L"Communicate effectively with your party members in multiplayer games, coordinating your actions and sharing information to maximize your chances of success. Teamwork is essential for conquering the toughest challenges in Hardcore Ironman.",
|
||||||
|
L"Exercise caution and prudence when exploring new areas, taking care to avoid potential traps, ambushes, and other hazards that could spell doom for your character. Proceed with caution and always be prepared for the unexpected.",
|
||||||
|
L"Equip gear that emphasizes defensive bonuses and survivability over raw offensive power, prioritizing items that offer high resistances, damage reduction, and other life-saving properties. In Hardcore mode, staying alive is the ultimate goal.",
|
||||||
|
L"Study the strengths and weaknesses of different enemy types, learning their attack patterns and behaviors to better anticipate and counter their threats. Knowledge is power in Hardcore Ironman, and understanding your foes is key to victory.",
|
||||||
|
L"Embrace the virtues of patience and perseverance, knowing that success in Hardcore mode often requires multiple attempts and learning from your mistakes. Stay determined and keep pushing forward, even in the face of adversity.",
|
||||||
|
L"Develop a backup plan for emergencies, ensuring you have contingencies in place for unexpected situations such as running out of potions or finding yourself cornered by powerful enemies. Preparation is key to survival in Hardcore Ironman.",
|
||||||
|
L"Coordinate your actions with your party members, leveraging each other's strengths and abilities to overcome challenges that would be insurmountable alone. In Hardcore mode, teamwork can mean the difference between life and death.",
|
||||||
|
L"Remain vigilant and alert at all times, keeping a watchful eye on your surroundings and being prepared to react swiftly to any threats or dangers that may arise. In Hardcore Ironman, constant vigilance is essential for survival."
|
||||||
|
|
||||||
|
L"In Hardcore Ironman, the safety of your character is paramount. Every action you take should be calculated to ensure survival in the unforgiving world of Diablo 2. Take the time to carefully assess your surroundings, anticipate potential threats, and plan your actions accordingly.",
|
||||||
|
L"With town portals disabled, strategic planning becomes even more crucial. Always have an exit strategy in mind, whether it's knowing the location of the nearest waypoint or having a designated escape route planned out in advance.",
|
||||||
|
L"Effective inventory management is essential for survival in Hardcore mode. Keep your inventory organized, prioritize essential items such as potions and scrolls, and be mindful of your carrying capacity at all times.",
|
||||||
|
L"When facing tough enemies or uncertain situations, don't be afraid to retreat and regroup if necessary. Survival in Hardcore Ironman requires patience, caution, and a willingness to reassess your approach when the odds are against you.",
|
||||||
|
L"Experiment with different skill builds, character setups, and equipment combinations to find what works best for your playstyle and the challenges you encounter. Adaptability and versatility are key attributes for success in Hardcore mode.",
|
||||||
|
L"Stay vigilant and remain constantly aware of your surroundings. Traps, ambushes, and environmental hazards can be just as deadly as enemy attacks, so always proceed with caution and keep your senses sharp.",
|
||||||
|
L"Equip gear that prioritizes defense and survivability over offensive power. Look for items with high resistances, damage reduction, and life-saving bonuses to increase your chances of surviving the dangers of Hardcore Ironman.",
|
||||||
|
L"Your mercenary companion can provide valuable support in Hardcore mode, serving as an additional source of damage, crowd control, and distraction in battle. Invest in their equipment and skills to ensure they can effectively complement your own abilities.",
|
||||||
|
L"In multiplayer games, effective communication and cooperation are crucial for success. Coordinate with your party members, share information about enemy locations and tactics, and work together to overcome challenges and dangers.",
|
||||||
|
L"Stay informed about the latest developments and strategies in the Diablo 2 community. Knowledge is power in Hardcore mode, and staying up-to-date with the latest information can give you a significant advantage.",
|
||||||
|
L"Develop contingency plans for emergencies. Whether it's having a stash of emergency potions, designated escape routes planned out in advance, or backup characters ready to take over in case of death, always be prepared for the worst-case scenario.",
|
||||||
|
L"Practice patience and resilience in the face of adversity. Setbacks and challenges are inevitable in Hardcore Ironman, but maintaining a positive attitude and persevering through tough times is essential for ultimate success.",
|
||||||
|
L"Build connections with other Hardcore players and participate in communities or forums where you can share tips, strategies, and experiences. Learning from the insights of others can help you improve your own Hardcore gameplay.",
|
||||||
|
L"Trust your instincts and intuition when navigating the dangers of Hardcore mode. If something feels too risky or dangerous, don't hesitate to err on the side of caution and take a safer approach.",
|
||||||
|
L"Embrace the excitement and challenge of Hardcore Ironman, and relish the adrenaline rush that comes with narrowly escaping death. The high stakes and permanent consequences make every victory all the more satisfying in Hardcore mode.",
|
||||||
|
L"Maintain discipline and avoid taking unnecessary risks that could jeopardize your character's survival. Exercise caution in all your actions, and remember that one careless mistake could cost you dearly in Hardcore Ironman.",
|
||||||
|
L"Keep a clear head and stay focused, especially during intense or dangerous situations. Panic and fear can cloud your judgment and lead to fatal errors in Hardcore mode, so strive to remain calm and composed at all times.",
|
||||||
|
L"Learn from your mistakes and view each death as an opportunity for growth and improvement. Analyze what went wrong, identify areas for improvement, and apply those lessons to your future gameplay to become a stronger Hardcore player.",
|
||||||
|
L"Be vigilant and observant of your surroundings, as danger can lurk around every corner in Hardcore mode. Take nothing for granted, and always be prepared to react swiftly to unexpected threats or challenges.",
|
||||||
|
L"Prioritize defensive capabilities and survival skills when choosing gear and allocating skill points. A solid defense and reliable survivability are essential for withstanding the dangers of Hardcore Ironman.",
|
||||||
|
L"Stock up on essential supplies such as potions, scrolls, and emergency gear to ensure you're always prepared for whatever challenges may arise in Hardcore mode. It's better to have too much than too little when your life is on the line.",
|
||||||
|
L"Plan your routes and engagements carefully, avoiding unnecessary risks and ensuring you always have a viable escape plan. Charging headlong into danger is a surefire way to meet an untimely end in Hardcore Ironman.",
|
||||||
|
L"Remain adaptable and flexible in your approach, adjusting your tactics and strategies as needed to overcome the ever-changing challenges of Hardcore mode. The ability to think on your feet and adapt to new situations is crucial for survival.",
|
||||||
|
L"Communicate effectively with your party members in multiplayer games, coordinating your actions and sharing information to maximize your chances of success. Teamwork is essential for overcoming the toughest challenges in Hardcore Ironman.",
|
||||||
|
L"Exercise caution and prudence when exploring new areas, taking care to avoid potential traps, ambushes, and other hazards that could spell doom for your character. Proceed with caution and always be prepared for the unexpected.",
|
||||||
|
L"Equip gear that emphasizes defensive bonuses and survivability over raw offensive power, prioritizing items that offer high resistances, damage reduction, and other life-saving properties. In Hardcore mode, staying alive is paramount.",
|
||||||
|
L"Study the strengths and weaknesses of different enemy types, familiarizing yourself with their attack patterns and behaviors to better anticipate and counter their threats. Knowledge is power in Hardcore Ironman, and understanding your foes is key to victory.",
|
||||||
|
L"Embrace the virtues of patience and perseverance, recognizing that success in Hardcore mode often requires multiple attempts and learning from your mistakes. Stay determined and keep pushing forward, even when the odds seem stacked against you.",
|
||||||
|
L"Develop backup plans for emergencies, ensuring you have contingencies in place for unexpected situations such as running out of potions or finding yourself cornered by powerful enemies. Preparation is key to survival in Hardcore Ironman.",
|
||||||
|
L"Coordinate your actions with your party members, leveraging each other's strengths and abilities to overcome challenges that would be insurmountable alone. In Hardcore mode, teamwork can be the difference between life and death.",
|
||||||
|
L"Remain vigilant and alert at all times, maintaining a keen awareness of your surroundings and being prepared to react swiftly to any threats or dangers that may arise. In Hardcore Ironman, constant vigilance is essential for survival.",
|
||||||
|
L"Learn from your mistakes and view each death as an opportunity for growth and improvement. Reflect on what went wrong, identify areas for improvement, and apply those lessons to your future gameplay to become a more skilled Hardcore player.",
|
||||||
|
L"Stock up on essential supplies such as potions, scrolls, and emergency gear to ensure you're always prepared for whatever challenges may arise in Hardcore mode. It's better to have too much than too little when your life is on the line.",
|
||||||
|
L"Plan your routes and engagements carefully, avoiding unnecessary risks and ensuring you always have a viable escape plan. Charging headlong into danger is a surefire way to meet an untimely end in Hardcore Ironman.",
|
||||||
|
L"Remain adaptable and flexible in your approach, adjusting your tactics and strategies as needed to overcome the ever-changing challenges of Hardcore mode. The ability to think on your feet and adapt to new situations is crucial for survival.",
|
||||||
|
L"Communicate effectively with your party members in multiplayer games, coordinating your actions and sharing information to maximize your chances of success. Teamwork is essential for overcoming the toughest challenges in Hardcore Ironman.",
|
||||||
|
L"Exercise caution and prudence when exploring new areas, taking care to avoid potential traps, ambushes, and other hazards that could spell doom for your character. Proceed with caution and always be prepared for the unexpected.",
|
||||||
|
L"Equip gear that emphasizes defensive bonuses and survivability over raw offensive power, prioritizing items that offer high resistances, damage reduction, and other life-saving properties. In Hardcore mode, staying alive is paramount.",
|
||||||
|
L"Study the strengths and weaknesses of different enemy types, familiarizing yourself with their attack patterns and behaviors to better anticipate and counter their threats. Knowledge is power in Hardcore Ironman, and understanding your foes is key to victory.",
|
||||||
|
L"Embrace the virtues of patience and perseverance, recognizing that success in Hardcore mode often requires multiple attempts and learning from your mistakes. Stay determined and keep pushing forward, even when the odds seem stacked against you.",
|
||||||
|
L"Develop backup plans for emergencies, ensuring you have contingencies in place for unexpected situations such as running out of potions or finding yourself cornered by powerful enemies. Preparation is key to survival in Hardcore Ironman.",
|
||||||
|
L"Coordinate your actions with your party members, leveraging each other's strengths and abilities to overcome challenges that would be insurmountable alone. In Hardcore mode, teamwork can be the difference between life and death.",
|
||||||
|
L"Remain vigilant and alert at all times, maintaining a keen awareness of your surroundings and being prepared to react swiftly to any threats or dangers that may arise. In Hardcore Ironman, constant vigilance is essential for survival.",
|
||||||
|
|
||||||
|
L"Discover the vast array of new sets introduced in the latest update, each offering unique bonuses and playstyles to explore. Experiment with different combinations to find the perfect set for your character's build and playstyle.",
|
||||||
|
L"Explore the expansive collection of over 1400 new unique items, each with its own distinct attributes, affixes, and effects. From powerful weapons to protective armor, there's something for every type of character and playstyle.",
|
||||||
|
L"Unlock the potential of hundreds of new runewords, each offering powerful bonuses and enhancements when socketed into your gear. Experiment with different combinations of runes to create the perfect runeword for your character's needs.",
|
||||||
|
L"Delve into the world of gemwords, where combining multiple gems in your gear unlocks powerful bonuses and effects. With hundreds of gemwords to discover, there's endless potential for customization and optimization.",
|
||||||
|
L"Discover the versatility of stonewords, which combine Diablo 3 gems with existing items to create powerful new gear with enhanced properties. Experiment with different gem combinations to find the perfect stoneword for your character.",
|
||||||
|
L"Maximize the efficiency of your inventory management by utilizing the Magic Essence Harvester to extract essence from unwanted items. Convert magic, rare, set, or unique items into essence points, which can then be used to create new items and mods.",
|
||||||
|
L"Utilize the Magic Essence Points obtained from the Harvester to create a wide variety of magic items and modifications. Whether you're enhancing existing gear or creating entirely new items, the possibilities are endless with Magic Essence Points.",
|
||||||
|
L"Enhance your arsenal by using Rare Shards, Set Stones, or Unique Particles to create rare, set, and unique versions of items. Visit the NPC in town to access this feature and unlock the full potential of your gear.",
|
||||||
|
L"Take advantage of Smithing Hammers, a new item type that drops in-game, to produce base item types for crafting custom gear. Use these base items as the foundation for creating powerful and unique equipment tailored to your character's needs.",
|
||||||
|
L"Make use of the Item Salvager to break down white items and obtain valuable item parts for crafting. With a variety of salvaging options available, you can extract parts from different item qualities to fuel your crafting endeavors.",
|
||||||
|
L"Explore the vast array of cube recipes added to the salvaging system, offering over 2,000 new combinations for extracting item parts and materials. Experiment with different recipes to discover the most efficient ways to salvage items and obtain resources.",
|
||||||
|
L"Discover the excitement of Demon Souls and Spirits, which can be obtained from defeated demons. These unique drops offer valuable bonuses and enhancements, providing new opportunities for character customization and power-ups.",
|
||||||
|
L"Organize your collection of gems and runes with Gem Bags and Rune Bags, which allow you to store and manage your precious resources more efficiently. With the ability to stack gems and runes up to 100 each, you'll have plenty of space for your collection.",
|
||||||
|
L"Unlock the potential of full hireling inventory, allowing your hired companions to equip additional items such as belts, boots, gloves, rings, and amulets. Customize your hirelings to suit your needs and maximize their effectiveness in battle.",
|
||||||
|
L"Access your stash from anywhere with the Remote Stash feature, which drops after achieving 10,000 kills. Enjoy the convenience of managing your inventory on the go, without the need to return to town or find a stash.",
|
||||||
|
L"Increase your killcounter stat by slaying monsters and unlocking various bonuses and rewards based on your kill count. From healing potions to rare weapons and armor, there are plenty of incentives to keep pushing forward and defeating enemies.",
|
||||||
|
L"Unlock Demon Chests and Keys by combining demon drops to receive random items of varying qualities. Experiment with different combinations to discover the treasures hidden within these mysterious chests.",
|
||||||
|
L"Maximize the potential of your gear by socketing gems and runes into almost every item type, including helms, charms, boots, rings, amulets, shields, and belts. Customize your equipment to suit your playstyle and optimize your character's abilities.",
|
||||||
|
L"Discover a wide range of magic, rare, and unique arrows and bolts, each offering unique properties and effects to enhance your ranged combat abilities. Experiment with different types to find the perfect ammunition for your character.",
|
||||||
|
L"Unlock the power of magic, rare, and unique charms to bolster your character's stats and abilities. Whether you're seeking increased damage, resistance, or utility, there's a charm out there to suit your needs.",
|
||||||
|
L"Explore the world of summoner doll charms, which offer unique bonuses and effects related to summoning and pet abilities. Enhance your summoner build with these specialized charms and unleash the full potential of your minions.",
|
||||||
|
L"Experience the thrill of the Charmzone, where charms can only be utilized in the bottom four rows of your inventory. Strategically manage your charm inventory to optimize your character's performance in battle.",
|
||||||
|
L"Collect monster body parts dropped by defeated enemies and use them to craft various items and enhancements. From resistance potions to elemental essences, there's a wide range of possibilities to explore with monster body parts.",
|
||||||
|
L"Enhance your character's resistance capabilities with a variety of resistance potions, including fire, magic, poison, and lightning resistance. Stock up on these valuable consumables to bolster your defenses against elemental threats.",
|
||||||
|
L"Dive into the Hardcore Ironman game mode, where survival is your top priority and every decision could mean life or death. With gold disabled and town portals replaced by waypoints, strategic gameplay and resource management are essential for success.",
|
||||||
|
L"Experience the unique challenges of Hardcore Ironman, where underused skills become valuable and vitality is crucial for survival. Experiment with different weapons and strategies to overcome the dangers of this unforgiving game mode.",
|
||||||
|
L"Prepare for the ultimate test of skill and strategy as you venture into Hardcore Ironman mode, where the stakes are high and the risks are greater than ever before. With gold rendered useless and town portals disabled, only the bravest adventurers will survive.",
|
||||||
|
L"Master the art of survival in Hardcore Ironman mode, where every decision could mean the difference between life and death. With gold eliminated from the game and town portals disabled, strategic planning and careful resource management are essential for success.",
|
||||||
|
L"Immerse yourself in the Hardcore Ironman experience, where the thrill of danger and the rush of victory await at every turn. With gold removed from the equation and town portals disabled, only the strongest and most resourceful adventurers will prevail.",
|
||||||
|
L"Embark on a journey into the heart of darkness with Hardcore Ironman mode, where the challenges are greater, the risks are higher, and the rewards are more satisfying than ever before. Will you have what it takes to survive in this unforgiving world?",
|
||||||
|
L"Test your skills and resilience in Hardcore Ironman mode, where every decision carries weight and every encounter could be your last. With gold no longer a factor and town portals disabled, only the most cunning and resourceful players will emerge victorious.",
|
||||||
|
L"Challenge yourself to new heights of difficulty with Hardcore Ironman mode, where the stakes are higher, the dangers are greater, and the rewards are more satisfying than ever before. Can you overcome the ultimate test of skill and strategy?",
|
||||||
|
L"Prepare for the ultimate test of survival in Hardcore Ironman mode, where every step could be your last and every decision could mean life or death. With gold out of the picture and town portals disabled, only the bravest adventurers will dare to venture forth.",
|
||||||
|
L"Experience the adrenaline-fueled excitement of Hardcore Ironman mode, where danger lurks around every corner and death is always one misstep away. With gold rendered useless and town portals disabled, only the strongest and most resourceful heroes will prevail.",
|
||||||
|
L"Dive into the heart of darkness with Hardcore Ironman mode, where the challenges are greater, the risks are higher, and the rewards are more satisfying than ever before. Will you have what it takes to conquer the perils that await?",
|
||||||
|
L"Test your mettle in Hardcore Ironman mode, where survival is the ultimate goal and every decision could mean life or death. With gold eliminated from the game and town portals disabled, only the most skilled and determined adventurers will emerge victorious.",
|
||||||
|
L"Prepare yourself for the ultimate challenge with Hardcore Ironman mode, where danger lurks around every corner and death is always a possibility. With gold removed from the equation and town portals disabled, only the bravest souls will dare to face the darkness.",
|
||||||
|
L"Embark on an epic journey into the unknown with Hardcore Ironman mode, where the challenges are greater, the dangers are deadlier, and the rewards are more satisfying than ever before. Will you have what it takes to survive in this unforgiving world?",
|
||||||
|
L"Test your limits in Hardcore Ironman mode, where every decision could mean life or death and every encounter is a battle for survival. With gold eliminated from the game and town portals disabled, only the strongest and most resourceful adventurers will prevail.",
|
||||||
|
L"Experience the thrill of Hardcore Ironman mode, where danger lurks around every corner and death is always a possibility. With gold out of the picture and town portals disabled, only the bravest heroes will dare to venture forth into the unknown.",
|
||||||
|
L"Dive into the heart of darkness with Hardcore Ironman mode, where the challenges are greater, the risks are higher, and the rewards are more satisfying than ever before. Will you have what it takes to overcome the perils that await?",
|
||||||
|
L"Test your skills and resilience in Hardcore Ironman mode, where survival is the ultimate goal and every decision could mean life or death. With gold removed from the equation and town portals disabled, only the bravest adventurers will dare to venture forth.",
|
||||||
|
L"Prepare for the ultimate test of survival in Hardcore Ironman mode, where danger lurks around every corner and death is always one misstep away. With gold rendered useless and town portals disabled, only the strongest and most resourceful heroes will prevail.",
|
||||||
|
L"Experience the adrenaline-fueled excitement of Hardcore Ironman mode, where danger lurks around every corner and death is always a possibility. With gold eliminated from the game and town portals disabled, only the bravest souls will dare to face the darkness.",
|
||||||
|
L"Dive into the heart of darkness with Hardcore Ironman mode, where the challenges are greater, the risks are higher, and the rewards are more satisfying than ever before. Will you have what it takes to survive in this unforgiving world?",
|
||||||
|
L"Test your limits in Hardcore Ironman mode, where every decision could mean life or death and every encounter is a battle for survival. With gold out of the picture and town portals disabled, only the strongest and most resourceful adventurers will prevail.",
|
||||||
|
|
||||||
|
L"Upgrade your Runes by combining any 3 Runes up to Lem to create the next Rune type. Likewise, merge any 2 Runes from Pul up to advance to the next level of Rune power.",
|
||||||
|
L"Transform your Magic Charms by combining 3 of the same type into a new Magic Charm of the same variety. Whether they're Small, Large, or Grand, gather 3 Magic Charms to reroll them into a fresh version at 100% of your character's level.",
|
||||||
|
L"Enhance your Jewels by gathering 3 of the same type and converting them into a new Jewel of the same category. Whether they're Magic or Rare, merge 3 Jewels to reroll them into a more potent version, matching your character's level at 100%.",
|
||||||
|
L"Craft new Rings by combining sets of 3 Rings. Combine 3 Magic Rings to reroll them into a new Magic Ring at 75% of your character's level, or gather 3 Rare Rings to reroll them at full power.",
|
||||||
|
L"Create new Amulets by collecting sets of 3 Amulets. Combine 3 Magic Amulets to reroll them into a fresh Magic Amulet at 75% of your character's level, or gather 3 Rare Amulets to reroll them into new Rare Amulets at full strength.",
|
||||||
|
L"Unleash the power of Unique Arrows & Bolts by combining them with specific Runes and Gems. Mix a Quiver of Arrows or Bolts with the right combination of Runes and Gems to create unique ammunition, or replenish your Arrow Stack by combining any Unique Arrows or Bolts with a Health Potion.",
|
||||||
|
L"Prepare your Armor, Shields, and Weapons for powerful Runewords by socketing them appropriately. Use specific Runes to add sockets to your equipment, allowing for the insertion of powerful Runewords to enhance their capabilities.",
|
||||||
|
L"Add sockets to your Armor, Shields, and Weapons to prepare them for powerful upgrades. Combine specific Runes with various types of equipment to add sockets, enabling you to further customize and enhance their effectiveness.",
|
||||||
|
L"Enhance your Weapons with the power of Chipped Gems, upgrading their damage and attributes. Combine any Weapon with Chipped Gems to add elemental damage, increased attack rating, or additional durability, depending on the gem used and its level.",
|
||||||
|
L"Elevate your Weapons with Flawed Gems, infusing them with greater power and versatility. Combine any Weapon with Flawed Gems to significantly increase their elemental damage, attack rating, or durability, based on the gem type and its level.",
|
||||||
|
L"Augment your Weapons with Regular Gems, imbuing them with even greater potency and effectiveness. Combine any Weapon with Regular Gems to substantially boost their elemental damage, attack rating, or durability, depending on the gem used and its level.",
|
||||||
|
L"Empower your Weapons with Flawless Gems, unlocking their full potential and making them formidable tools of destruction. Combine any Weapon with Flawless Gems to dramatically increase their elemental damage, attack rating, or durability, depending on the gem type and its level.",
|
||||||
|
L"Enrich your Weapons with the supreme power of Perfect Gems, granting them unparalleled strength and capability. Combine any Weapon with Perfect Gems to unleash devastating elemental damage, vastly improve attack rating, or significantly enhance durability, depending on the gem used and its level.",
|
||||||
|
L"Fortify your Armor with the durability of Perfect Diamonds, ensuring they withstand the toughest battles. Combine any Armor with Perfect Diamonds to add durability, granting increased resistance to wear and tear.",
|
||||||
|
L"Reinforce your Armor with the defensive prowess of Perfect Diamonds, bolstering their resilience against enemy attacks. Combine any Armor with 3 Perfect Diamonds to enhance defense, providing greater protection in combat.",
|
||||||
|
|
||||||
|
|
||||||
|
L"Boost the effectiveness of all Armor types by combining them with various Runes and Magic Jewels. Enhance your Armor's attributes such as light radius, resistance, damage reduction, faster hit recovery, and more, depending on the combination used and the level of the runes.",
|
||||||
|
L"Strengthen any Body Armor (Torso) by infusing it with the power of Runes and Magic Jewels. Improve attributes like stamina drain, mana per kill, defense, mana regeneration, damage reduction, resistances, and more, based on the combination of runes and jewels used.",
|
||||||
|
L"Empower Belts, Boots, Gloves, and Helms with the magical properties of Runes and Magic Jewels. Enhance attributes such as stamina drain, mana per kill, defense, mana regeneration, damage reduction, resistances, and more, depending on the combination of runes and jewels used.",
|
||||||
|
|
||||||
|
|
||||||
|
L"Improve the defensive capabilities of any Torso Armor by combining it with various Runes and Magic Jewels. Enhance attributes such as stamina drain, mana per kill, defense, mana regeneration, damage reduction, resistances, and magic find, depending on the combination used.",
|
||||||
|
L"Strengthen the properties of Belts, Boots, Gloves, and Helms by infusing them with the magical essence of Runes and Magic Jewels. Enhance attributes like stamina drain, mana per kill, defense, mana regeneration, damage reduction, resistances, and magic find, based on the combination of runes and jewels employed.",
|
||||||
|
L"Empower Shields with the mystical energy of Runes and Magic Jewels to bolster their defensive capabilities. Enhance attributes such as light radius, block chance, mana per kill, defense, mana regeneration, damage reduction, faster block rate, resistances, and magic find, depending on the combination of runes and jewels utilized.",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
L"Use a variety of weapons to exploit enemy vulnerabilities and resistances",
|
||||||
|
L"Consume spirits like potions to increase Spirits Quaffed stat in character stat sheet page",
|
||||||
|
L"Cube Souls with Energy Sphere to capture Soul Energy and use it to create powerful items. Recipes will come later",
|
||||||
|
L"Collect Demon souls from demons and regular souls from monsters; Demon souls morph you into the demon whose soul you have",
|
||||||
|
L"Spirits can be consumed like potions or put on as rings to add to Souls Consumed count",
|
||||||
|
L"Cube underused magic, rare, set, unique items with Energy Sphere to collect their magic energy for creating new items",
|
||||||
|
L"Cube white items with Energy Sphere to break down into simple item parts for creating base item types with smithing hammers",
|
||||||
|
L"Use Rare Shard, Set Stone, or Unique Particle with smithing hammers and Energy Sphere to create rare, set, unique items",
|
||||||
|
L"Acquire smithing hammers to create base item types, each requiring X number of collected item parts",
|
||||||
|
L"Capture Talisman of Corruption and cube to corrupt items for new magical properties; a gamble with potential rewards",
|
||||||
|
L"Use Experience Book for extra experience, Infinite Mana Elixir for massive mana regeneration, and Regeneration Elixir for life regeneration",
|
||||||
|
L"Use Elixirs to permanently boost stats like Strength, Dexterity, Health, Stamina, Mana, and resistances",
|
||||||
|
L"Equip Sling Stone for increased throwing potion damage, various elemental stones for resistance boosts, and Mastery Stones for skill damage boosts",
|
||||||
|
L"Use Portable Shrines for temporary buffs like increased defense, damage, experience gained, mana regeneration, and skill levels",
|
||||||
|
L"In Ironman, gold is nonexistent, town portals are disabled; rely on items, waypoints, and strategic gameplay to progress",
|
||||||
|
L"Inventory management is critical; use items conservatively and intelligently switch gear based on monster types and situations",
|
||||||
|
L"Hybrid character builds and creative weapon choices are encouraged in Ironman; experiment and adapt strategies accordingly",
|
||||||
|
L"Protect hirelings actively as they are essential allies; they can be hired for 0 gold but lose items if they die",
|
||||||
|
L"Coordinate with teammates in MultiPlayer; teamwork, resource sharing, and strategy are key to success in Ironman",
|
||||||
|
L"In Hardcore Ironman, caution and careful planning are crucial; falling back, potion management, and adaptability are essential for survival",
|
||||||
|
L"Utilize waypoints for inter-level travel in Ironman; waypoints become crucial for navigating the game world",
|
||||||
|
L"Always have backup gear in your backpack in Ironman; switch out gear intelligently based on monster types and challenges",
|
||||||
|
L"Experiment with different weapons and gear in Ironman; adapt your strategies to overcome various monster types and situations",
|
||||||
|
L"Keep a close watch on your hirelings' health in Ironman; losing a hireling means losing their equipped items as well",
|
||||||
|
L"Plan and communicate effectively in MultiPlayer Ironman games; teamwork and coordination are key to overcoming challenges",
|
||||||
|
L"Be conservative with resources in Hardcore Ironman; strategic planning and careful execution are vital for survival",
|
||||||
|
L"Craft rare, set, unique items using collected item parts and smithing hammers in Ironman; choose item types wisely for your build",
|
||||||
|
L"Capture and corrupt items using Talisman of Corruption for new magical properties in Ironman; take calculated risks for potential rewards",
|
||||||
|
L"Use Portable Shrines strategically in Ironman for temporary buffs; timing and placement of shrines can turn the tide of battle",
|
||||||
|
L"Keep track of Souls Consumed and Spirits Quaffed stats in Ironman; they reflect your progress and resource utilization in the game",
|
||||||
|
L"Enhance your character with Elixirs and Stones for permanent stat boosts and bonuses in Ironman; plan your upgrades wisely",
|
||||||
|
L"Master the art of retreating and regrouping in Hardcore Ironman; strategic fallbacks can save your character's life in tough situations",
|
||||||
|
L"Stay vigilant and adapt your strategies in MultiPlayer Ironman games; synergy and cooperation with teammates are essential for success",
|
||||||
|
L"Experiment with different skill synergies and builds in Ironman; explore the full potential of your character's abilities",
|
||||||
|
L"Craft and equip powerful unique items using collected Magic Essence Points and recipes in Ironman; customize your gear for optimal performance",
|
||||||
|
L"Explore new areas and challenges in Ironman; discover hidden secrets and encounters by venturing off the beaten path",
|
||||||
|
L"Combine different magic, rare, set, unique items with the Energy Sphere to collect their magic energy in Ironman",
|
||||||
|
L"Cube white items with the Energy Sphere to break them down into simple item parts for crafting in Ironman",
|
||||||
|
L"Use smithing hammers with the Energy Sphere to create base item types for crafting in Ironman",
|
||||||
|
L"Combine Rare Shard, Set Stone, or Unique Particle with base item types and Magic Essence Points to create rare, set, unique items in Ironman",
|
||||||
|
L"Cube Souls with the Energy Sphere to capture their energy and use it for creating more powerful items in Ironman",
|
||||||
|
L"Capture Talisman of Corruption and cube it to corrupt items for new magical properties in Ironman; a gamble with potential rewards",
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void OnLoad() {
|
||||||
|
srand(time(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Function to break the tip into words
|
||||||
|
vector<string> split(const string& s, char delim) {
|
||||||
|
stringstream ss(s);
|
||||||
|
string item;
|
||||||
|
vector<string> tokens;
|
||||||
|
while (getline(ss, item, delim)) {
|
||||||
|
tokens.push_back(item);
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to create sentences from words
|
||||||
|
string makeSentence(vector<string> words, int start, int end) {
|
||||||
|
stringstream ss;
|
||||||
|
for (int i = start; i <= end; ++i) {
|
||||||
|
ss << words[i] << " ";
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to convert string to wide string
|
||||||
|
wstring stringToWstring(const string& s) {
|
||||||
|
wstring ws;
|
||||||
|
for (char c : s) {
|
||||||
|
ws += (wchar_t)c;
|
||||||
|
}
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Your original code here
|
||||||
|
|
||||||
|
// Modified onDraw function
|
||||||
|
//void onDraw() {
|
||||||
|
// if (GetTickCount64() >= nEndTime) {
|
||||||
|
// nEndTime = GetTickCount64() + DURATION;
|
||||||
|
// nTip = rand() % diablo2Tips.size();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Convert wstring to string for manipulation
|
||||||
|
// string strTip = string(diablo2Tips[nTip].begin(), diablo2Tips[nTip].end());
|
||||||
|
// vector<string> words = split(strTip, ' ');
|
||||||
|
|
||||||
|
// // Calculate positions for multiple lines
|
||||||
|
// int yPos = 65;
|
||||||
|
// for (int i = 0; i < words.size(); i += 5) {
|
||||||
|
// // Create a sentence from words and convert it back to wide string
|
||||||
|
// string sentence = makeSentence(words, i, min(i + 4, (int)words.size() - 1));
|
||||||
|
// wstring wSentence = stringToWstring(sentence);
|
||||||
|
// D2PrintString(const_cast<LPWSTR>(wSentence.c_str()), 152, yPos, D2Color::WHITE, 0);
|
||||||
|
// yPos += 14; // Move to the next line
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Helper function to justify a line of text
|
||||||
|
void justifyLine(const vector<string>& words, int start, int end, int maxLineLength, int yPos) {
|
||||||
|
// Handle the case when there is only one word in the line
|
||||||
|
if (start == end) {
|
||||||
|
wstring word = stringToWstring(words[start]);
|
||||||
|
D2PrintString(const_cast<LPWSTR>(word.c_str()), 130, yPos, D2Color::WHITE, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the total length of the line (excluding spaces)
|
||||||
|
int lineLength = 0;
|
||||||
|
for (int i = start; i <= end; i++) {
|
||||||
|
lineLength += D2Win_GetTextWidth(const_cast<LPWSTR>(stringToWstring(words[i]).c_str())); // Get the actual width of the word
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the number of spaces to distribute
|
||||||
|
int numSpaces = end - start;
|
||||||
|
int extraSpaces = maxLineLength - lineLength;
|
||||||
|
|
||||||
|
// Distribute the extra spaces evenly
|
||||||
|
int spaceWidth = 1;
|
||||||
|
int extraSpacePerGap = extraSpaces / numSpaces;
|
||||||
|
int remainingSpaces = extraSpaces % numSpaces;
|
||||||
|
|
||||||
|
// Build the justified line
|
||||||
|
wstring wLine;
|
||||||
|
int xPos = 152;
|
||||||
|
for (int i = start; i <= end; i++) {
|
||||||
|
wstring word = stringToWstring(words[i]);
|
||||||
|
D2PrintString(const_cast<LPWSTR>(word.c_str()), xPos, yPos, D2Color::WHITE, 0);
|
||||||
|
xPos += D2Win_GetTextWidth(const_cast<LPWSTR>(stringToWstring(words[i]).c_str())) + (spaceWidth + extraSpacePerGap);
|
||||||
|
|
||||||
|
if (remainingSpaces > 0) {
|
||||||
|
xPos += 1; // Add an extra pixel for the remaining spaces
|
||||||
|
remainingSpaces--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Refactored onDraw function
|
||||||
|
void onDraw() {
|
||||||
|
if (GetTickCount64() >= nEndTime) {
|
||||||
|
nEndTime = GetTickCount64() + DURATION;
|
||||||
|
nTip = rand() % diablo2Tips.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert wstring to string for manipulation
|
||||||
|
string strTip = string(diablo2Tips[nTip].begin(), diablo2Tips[nTip].end());
|
||||||
|
vector<string> words = split(strTip, ' ');
|
||||||
|
|
||||||
|
// Calculate positions for multiple lines
|
||||||
|
int yPos = 65;
|
||||||
|
int lineStart = 0;
|
||||||
|
int lineLength = 0;
|
||||||
|
int maxLineLength = 580 - 152; // Maximum line length in pixels
|
||||||
|
|
||||||
|
for (int i = 0; i < words.size(); i++) {
|
||||||
|
// Get the length of the current word
|
||||||
|
// int wordLength = words[i].length() * 8; // Assuming a fixed-width font with 8 pixels per character
|
||||||
|
int wordLength = D2Win_GetTextWidth(const_cast<LPWSTR>(stringToWstring(words[i]).c_str())); // Get the actual width of the word
|
||||||
|
|
||||||
|
// If adding the current word would exceed the maximum line length, print the current line
|
||||||
|
if (lineLength + wordLength > maxLineLength) {
|
||||||
|
// Justify the current line
|
||||||
|
justifyLine(words, lineStart, i - 1, maxLineLength, yPos);
|
||||||
|
|
||||||
|
// Move to the next line
|
||||||
|
yPos += 14;
|
||||||
|
lineStart = i;
|
||||||
|
lineLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the current word to the line
|
||||||
|
lineLength += wordLength + 8; // Add space length (8 pixels)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the last line if it exists
|
||||||
|
if (lineStart < words.size()) {
|
||||||
|
//justifyLine(words, lineStart, words.size() - 1, maxLineLength, yPos);
|
||||||
|
wstring wLine = stringToWstring(makeSentence(words, lineStart, words.size() - 1));
|
||||||
|
D2PrintString(const_cast<LPWSTR>(wLine.c_str()), 152, yPos, D2Color::WHITE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//// Refactored onDraw function
|
||||||
|
//void onDraw() {
|
||||||
|
// if (GetTickCount64() >= nEndTime) {
|
||||||
|
// nEndTime = GetTickCount64() + DURATION;
|
||||||
|
// nTip = rand() % diablo2Tips.size();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Convert wstring to string for manipulation
|
||||||
|
// string strTip = string(diablo2Tips[nTip].begin(), diablo2Tips[nTip].end());
|
||||||
|
// vector<string> words = split(strTip, ' ');
|
||||||
|
//
|
||||||
|
// // Calculate positions for multiple lines
|
||||||
|
// int yPos = 65;
|
||||||
|
// int lineStart = 0;
|
||||||
|
// int lineLength = 0;
|
||||||
|
// int maxLineLength = 590 - 158; // Maximum line length in pixels
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < words.size(); i++) {
|
||||||
|
// // Get the length of the current word
|
||||||
|
// int wordLength = words[i].length() * 8; // Assuming a fixed-width font with 8 pixels per character
|
||||||
|
//
|
||||||
|
// // If adding the current word would exceed the maximum line length, print the current line
|
||||||
|
// if (lineLength + wordLength > maxLineLength) {
|
||||||
|
// // Print the current line
|
||||||
|
// wstring wLine = stringToWstring(makeSentence(words, lineStart, i - 1));
|
||||||
|
// D2PrintString(const_cast<LPWSTR>(wLine.c_str()), 130, yPos, D2Color::WHITE, 0);
|
||||||
|
//
|
||||||
|
// // Move to the next line
|
||||||
|
// yPos += 14;
|
||||||
|
// lineStart = i;
|
||||||
|
// lineLength = 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Add the current word to the line
|
||||||
|
// lineLength += wordLength + 8; // Add space length (8 pixels)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Print the last line
|
||||||
|
// if (lineStart < words.size()) {
|
||||||
|
// wstring wLine = stringToWstring(makeSentence(words, lineStart, words.size() - 1));
|
||||||
|
// D2PrintString(const_cast<LPWSTR>(wLine.c_str()), 130, yPos, D2Color::WHITE, 0); //diablo2::d2_gfx::draw_filled_rect(130, 48, 640, 155, 5, 50);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FASTCALL printPageNumber(LPWSTR maxGoldText, DWORD x, DWORD y, DWORD color, DWORD bfalse)
|
void FASTCALL printPageNumber(LPWSTR maxGoldText, DWORD x, DWORD y, DWORD color, DWORD bfalse)
|
||||||
{
|
{
|
||||||
if (onRealm || !D2isLODGame() )
|
if (onRealm || !D2isLODGame() )
|
||||||
@ -355,10 +1030,9 @@ void FASTCALL printPageNumber(LPWSTR maxGoldText, DWORD x, DWORD y, DWORD color,
|
|||||||
|
|
||||||
WCHAR text[21];
|
WCHAR text[21];
|
||||||
getCurrentStashName(text, 21, ptChar);
|
getCurrentStashName(text, 21, ptChar);
|
||||||
|
|
||||||
// Replace character # by number page.
|
// Replace character # by number page.
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i=0; text[i]; i++)
|
for (int i = 0; text[i]; i++)
|
||||||
{
|
{
|
||||||
if (text[i] == L'#')
|
if (text[i] == L'#')
|
||||||
{
|
{
|
||||||
@ -368,7 +1042,7 @@ void FASTCALL printPageNumber(LPWSTR maxGoldText, DWORD x, DWORD y, DWORD color,
|
|||||||
{
|
{
|
||||||
nbDigits++;
|
nbDigits++;
|
||||||
val /= 10;
|
val /= 10;
|
||||||
} while(val);
|
} while (val);
|
||||||
j += nbDigits;
|
j += nbDigits;
|
||||||
|
|
||||||
val = currentId;
|
val = currentId;
|
||||||
@ -378,7 +1052,7 @@ void FASTCALL printPageNumber(LPWSTR maxGoldText, DWORD x, DWORD y, DWORD color,
|
|||||||
nbDigits++;
|
nbDigits++;
|
||||||
popupText[j - nbDigits] = (WCHAR)(val % 10 + 48);
|
popupText[j - nbDigits] = (WCHAR)(val % 10 + 48);
|
||||||
val /= 10;
|
val /= 10;
|
||||||
} while(val);
|
} while (val);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
popupText[j++] = text[i];
|
popupText[j++] = text[i];
|
||||||
@ -388,7 +1062,7 @@ void FASTCALL printPageNumber(LPWSTR maxGoldText, DWORD x, DWORD y, DWORD color,
|
|||||||
// Check text length vs field name length
|
// Check text length vs field name length
|
||||||
int pixelLen = D2GetPixelLen(popupText);
|
int pixelLen = D2GetPixelLen(popupText);
|
||||||
int len = wcslen(popupText);
|
int len = wcslen(popupText);
|
||||||
while(len > 0 && pixelLen > posWStashNameField - 5)
|
while (len > 0 && pixelLen > posWStashNameField - 5)
|
||||||
{
|
{
|
||||||
len--;
|
len--;
|
||||||
popupText[len] = NULL;
|
popupText[len] = NULL;
|
||||||
@ -396,24 +1070,40 @@ void FASTCALL printPageNumber(LPWSTR maxGoldText, DWORD x, DWORD y, DWORD color,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DWORD color = isShared ? (isMainIndex ? SharedMainIndexPageColor : isIndex ? SharedIndexPageColor : SharedNormalPageColor) : (isMainIndex ? PersonalMainIndexPageColor : isIndex ? PersonalIndexPageColor : PersonalNormalPageColor);
|
DWORD color = isShared ? (isMainIndex ? SharedMainIndexPageColor : isIndex ? SharedIndexPageColor : SharedNormalPageColor) : (isMainIndex ? PersonalMainIndexPageColor : isIndex ? PersonalIndexPageColor : PersonalNormalPageColor);
|
||||||
D2PrintString(popupText, x, y, color, bfalse);
|
|
||||||
|
|
||||||
if (isOnStashNameField(mx, my))
|
// By HashCasper
|
||||||
{
|
D2PrintString(popupText, 152, 605, color, bfalse);
|
||||||
_snwprintf(popupText, 0x400, getLocalString(STR_PAGE_TYPE_CHANGE), currentId);
|
|
||||||
D2PrintPopup(popupText, getXStashNameField() + posWStashNameField/2, getYStashNameField() - posHStashNameField - 2, WHITE, 1);
|
// Mapping from int to ui_font_t
|
||||||
}
|
//std::map<int, diablo2::ui_font_t> fontMap = {
|
||||||
}
|
// {0, diablo2::ui_font_t::UI_FONT_8},
|
||||||
|
// {1, diablo2::ui_font_t::UI_FONT_16},
|
||||||
|
// {2, diablo2::ui_font_t::UI_FONT_30},
|
||||||
|
// {3, diablo2::ui_font_t::UI_FONT_42},
|
||||||
|
// {4, diablo2::ui_font_t::UI_FONT_FORMAL10},
|
||||||
|
// {5, diablo2::ui_font_t::UI_FONT_FORMAL12},
|
||||||
|
// {6, diablo2::ui_font_t::UI_FONT_6},
|
||||||
|
// {7, diablo2::ui_font_t::UI_FONT_24},
|
||||||
|
// {8, diablo2::ui_font_t::UI_FONT_FORMAL11},
|
||||||
|
// {9, diablo2::ui_font_t::UI_FONT_EXOCET10},
|
||||||
|
// {10, diablo2::ui_font_t::UI_FONT_RIDICULOUS},
|
||||||
|
// {11, diablo2::ui_font_t::UI_FONT_EXOCET8},
|
||||||
|
// {12, diablo2::ui_font_t::UI_FONT_REALLYTHELASTSUCKER},
|
||||||
|
// {13, diablo2::ui_font_t::UI_FONT_INGAMECHAT}
|
||||||
|
//};
|
||||||
|
|
||||||
|
|
||||||
|
D2SetFont(2);
|
||||||
|
WCHAR HashString[] = L"Ironman Mod by Hash";
|
||||||
|
D2PrintString(HashString, 150, 35, color, bfalse);
|
||||||
|
|
||||||
|
// Print Random Tips
|
||||||
|
D2SetFont(0);
|
||||||
|
onDraw();
|
||||||
|
|
||||||
|
// Reset font after printing
|
||||||
|
D2SetFont(8);
|
||||||
|
|
||||||
//printGoldMaxPopup
|
|
||||||
if (isOnStashGoldField(mx, my))
|
|
||||||
{
|
|
||||||
if (active_sharedGold)
|
|
||||||
{
|
|
||||||
_snwprintf(popupText, 0x400, L"%s\n%s: %u", maxGoldText, getLocalString(STR_SHARED_GOLD_QUANTITY), PCPY->sharedGold);
|
|
||||||
D2PrintPopup(popupText, getXStashGoldField() + posWStashGoldField/2, getYStashGoldField() - posHStashGoldField - 2, WHITE, 1);
|
|
||||||
} else
|
|
||||||
D2PrintPopup(maxGoldText, getXStashGoldField() + posWStashGoldField/2, getYStashGoldField() - posHStashGoldField - 2, WHITE, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +1315,11 @@ void Install_InterfaceStash()
|
|||||||
|
|
||||||
// print page number
|
// print page number
|
||||||
mem_seek R8(D2Client, 3903C, 3903C, 3F375, B0FE3, 7DF63, B3633, 99A33, 9DE03, 8F2E5);
|
mem_seek R8(D2Client, 3903C, 3903C, 3F375, B0FE3, 7DF63, B3633, 99A33, 9DE03, 8F2E5);
|
||||||
|
|
||||||
MEMJ_REF4( D2PrintString, printPageNumber);
|
MEMJ_REF4( D2PrintString, printPageNumber);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//6FADF374 |. E8 3FCC0800 CALL <JMP.&D2Win.#10117>
|
//6FADF374 |. E8 3FCC0800 CALL <JMP.&D2Win.#10117>
|
||||||
//6FB60FE2 |. E8 99C2F5FF CALL <JMP.&D2Win.#10020>
|
//6FB60FE2 |. E8 99C2F5FF CALL <JMP.&D2Win.#10020>
|
||||||
//6FB2DF62 |. E8 19F3F8FF CALL <JMP.&D2Win.#10064>
|
//6FB2DF62 |. E8 19F3F8FF CALL <JMP.&D2Win.#10064>
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
union{
|
union{
|
||||||
@ -35,6 +36,7 @@ static struct
|
|||||||
#define getYNextPageBtn() RY(D2GetResolution()?0x40:0x70)
|
#define getYNextPageBtn() RY(D2GetResolution()?0x40:0x70)
|
||||||
#define getHNextPageBtn() 32
|
#define getHNextPageBtn() 32
|
||||||
#define isOnNextPageBtn(x,y) isOnRect(x, y, getXNextPageBtn(), getYNextPageBtn(), getLNextPageBtn(), getHNextPageBtn())
|
#define isOnNextPageBtn(x,y) isOnRect(x, y, getXNextPageBtn(), getYNextPageBtn(), getLNextPageBtn(), getHNextPageBtn())
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +51,7 @@ void STDCALL printStatsPageBtns()
|
|||||||
sDrawImageInfo data;
|
sDrawImageInfo data;
|
||||||
ZeroMemory(&data,sizeof(data));
|
ZeroMemory(&data,sizeof(data));
|
||||||
|
|
||||||
if (printBackgroundOnMainPage && D2GetResolution())
|
if (printBackgroundOnMainPage)
|
||||||
{
|
{
|
||||||
setImage(&data, statsBackgroundImages);
|
setImage(&data, statsBackgroundImages);
|
||||||
setFrame(&data, 1);
|
setFrame(&data, 1);
|
||||||
@ -57,16 +59,14 @@ void STDCALL printStatsPageBtns()
|
|||||||
}
|
}
|
||||||
|
|
||||||
setImage(&data, D2LoadBuySelBtn());
|
setImage(&data, D2LoadBuySelBtn());
|
||||||
if (D2GetResolution())
|
|
||||||
{
|
|
||||||
setFrame(&data, 12 + isDownBtn.previousPage);
|
setFrame(&data, 12 + isDownBtn.previousPage);
|
||||||
D2PrintImage(&data, getXPreviousPageBtn(), getYPreviousPageBtn(), -1, 5, 0);
|
D2PrintImage(&data, getXPreviousPageBtn(), getYPreviousPageBtn(), -1, 5, 0);
|
||||||
}
|
|
||||||
setFrame(&data, 14 + isDownBtn.nextPage);
|
setFrame(&data, 14 + isDownBtn.nextPage);
|
||||||
D2PrintImage(&data, getXNextPageBtn(), getYNextPageBtn(), -1, 5, 0);
|
D2PrintImage(&data, getXNextPageBtn(), getYNextPageBtn(), -1, 5, 0);
|
||||||
|
|
||||||
D2SetFont(1);
|
D2SetFont(1);
|
||||||
if (D2GetResolution() && isOnPreviousPageBtn(mx,my)) //print popup "previous page"
|
if (isOnPreviousPageBtn(mx,my)) //print popup "previous page"
|
||||||
{
|
{
|
||||||
lpText = getLocalString(STR_PREVIOUS_PAGE);
|
lpText = getLocalString(STR_PREVIOUS_PAGE);
|
||||||
D2PrintPopup(lpText, getXPreviousPageBtn()+getLPreviousPageBtn()/2, getYPreviousPageBtn()-getHPreviousPageBtn(), WHITE, 1);
|
D2PrintPopup(lpText, getXPreviousPageBtn()+getLPreviousPageBtn()/2, getYPreviousPageBtn()-getHPreviousPageBtn(), WHITE, 1);
|
||||||
@ -84,6 +84,12 @@ Unit* STDCALL statsPageMouseDown(sWinMessage* msg)
|
|||||||
|
|
||||||
if (!active_newInterfaces || !D2isLODGame() ) return ptChar;
|
if (!active_newInterfaces || !D2isLODGame() ) return ptChar;
|
||||||
|
|
||||||
|
if (statsLeftDown(msg)) {
|
||||||
|
freeMessage(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (D2GetResolution() && isOnPreviousPageBtn(msg->x,msg->y))
|
if (D2GetResolution() && isOnPreviousPageBtn(msg->x,msg->y))
|
||||||
{
|
{
|
||||||
log_msg("push down left button previous page\n");
|
log_msg("push down left button previous page\n");
|
||||||
@ -100,6 +106,7 @@ Unit* STDCALL statsPageMouseDown(sWinMessage* msg)
|
|||||||
freeMessage(msg);
|
freeMessage(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return ptChar;
|
return ptChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +117,13 @@ Unit* STDCALL statsPageMouseUp(sWinMessage* msg)
|
|||||||
|
|
||||||
if (!active_newInterfaces || !D2isLODGame() ) return ptChar;
|
if (!active_newInterfaces || !D2isLODGame() ) return ptChar;
|
||||||
|
|
||||||
|
if (statsLeftUp(msg)) {
|
||||||
|
isDownBtn.all=0;
|
||||||
|
freeMessage(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (D2GetResolution() && isOnPreviousPageBtn(msg->x,msg->y))
|
if (D2GetResolution() && isOnPreviousPageBtn(msg->x,msg->y))
|
||||||
{
|
{
|
||||||
log_msg("push up left button previous page\n");
|
log_msg("push up left button previous page\n");
|
||||||
@ -134,6 +148,7 @@ Unit* STDCALL statsPageMouseUp(sWinMessage* msg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
isDownBtn.all=0;
|
isDownBtn.all=0;
|
||||||
return ptChar;
|
return ptChar;
|
||||||
|
@ -51,7 +51,7 @@ LPCWSTR getLocalTypeString(DWORD code)
|
|||||||
{
|
{
|
||||||
if (sLocalizedTypeStrings[i].code == code)
|
if (sLocalizedTypeStrings[i].code == code)
|
||||||
{
|
{
|
||||||
log_msg("Code=%08X\n", code);
|
//log_msg("Code=%08X\n", code);
|
||||||
if (sLocalizedTypeStrings[i].itemStr)
|
if (sLocalizedTypeStrings[i].itemStr)
|
||||||
return StripGender(D2GetStringFromString(sLocalizedTypeStrings[i].itemStr));
|
return StripGender(D2GetStringFromString(sLocalizedTypeStrings[i].itemStr));
|
||||||
LPWSTR text = StripGender(sLocalizedTypeStrings[i].typeLocalizedString);
|
LPWSTR text = StripGender(sLocalizedTypeStrings[i].typeLocalizedString);
|
||||||
@ -300,6 +300,8 @@ void loadLocalizedStrings(int language)
|
|||||||
LOAD(STR_SHARED_GOLD_QUANTITY);
|
LOAD(STR_SHARED_GOLD_QUANTITY);
|
||||||
LOAD(STR_PREVIOUS_PAGE);
|
LOAD(STR_PREVIOUS_PAGE);
|
||||||
LOAD(STR_NEXT_PAGE);
|
LOAD(STR_NEXT_PAGE);
|
||||||
|
LOAD(STR_PREVIOUS_RUNE);
|
||||||
|
LOAD(STR_NEXT_RUNE);
|
||||||
LOAD(STR_ITEM_LEVEL);
|
LOAD(STR_ITEM_LEVEL);
|
||||||
LOAD(STR_PAGE_TYPE_CHANGE);
|
LOAD(STR_PAGE_TYPE_CHANGE);
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ enum eStringList
|
|||||||
STR_SHARED_GOLD_QUANTITY,
|
STR_SHARED_GOLD_QUANTITY,
|
||||||
STR_PREVIOUS_PAGE,
|
STR_PREVIOUS_PAGE,
|
||||||
STR_NEXT_PAGE,
|
STR_NEXT_PAGE,
|
||||||
|
STR_PREVIOUS_RUNE,
|
||||||
|
STR_NEXT_RUNE,
|
||||||
STR_ITEM_LEVEL,
|
STR_ITEM_LEVEL,
|
||||||
STR_PAGE_TYPE_CHANGE,
|
STR_PAGE_TYPE_CHANGE,
|
||||||
//
|
//
|
||||||
|
@ -233,12 +233,6 @@ DWORD print(CubeMainBIN* curForm, LPWSTR buf, LPINT len, DWORD)//maxsize)
|
|||||||
printInputItem(&curForm->input6, buf, len, &realNbInputs);
|
printInputItem(&curForm->input6, buf, len, &realNbInputs);
|
||||||
printInputItem(&curForm->input7, buf, len, &realNbInputs);
|
printInputItem(&curForm->input7, buf, len, &realNbInputs);
|
||||||
|
|
||||||
if (realNbInputs != curForm->numinputs)
|
|
||||||
{
|
|
||||||
PRINT(BUF, L" *** ERROR : numInputs(%d) != realNbInputs(%d) ***", curForm->numinputs, realNbInputs);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRINT(BUF,L" => ");
|
PRINT(BUF,L" => ");
|
||||||
int realNbOutputs=0;
|
int realNbOutputs=0;
|
||||||
|
|
||||||
@ -269,6 +263,9 @@ DWORD print(CubeMainBIN* curForm, LPWSTR buf, LPINT len, DWORD)//maxsize)
|
|||||||
// if (curForm->version == 100)
|
// if (curForm->version == 100)
|
||||||
// sprintf(BUF, " [expansion only]");
|
// sprintf(BUF, " [expansion only]");
|
||||||
|
|
||||||
|
if (realNbInputs != curForm->numinputs)
|
||||||
|
PRINT(BUF, L" *** ERROR : numInputs(%d) != realNbInputs(%d) ***", curForm->numinputs, realNbInputs);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#undef BUF
|
#undef BUF
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
#define NB_RUNES_PER_PAGE 25
|
#define NB_RUNES_PER_PAGE 25
|
||||||
|
|
||||||
#define getXCloseBtn() 360
|
#define getXCloseBtn() 360
|
||||||
@ -53,6 +54,7 @@ static struct
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
} isDownBtn;
|
} isDownBtn;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
void printRuneword(RunesBIN* runesData, DWORD pos)
|
void printRuneword(RunesBIN* runesData, DWORD pos)
|
||||||
@ -64,7 +66,7 @@ void printRuneword(RunesBIN* runesData, DWORD pos)
|
|||||||
D2SetFont(6);
|
D2SetFont(6);
|
||||||
DWORD nbPixel = D2GetPixelLen(lpText);
|
DWORD nbPixel = D2GetPixelLen(lpText);
|
||||||
DWORD x1 = (nbPixel >= 195) ? 0 : 195-nbPixel;
|
DWORD x1 = (nbPixel >= 195) ? 0 : 195-nbPixel;
|
||||||
D2PrintString(lpText, x1, 10 + pos*20, GOLD, 0);//MILIEU(0x00,0x70,nbPixel)
|
D2PrintString(lpText, posXRunesList + RX(x1), posYRunesList + 10 + pos*20, GOLD, 0);//MILIEU(0x00,0x70,nbPixel)
|
||||||
|
|
||||||
typesList[0]=L'\0';
|
typesList[0]=L'\0';
|
||||||
DWORD numItype=0;
|
DWORD numItype=0;
|
||||||
@ -80,7 +82,7 @@ void printRuneword(RunesBIN* runesData, DWORD pos)
|
|||||||
}
|
}
|
||||||
nbPixel = D2GetPixelLen(typesList);
|
nbPixel = D2GetPixelLen(typesList);
|
||||||
x1 = (nbPixel >= 195) ? 0 : 195-nbPixel;
|
x1 = (nbPixel >= 195) ? 0 : 195-nbPixel;
|
||||||
D2PrintString(typesList, x1, 20 + pos*20, WHITE, 0);//MILIEU(0x70,0xA0,nbPixel)
|
D2PrintString(typesList, posXRunesList + RX(x1), posYRunesList + 20 + pos*20, WHITE, 0);//MILIEU(0x70,0xA0,nbPixel)
|
||||||
|
|
||||||
runesList[0]=L'\0';
|
runesList[0]=L'\0';
|
||||||
DWORD numRune=0;
|
DWORD numRune=0;
|
||||||
@ -115,7 +117,7 @@ void printRuneword(RunesBIN* runesData, DWORD pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// x1 = (nbPixel < 145) ? 155 : 300-nbPixel;
|
// x1 = (nbPixel < 145) ? 155 : 300-nbPixel;
|
||||||
D2PrintString(runesList, x1, y1 + pos*20, WHITE, 0);//MILIEU(0xD0,0xA0,nbPixel)
|
D2PrintString(runesList, posXRunesList + RX(x1), posYRunesList + y1 + pos*20, WHITE, 0);//MILIEU(0xD0,0xA0,nbPixel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -123,48 +125,58 @@ void printRuneword(RunesBIN* runesData, DWORD pos)
|
|||||||
//6FB21FAA
|
//6FB21FAA
|
||||||
void STDCALL printRunewordsPage()
|
void STDCALL printRunewordsPage()
|
||||||
{
|
{
|
||||||
if (!D2isLODGame() || !D2GetResolution()) return D2PrintStatsPage();
|
if (!D2isLODGame()) return D2PrintStatsPage();
|
||||||
|
|
||||||
LPWSTR lpText;
|
LPWSTR lpText;
|
||||||
bDontPrintBorder = true;
|
bDontPrintBorder = D2GetResolution()? true : false;
|
||||||
|
|
||||||
//Init data for print image
|
//Init data for print image
|
||||||
sDrawImageInfo data;
|
sDrawImageInfo data;
|
||||||
ZeroMemory(&data,sizeof(data));
|
ZeroMemory(&data,sizeof(data));
|
||||||
|
|
||||||
//print background
|
//print background
|
||||||
/* setImage(&data, newStatsInterfaceImages);
|
fillRect(RX(0), RY(ResolutionY), 512, 768, 0, 5);
|
||||||
|
setImage(&data, newStatsInterfaceImages);
|
||||||
setFrame(&data, 0);
|
setFrame(&data, 0);
|
||||||
D2PrintImage(&data, 0, 256, -1, 5, 0);
|
D2PrintImage(&data, RX(0), RY(ResolutionY-256), -1, 5, 0);
|
||||||
setFrame(&data, 1);
|
setFrame(&data, 1);
|
||||||
D2PrintImage(&data, 256,256, -1, 5, 0);
|
D2PrintImage(&data, RX(256),RY(ResolutionY-256), -1, 5, 0);
|
||||||
setFrame(&data, 2);
|
setFrame(&data, 2);
|
||||||
D2PrintImage(&data, 0, 512, -1, 5, 0);
|
D2PrintImage(&data, RX(0), RY(ResolutionY-256*2), -1, 5, 0);
|
||||||
setFrame(&data, 3);
|
setFrame(&data, 3);
|
||||||
D2PrintImage(&data, 256,512, -1, 5, 0);
|
D2PrintImage(&data, RX(256),RY(ResolutionY-256*2), -1, 5, 0);
|
||||||
setFrame(&data, 4);
|
setFrame(&data, 4);
|
||||||
D2PrintImage(&data, 0, 552, -1, 5, 0);
|
D2PrintImage(&data, RX(0), RY(ResolutionY-256*3), -1, 5, 0);
|
||||||
setFrame(&data, 5);
|
setFrame(&data, 5);
|
||||||
D2PrintImage(&data, 256,552, -1, 5, 0);
|
D2PrintImage(&data, RX(256),RY(ResolutionY-256*3), -1, 5, 0);
|
||||||
*/
|
|
||||||
fillRect(0,0,400,552,0,5);
|
if (printBackgroundOnMainPage)
|
||||||
|
{
|
||||||
|
setImage(&data, statsBackgroundImages);
|
||||||
|
setFrame(&data, 1);
|
||||||
|
D2PrintImage(&data, getXPreviousPageBtn()-7, getYPreviousPageBtn()+8, -1, 5, 0);
|
||||||
|
D2PrintImage(&data, getXPrevRunesBtn()-7, getYPrevRunesBtn()+8, -1, 5, 0);
|
||||||
|
}
|
||||||
|
|
||||||
//print button close
|
//print button close
|
||||||
setImage(&data, D2LoadBuySelBtn());
|
setImage(&data, D2LoadBuySelBtn());
|
||||||
setFrame(&data, 10 + isDownBtn.close);
|
setFrame(&data, 10 + isDownBtn.close);
|
||||||
D2PrintImage(&data, getXCloseBtn(), getYCloseBtn(), -1, 5, 0);
|
D2PrintImage(&data, getXCloseBtn(), getYCloseBtn(), -1, 5, 0);
|
||||||
|
|
||||||
|
//print previous page button
|
||||||
|
setFrame(&data, 12 + isDownBtn.previousPage);
|
||||||
|
D2PrintImage(&data, getXPreviousPageBtn(), getYPreviousPageBtn(), -1, 5, 0);
|
||||||
|
|
||||||
//print next page button
|
//print next page button
|
||||||
setFrame(&data, isDownBtn.nextPage);
|
setFrame(&data, 14 + isDownBtn.nextPage);
|
||||||
D2PrintImage(&data, getXNextPageBtn(), getYNextPageBtn(), -1, 5, 0);
|
D2PrintImage(&data, getXNextPageBtn(), getYNextPageBtn(), -1, 5, 0);
|
||||||
|
|
||||||
//print previous runes button
|
//print previous runes button
|
||||||
setImage(&data, stashBtnsImages);
|
setFrame(&data, 12 + isDownBtn.prevRunes);
|
||||||
setFrame(&data, isDownBtn.prevRunes);
|
|
||||||
D2PrintImage(&data, getXPrevRunesBtn(), getYPrevRunesBtn(), -1, 5, 0);
|
D2PrintImage(&data, getXPrevRunesBtn(), getYPrevRunesBtn(), -1, 5, 0);
|
||||||
|
|
||||||
//print previous runes button
|
//print previous runes button
|
||||||
setFrame(&data, 2 + isDownBtn.nextRunes);
|
setFrame(&data, 14 + isDownBtn.nextRunes);
|
||||||
D2PrintImage(&data, getXNextRunesBtn(), getYNextRunesBtn(), -1, 5, 0);
|
D2PrintImage(&data, getXNextRunesBtn(), getYNextRunesBtn(), -1, 5, 0);
|
||||||
|
|
||||||
D2SetFont(6);
|
D2SetFont(6);
|
||||||
@ -181,11 +193,11 @@ void STDCALL printRunewordsPage()
|
|||||||
{
|
{
|
||||||
if (!runesData->Complete || runesData->Server) continue;
|
if (!runesData->Complete || runesData->Server) continue;
|
||||||
nbRunesCompleted++;
|
nbRunesCompleted++;
|
||||||
if ( (curRunesPage * NB_RUNES_PER_PAGE < nbRunesCompleted) &&
|
if ( (curRunesPage * runesPerPage < nbRunesCompleted) &&
|
||||||
(nbRunesCompleted <= (curRunesPage+1) * NB_RUNES_PER_PAGE) )
|
(nbRunesCompleted <= (curRunesPage+1) * runesPerPage) )
|
||||||
printRuneword(runesData, curNbRunes++);
|
printRuneword(runesData, curNbRunes++);
|
||||||
}
|
}
|
||||||
maxRunesPage = nbRunesCompleted ? (nbRunesCompleted-1) / NB_RUNES_PER_PAGE : 0;
|
maxRunesPage = nbRunesCompleted ? (nbRunesCompleted-1) / runesPerPage : 0;
|
||||||
|
|
||||||
|
|
||||||
//////////////////// POPUP PRINTING ////////////////////
|
//////////////////// POPUP PRINTING ////////////////////
|
||||||
@ -197,11 +209,26 @@ void STDCALL printRunewordsPage()
|
|||||||
{
|
{
|
||||||
D2PrintPopup(D2GetStringFromIndex(0x1030), getXCloseBtn()+getLCloseBtn()/2, getYCloseBtn()-getHCloseBtn(), WHITE, 1);
|
D2PrintPopup(D2GetStringFromIndex(0x1030), getXCloseBtn()+getLCloseBtn()/2, getYCloseBtn()-getHCloseBtn(), WHITE, 1);
|
||||||
}
|
}
|
||||||
|
else if (isOnPreviousPageBtn(x,y)) //print popup "previous page"
|
||||||
|
{
|
||||||
|
lpText = getLocalString(STR_PREVIOUS_PAGE);
|
||||||
|
D2PrintPopup(lpText, getXPreviousPageBtn()+getLPreviousPageBtn()/2, getYPreviousPageBtn()-getHPreviousPageBtn(), WHITE, 1);
|
||||||
|
}
|
||||||
else if (isOnNextPageBtn(x,y)) // print popup "next page"
|
else if (isOnNextPageBtn(x,y)) // print popup "next page"
|
||||||
{
|
{
|
||||||
lpText = getLocalString(STR_NEXT_PAGE);
|
lpText = getLocalString(STR_NEXT_PAGE);
|
||||||
D2PrintPopup(lpText, getXNextPageBtn()+getLNextPageBtn()/2, getYNextPageBtn()-getHNextPageBtn(), WHITE, 1);
|
D2PrintPopup(lpText, getXNextPageBtn()+getLNextPageBtn()/2, getYNextPageBtn()-getHNextPageBtn(), WHITE, 1);
|
||||||
}
|
}
|
||||||
|
else if (isOnPrevRunesBtn(x,y)) // print popup "previous rune"
|
||||||
|
{
|
||||||
|
lpText = getLocalString(STR_PREVIOUS_RUNE);
|
||||||
|
D2PrintPopup(lpText, getXPrevRunesBtn()+getLPrevRunesBtn()/2, getYPrevRunesBtn()-getHPrevRunesBtn(), WHITE, 1);
|
||||||
|
}
|
||||||
|
else if (isOnNextRunesBtn(x,y)) // print popup "next rune"
|
||||||
|
{
|
||||||
|
lpText = getLocalString(STR_NEXT_RUNE);
|
||||||
|
D2PrintPopup(lpText, getXNextRunesBtn()+getLNextRunesBtn()/2, getYNextRunesBtn()-getHNextRunesBtn(), WHITE, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
#define getXCloseBtn() 360
|
#define getXCloseBtn() 360
|
||||||
#define getLCloseBtn() 32
|
#define getLCloseBtn() 32
|
||||||
#define getYCloseBtn() (ResolutionY - 60)
|
#define getYCloseBtn() (ResolutionY - 60)
|
||||||
@ -92,6 +93,7 @@ void** ptD2AssignStatsPointsBtnImages = (void**)0x6FBB5BB4;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
union{
|
union{
|
||||||
@ -111,6 +113,7 @@ static struct
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
} isDownBtn;
|
} isDownBtn;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
void print2Lines(WORD id, LPWSTR lpText, DWORD x, DWORD l, DWORD y)
|
void print2Lines(WORD id, LPWSTR lpText, DWORD x, DWORD l, DWORD y)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
#define getXCloseBtn() RX(0x110)
|
#define getXCloseBtn() RX(0x110)
|
||||||
#define getLCloseBtn() 32
|
#define getLCloseBtn() 32
|
||||||
#define getYCloseBtn() RY(0x40)
|
#define getYCloseBtn() RY(0x40)
|
||||||
@ -29,11 +30,13 @@
|
|||||||
#define getYNextPageBtn() RY(0x40)
|
#define getYNextPageBtn() RY(0x40)
|
||||||
#define getHNextPageBtn() 32
|
#define getHNextPageBtn() 32
|
||||||
#define isOnNextPageBtn(x,y) isOnRect(x, y, getXNextPageBtn(), getYNextPageBtn(), getLNextPageBtn(), getHNextPageBtn())
|
#define isOnNextPageBtn(x,y) isOnRect(x, y, getXNextPageBtn(), getYNextPageBtn(), getLNextPageBtn(), getHNextPageBtn())
|
||||||
|
*/
|
||||||
|
|
||||||
const char * STATS_INTERFACE_FILENAME = "PlugY\\statsinterface.txt";
|
const char * STATS_INTERFACE_FILENAME = "PlugY\\statsinterface.txt";
|
||||||
|
|
||||||
#define BUFSIZE 0x400
|
#define BUFSIZE 0x400
|
||||||
|
|
||||||
|
/*
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
union{
|
union{
|
||||||
@ -45,6 +48,7 @@ static struct
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
} isDownBtn;
|
} isDownBtn;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
struct statsInterfaceBIN
|
struct statsInterfaceBIN
|
||||||
@ -337,8 +341,7 @@ void STDCALL printNewStatsPageTwo(int currentPage)
|
|||||||
|
|
||||||
WCHAR text[BUFSIZE];
|
WCHAR text[BUFSIZE];
|
||||||
LPWSTR lpText;
|
LPWSTR lpText;
|
||||||
bDontPrintBorder = false;
|
bDontPrintBorder = D2GetResolution()? true : false;
|
||||||
|
|
||||||
Unit* ptChar = D2GetClientPlayer();
|
Unit* ptChar = D2GetClientPlayer();
|
||||||
|
|
||||||
d2_assert(!ptChar, "Printing stats page : no character selected",__FILE__,__LINE__);
|
d2_assert(!ptChar, "Printing stats page : no character selected",__FILE__,__LINE__);
|
||||||
@ -349,16 +352,20 @@ void STDCALL printNewStatsPageTwo(int currentPage)
|
|||||||
ZeroMemory(&data,sizeof(data));
|
ZeroMemory(&data,sizeof(data));
|
||||||
|
|
||||||
//print background
|
//print background
|
||||||
fillRect(RX(0),RY(480),320,432,0,5);//552
|
fillRect(RX(0), RY(ResolutionY), 512, 768, 0, 5);
|
||||||
setImage(&data, newStatsInterfaceImages);
|
setImage(&data, newStatsInterfaceImages);
|
||||||
setFrame(&data, 0);
|
setFrame(&data, 0);
|
||||||
D2PrintImage(&data, RX(0), RY(224), -1, 5, 0);
|
D2PrintImage(&data, RX(0), RY(ResolutionY-256), -1, 5, 0);
|
||||||
setFrame(&data, 1);
|
setFrame(&data, 1);
|
||||||
D2PrintImage(&data, RX(256),RY(224), -1, 5, 0);//256
|
D2PrintImage(&data, RX(256),RY(ResolutionY-256), -1, 5, 0);
|
||||||
setFrame(&data, 2);
|
setFrame(&data, 2);
|
||||||
D2PrintImage(&data, RX(0), RY(48), -1, 5, 0);//432
|
D2PrintImage(&data, RX(0), RY(ResolutionY-256*2), -1, 5, 0);
|
||||||
setFrame(&data, 3);
|
setFrame(&data, 3);
|
||||||
D2PrintImage(&data, RX(256),RY(48), -1, 5, 0);
|
D2PrintImage(&data, RX(256),RY(ResolutionY-256*2), -1, 5, 0);
|
||||||
|
setFrame(&data, 4);
|
||||||
|
D2PrintImage(&data, RX(0), RY(ResolutionY-256*3), -1, 5, 0);
|
||||||
|
setFrame(&data, 5);
|
||||||
|
D2PrintImage(&data, RX(256),RY(ResolutionY-256*3), -1, 5, 0);
|
||||||
|
|
||||||
D2SetFont(1);
|
D2SetFont(1);
|
||||||
for (int i=0; i<nbStatsInterface; i++)
|
for (int i=0; i<nbStatsInterface; i++)
|
||||||
@ -392,10 +399,12 @@ void STDCALL printNewStatsPageTwo(int currentPage)
|
|||||||
D2PrintString(text, x, y, WHITE, 0);
|
D2PrintString(text, x, y, WHITE, 0);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (printBackgroundOnMainPage) {
|
||||||
//print background previous/next page buttons
|
//print background previous/next page buttons
|
||||||
setImage(&data, statsBackgroundImages);
|
setImage(&data, statsBackgroundImages);
|
||||||
setFrame(&data, D2GetResolution()?1:0);
|
setFrame(&data, 1);
|
||||||
D2PrintImage(&data, getXPreviousPageBtn()-7, getYPreviousPageBtn()+8, -1, 5, 0);
|
D2PrintImage(&data, getXPreviousPageBtn()-7, getYPreviousPageBtn()+8, -1, 5, 0);
|
||||||
|
}
|
||||||
|
|
||||||
//print button close
|
//print button close
|
||||||
setImage(&data, D2LoadBuySelBtn());
|
setImage(&data, D2LoadBuySelBtn());
|
||||||
|
@ -22,11 +22,39 @@ bool active_newInterfaces=false;
|
|||||||
bool selectMainPageOnOpenning=true;
|
bool selectMainPageOnOpenning=true;
|
||||||
bool printBackgroundOnMainPage=true;
|
bool printBackgroundOnMainPage=true;
|
||||||
|
|
||||||
|
int posXNextPageBtn = -1;
|
||||||
|
int posYNextPageBtn = -1;
|
||||||
|
int posXPrevPageBtn = -1;
|
||||||
|
int posYPrevPageBtn = -1;
|
||||||
|
int posXClosePageBtn = -1;
|
||||||
|
int posYClosePageBtn = -1;
|
||||||
|
int posXNextRuneBtn = -1;
|
||||||
|
int posYNextRuneBtn = -1;
|
||||||
|
int posXPrevRuneBtn = -1;
|
||||||
|
int posYPrevRuneBtn = -1;
|
||||||
|
int posXRunesList = -1;
|
||||||
|
int posYRunesList = -1;
|
||||||
|
int runesPerPage = -1;
|
||||||
|
|
||||||
|
DWORD getXNextPageBtn() {return RX(posXNextPageBtn);}
|
||||||
|
DWORD getYNextPageBtn() {return RY(posYNextPageBtn);}
|
||||||
|
DWORD getXPreviousPageBtn() {return RX(posXPrevPageBtn);}
|
||||||
|
DWORD getYPreviousPageBtn() {return RY(posYPrevPageBtn);}
|
||||||
|
DWORD getXCloseBtn() {return RX(posXClosePageBtn);}
|
||||||
|
DWORD getYCloseBtn() {return RY(posYClosePageBtn);}
|
||||||
|
DWORD getXNextRunesBtn() {return RX(posXNextRuneBtn);}
|
||||||
|
DWORD getYNextRunesBtn() {return RY(posYNextRuneBtn);}
|
||||||
|
DWORD getXPrevRunesBtn() {return RX(posXPrevRuneBtn);}
|
||||||
|
DWORD getYPrevRunesBtn() {return RY(posYPrevRuneBtn);}
|
||||||
|
|
||||||
DWORD bDontPrintBorder=false;
|
DWORD bDontPrintBorder=false;
|
||||||
|
|
||||||
int selectedPage=0;
|
int selectedPage=0;
|
||||||
int lastPage=0;
|
int lastPage=0;
|
||||||
int extraHiddenPage=0;
|
int extraHiddenPage=0;
|
||||||
|
int curRunesPage=0;
|
||||||
|
int maxRunesPage=0xFFFF;
|
||||||
|
BtnState isDownBtn={0};
|
||||||
|
|
||||||
void GoNextStatPage()
|
void GoNextStatPage()
|
||||||
{
|
{
|
||||||
@ -44,8 +72,12 @@ void GoPreviousStatPage()
|
|||||||
|
|
||||||
void GoStatPage(int page)
|
void GoStatPage(int page)
|
||||||
{
|
{
|
||||||
if ( (page >= 0) && (page <= lastPage + (D2GetResolution()? extraHiddenPage : 0)) )
|
if ( (page >= 0) && (page <= (lastPage + extraHiddenPage)) )
|
||||||
selectedPage = page;
|
selectedPage = page;
|
||||||
|
else if (page < 0)
|
||||||
|
selectedPage = lastPage + extraHiddenPage;
|
||||||
|
else
|
||||||
|
selectedPage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetCurrentPage()
|
int GetCurrentPage()
|
||||||
@ -83,6 +115,16 @@ DWORD STDCALL mouseCustomPageLeftDown(sWinMessage* msg)
|
|||||||
DWORD STDCALL mouseCustomPageLeftUp(sWinMessage* msg)
|
DWORD STDCALL mouseCustomPageLeftUp(sWinMessage* msg)
|
||||||
{
|
{
|
||||||
if(onRealm) return -1;
|
if(onRealm) return -1;
|
||||||
|
|
||||||
|
if (selectedPage == 0) return -1;
|
||||||
|
if (!isOnStatsPage(msg->x,msg->y)) return 1;
|
||||||
|
statsLeftUp(msg);
|
||||||
|
D2CleanStatMouseUp();
|
||||||
|
freeMessage(msg);
|
||||||
|
isDownBtn.all=0;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
if ( (selectedPage > 0) && (selectedPage <= lastPage) )
|
if ( (selectedPage > 0) && (selectedPage <= lastPage) )
|
||||||
return mouseNewStatsPageTwoLeftUp(msg);
|
return mouseNewStatsPageTwoLeftUp(msg);
|
||||||
else if (selectedPage == lastPage+1)
|
else if (selectedPage == lastPage+1)
|
||||||
@ -91,6 +133,87 @@ DWORD STDCALL mouseCustomPageLeftUp(sWinMessage* msg)
|
|||||||
return mouseNewStatsPageLeftUp(msg);
|
return mouseNewStatsPageLeftUp(msg);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD STDCALL statsLeftDown(sWinMessage* msg)
|
||||||
|
{
|
||||||
|
if (isOnCloseBtn(msg->x,msg->y) && selectedPage != 0)
|
||||||
|
{
|
||||||
|
log_msg("push down left button close\n");
|
||||||
|
isDownBtn.close = 1;
|
||||||
|
D2PlaySound(4,0,0,0,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isOnPreviousPageBtn(msg->x,msg->y))
|
||||||
|
{
|
||||||
|
log_msg("push down left button previous page\n");
|
||||||
|
isDownBtn.previousPage = 1;
|
||||||
|
D2PlaySound(4,0,0,0,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isOnNextPageBtn(msg->x,msg->y))
|
||||||
|
{
|
||||||
|
log_msg("push down left button next page\n");
|
||||||
|
isDownBtn.nextPage = 1;
|
||||||
|
D2PlaySound(4,0,0,0,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isOnPrevRunesBtn(msg->x,msg->y) && selectedPage == (lastPage + extraHiddenPage))
|
||||||
|
{
|
||||||
|
log_msg("push down left button prev runes\n");
|
||||||
|
isDownBtn.prevRunes = 1;
|
||||||
|
D2PlaySound(4,0,0,0,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isOnNextRunesBtn(msg->x,msg->y) && selectedPage == (lastPage + extraHiddenPage))
|
||||||
|
{
|
||||||
|
log_msg("push down left button next runes\n");
|
||||||
|
isDownBtn.nextRunes = 1;
|
||||||
|
D2PlaySound(4,0,0,0,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD STDCALL statsLeftUp(sWinMessage* msg)
|
||||||
|
{
|
||||||
|
if (isOnCloseBtn(msg->x,msg->y) && selectedPage != 0)
|
||||||
|
{
|
||||||
|
log_msg("push up left button close\n");
|
||||||
|
if (isDownBtn.close)
|
||||||
|
D2TogglePage(2,1,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isOnPreviousPageBtn(msg->x,msg->y))
|
||||||
|
{
|
||||||
|
log_msg("push up left button previous page\n");
|
||||||
|
if (isDownBtn.previousPage)
|
||||||
|
GoStatPage(selectedPage-1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isOnNextPageBtn(msg->x,msg->y))
|
||||||
|
{
|
||||||
|
log_msg("push up left button next page\n");
|
||||||
|
if (isDownBtn.nextPage)
|
||||||
|
GoStatPage(selectedPage+1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isOnPrevRunesBtn(msg->x,msg->y) && selectedPage == (lastPage + extraHiddenPage))
|
||||||
|
{
|
||||||
|
log_msg("push up left button prev runes\n");
|
||||||
|
if (isDownBtn.prevRunes && curRunesPage)
|
||||||
|
curRunesPage--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isOnNextRunesBtn(msg->x,msg->y) && selectedPage == (lastPage + extraHiddenPage))
|
||||||
|
{
|
||||||
|
log_msg("push up left button next runes\n");
|
||||||
|
if (isDownBtn.nextRunes && (curRunesPage < maxRunesPage))
|
||||||
|
curRunesPage++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FCT_ASM ( caller_DontPrintBorder_114 )
|
FCT_ASM ( caller_DontPrintBorder_114 )
|
||||||
@ -474,6 +597,7 @@ void Install_NewInterfaces()
|
|||||||
//00498636 |. 6A 48 PUSH 48
|
//00498636 |. 6A 48 PUSH 48
|
||||||
//00498638 |. 8D45 B8 LEA EAX,DWORD PTR SS:[EBP-48]
|
//00498638 |. 8D45 B8 LEA EAX,DWORD PTR SS:[EBP-48]
|
||||||
|
|
||||||
|
/* Conflicts with D2ExpRes
|
||||||
// Manage mouse down (Play sound)
|
// Manage mouse down (Play sound)
|
||||||
mem_seek R8(D2Client, 2A9DC, 2A9CC, 312A5, 82736, 891B6, 6B116, BCD36, BF4D6, A7731);
|
mem_seek R8(D2Client, 2A9DC, 2A9CC, 312A5, 82736, 891B6, 6B116, BCD36, BF4D6, A7731);
|
||||||
memt_byte( 0x8D, 0xE8 ); // CALL
|
memt_byte( 0x8D, 0xE8 ); // CALL
|
||||||
@ -486,6 +610,7 @@ void Install_NewInterfaces()
|
|||||||
//6FB6CD36 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
//6FB6CD36 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
||||||
//6FB6F4D6 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
//6FB6F4D6 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
||||||
//004A7731 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
//004A7731 . 8D88 80000000 LEA ECX,DWORD PTR DS:[EAX+80]
|
||||||
|
*/
|
||||||
|
|
||||||
// Manage mouse up
|
// Manage mouse up
|
||||||
mem_seek R8(D2Client, 2ABBB, 2ABAB, 3148D, 836D9, 8A159, 6C0B9, BDCB9, C0459, A78DA);
|
mem_seek R8(D2Client, 2ABBB, 2ABAB, 3148D, 836D9, 8A159, 6C0B9, BDCB9, C0459, A78DA);
|
||||||
|
@ -58,6 +58,7 @@ const char* S_dllFilenames2 = "DllToLoad2";
|
|||||||
const char* S_active_Commands = "ActiveCommands";
|
const char* S_active_Commands = "ActiveCommands";
|
||||||
const char* S_active_CheckMemory = "ActiveCheckMemory";
|
const char* S_active_CheckMemory = "ActiveCheckMemory";
|
||||||
const char* S_active_othersFeatures = "ActiveAllOthersFeatures";
|
const char* S_active_othersFeatures = "ActiveAllOthersFeatures";
|
||||||
|
const char* S_saveFileStackSize = "SaveFileStackSize";
|
||||||
|
|
||||||
const char* S_WINDOWED = "WINDOWED";
|
const char* S_WINDOWED = "WINDOWED";
|
||||||
const char* S_ActiveWindowed = "ActiveWindowed";
|
const char* S_ActiveWindowed = "ActiveWindowed";
|
||||||
@ -214,6 +215,19 @@ const char* S_INTERFACE = "INTERFACE";
|
|||||||
const char* S_active_newInterfaces = "ActiveNewStatsInterface";
|
const char* S_active_newInterfaces = "ActiveNewStatsInterface";
|
||||||
const char* S_selectMainPageOnOpenning = "SelectMainPageOnOpenning";
|
const char* S_selectMainPageOnOpenning = "SelectMainPageOnOpenning";
|
||||||
const char* S_printBackgroundOnMainPage = "PrintButtonsBackgroundOnMainStatsPage";
|
const char* S_printBackgroundOnMainPage = "PrintButtonsBackgroundOnMainStatsPage";
|
||||||
|
const char* S_posXNextPageBtn = "PosXNextPageBtn";
|
||||||
|
const char* S_posYNextPageBtn = "PosYNextPageBtn";
|
||||||
|
const char* S_posXPrevPageBtn = "PosXPrevPageBtn";
|
||||||
|
const char* S_posYPrevPageBtn = "PosYPrevPageBtn";
|
||||||
|
const char* S_posXClosePageBtn = "PosXClosePageBtn";
|
||||||
|
const char* S_posYClosePageBtn = "PosYClosePageBtn";
|
||||||
|
const char* S_posXNextRuneBtn = "PosXNextRuneBtn";
|
||||||
|
const char* S_posYNextRuneBtn = "PosYNextRuneBtn";
|
||||||
|
const char* S_posXPrevRuneBtn = "PosXPrevRuneBtn";
|
||||||
|
const char* S_posYPrevRuneBtn = "PosYPrevRuneBtn";
|
||||||
|
const char* S_posXRunesList = "PosXRunesList";
|
||||||
|
const char* S_posYRunesList = "PosYRunesList";
|
||||||
|
const char* S_runesPerPage = "RunesPerPage";
|
||||||
|
|
||||||
const char* S_EXTRA = "EXTRA";
|
const char* S_EXTRA = "EXTRA";
|
||||||
const char* S_active_RunLODs = "ActiveLaunchAnyNumberOfLOD";
|
const char* S_active_RunLODs = "ActiveLaunchAnyNumberOfLOD";
|
||||||
@ -316,6 +330,10 @@ void init_General(INIFile* iniFile, INIFile* iniFixedFile, INIFile* iniDefaultFi
|
|||||||
active_othersFeatures = atoi(buffer) != 0;
|
active_othersFeatures = atoi(buffer) != 0;
|
||||||
log_msg("active_othersFeatures\t\t= %u\n", active_othersFeatures);
|
log_msg("active_othersFeatures\t\t= %u\n", active_othersFeatures);
|
||||||
|
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_GENERAL, S_saveFileStackSize, "8192");
|
||||||
|
saveFileStackSize = atoi(buffer);
|
||||||
|
log_msg("SaveFileStackSize\t\t\t= %u\n", saveFileStackSize);
|
||||||
|
|
||||||
log_msg("\n");
|
log_msg("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1032,6 +1050,52 @@ void init_NewInterfaces(INIFile* iniFile, INIFile* iniFixedFile, INIFile* iniDef
|
|||||||
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_printBackgroundOnMainPage, "1");
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_printBackgroundOnMainPage, "1");
|
||||||
printBackgroundOnMainPage = atoi(buffer) != 0;
|
printBackgroundOnMainPage = atoi(buffer) != 0;
|
||||||
log_msg("printBackgroundOnMainPage\t= %u\n", printBackgroundOnMainPage);
|
log_msg("printBackgroundOnMainPage\t= %u\n", printBackgroundOnMainPage);
|
||||||
|
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXNextPageBtn, "161");
|
||||||
|
posXNextPageBtn = atoi(buffer);
|
||||||
|
log_msg("posXNextPageBtn\t= %d\n", posXNextPageBtn);
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYNextPageBtn, "64");
|
||||||
|
posYNextPageBtn = atoi(buffer);
|
||||||
|
log_msg("posYNextPageBtn\t= %d\n", posYNextPageBtn);
|
||||||
|
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXPrevPageBtn, "119");
|
||||||
|
posXPrevPageBtn = atoi(buffer);
|
||||||
|
log_msg("posXPrevPageBtn\t= %d\n", posXPrevPageBtn);
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYPrevPageBtn, "64");
|
||||||
|
posYPrevPageBtn = atoi(buffer);
|
||||||
|
log_msg("posYPrevPageBtn\t= %d\n", posYPrevPageBtn);
|
||||||
|
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXClosePageBtn, "360");
|
||||||
|
posXClosePageBtn = atoi(buffer);
|
||||||
|
log_msg("posXClosePageBtn\t= %d\n", posXClosePageBtn);
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYClosePageBtn, "64");
|
||||||
|
posYClosePageBtn = atoi(buffer);
|
||||||
|
log_msg("posYClosePageBtn\t= %d\n", posYClosePageBtn);
|
||||||
|
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXNextRuneBtn, "302");
|
||||||
|
posXNextRuneBtn = atoi(buffer);
|
||||||
|
log_msg("posXNextRuneBtn\t= %d\n", posXNextRuneBtn);
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYNextRuneBtn, "64");
|
||||||
|
posYNextRuneBtn = atoi(buffer);
|
||||||
|
log_msg("posYNextRuneBtn\t= %d\n", posYNextRuneBtn);
|
||||||
|
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXPrevRuneBtn, "260");
|
||||||
|
posXPrevRuneBtn = atoi(buffer);
|
||||||
|
log_msg("posXPrevRuneBtn\t= %d\n", posXPrevRuneBtn);
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYPrevRuneBtn, "64");
|
||||||
|
posYPrevRuneBtn = atoi(buffer);
|
||||||
|
log_msg("posYPrevRuneBtn\t= %d\n", posYPrevRuneBtn);
|
||||||
|
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posXRunesList, "50");
|
||||||
|
posXRunesList = atoi(buffer);
|
||||||
|
log_msg("posXRunesList\t= %d\n", posXRunesList);
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_posYRunesList, "45");
|
||||||
|
posYRunesList = atoi(buffer);
|
||||||
|
log_msg("posYRunesList\t= %d\n", posYRunesList);
|
||||||
|
|
||||||
|
GET_PRIVATE_PROFILE_STRING(S_INTERFACE, S_runesPerPage, "30");
|
||||||
|
runesPerPage = atoi(buffer);
|
||||||
|
log_msg("runesPerPage\t= %d\n", runesPerPage);
|
||||||
}
|
}
|
||||||
log_msg("\n");
|
log_msg("\n");
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ Unit* FASTCALL updateItem(Game* ptGame, DWORD type, DWORD itemNum, Unit* ptChar)
|
|||||||
if (ptGame->isLODGame && (D2ItemGetPage(ptItem) == 4))
|
if (ptGame->isLODGame && (D2ItemGetPage(ptItem) == 4))
|
||||||
{
|
{
|
||||||
Stash* ptStash = getStashFromItem(ptChar, ptItem);
|
Stash* ptStash = getStashFromItem(ptChar, ptItem);
|
||||||
|
//log_msg("- updateItem PCPY->currentStash->id : %d // ptStash->id : %d\n", PCPY->currentStash?PCPY->currentStash->id:-1, ptStash?ptStash->id:-1);
|
||||||
if (!ptStash) return NULL;
|
if (!ptStash) return NULL;
|
||||||
selectStash(ptChar, ptStash, ptStash->id == 0);
|
selectStash(ptChar, ptStash, ptStash->id == 0);
|
||||||
}
|
}
|
||||||
|
BIN
PlugY/PlugY.aps
Normal file
BIN
PlugY/PlugY.aps
Normal file
Binary file not shown.
BIN
PlugY/PlugY.rc
BIN
PlugY/PlugY.rc
Binary file not shown.
@ -1,7 +1,9 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual C++ Express 2008
|
# Visual Studio Version 17
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PlugY", "PlugY.vcproj", "{EB63DF4E-A019-4522-A140-9E8C7350B331}"
|
VisualStudioVersion = 17.2.32505.173
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PlugY", "PlugY.vcxproj", "{EB63DF4E-A019-4522-A140-9E8C7350B331}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -17,4 +19,7 @@ Global
|
|||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {83A1632A-5376-46CE-89D9-F2D4E74FFE31}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
BIN
PlugY/PlugY.suo
BIN
PlugY/PlugY.suo
Binary file not shown.
@ -18,6 +18,7 @@ extern bool active_sharedStash;
|
|||||||
extern bool active_sharedGold;
|
extern bool active_sharedGold;
|
||||||
extern bool separateHardSoftStash;
|
extern bool separateHardSoftStash;
|
||||||
extern char* sharedStashFilename;
|
extern char* sharedStashFilename;
|
||||||
|
extern DWORD saveFileStackSize;
|
||||||
|
|
||||||
extern bool displaySharedSetItemNameInGreen;
|
extern bool displaySharedSetItemNameInGreen;
|
||||||
extern int posXPreviousBtn;
|
extern int posXPreviousBtn;
|
||||||
|
@ -9,20 +9,94 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define MILIEU(X,L,N) (X + ((N<L)? (L-N)/2 : 0))
|
#define MILIEU(X,L,N) (X + ((N<L)? (L-N)/2 : 0))
|
||||||
#define isOnStatsPage(x,y) ((x<400) && (y<553))
|
#define isOnStatsPage(x,y) (x<RX(512))
|
||||||
|
|
||||||
extern DWORD bDontPrintBorder;
|
extern DWORD bDontPrintBorder;
|
||||||
|
extern int selectedPage;
|
||||||
extern int extraHiddenPage;
|
extern int extraHiddenPage;
|
||||||
|
extern int curRunesPage;
|
||||||
|
extern int maxRunesPage;
|
||||||
|
|
||||||
void GoNextStatPage();
|
void GoNextStatPage();
|
||||||
void GoPreviousStatPage();
|
void GoPreviousStatPage();
|
||||||
void GoStatPage(int page);
|
void GoStatPage(int page);
|
||||||
int GetCurrentPage();
|
int GetCurrentPage();
|
||||||
|
|
||||||
|
struct BtnState
|
||||||
|
{
|
||||||
|
union{
|
||||||
|
DWORD all;
|
||||||
|
struct{
|
||||||
|
DWORD AssSTR:1;
|
||||||
|
DWORD AssDEX:1;
|
||||||
|
DWORD AssVIT:1;
|
||||||
|
DWORD AssENE:1;
|
||||||
|
DWORD UnaSTR:1;
|
||||||
|
DWORD UnaDEX:1;
|
||||||
|
DWORD UnaVIT:1;
|
||||||
|
DWORD UnaENE:1;
|
||||||
|
DWORD close:1;
|
||||||
|
DWORD previousPage:1;
|
||||||
|
DWORD nextPage:1;
|
||||||
|
DWORD prevRunes:1;
|
||||||
|
DWORD nextRunes:1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
extern BtnState isDownBtn;
|
||||||
|
|
||||||
extern bool active_newInterfaces;
|
extern bool active_newInterfaces;
|
||||||
extern bool selectMainPageOnOpenning;
|
extern bool selectMainPageOnOpenning;
|
||||||
extern bool printBackgroundOnMainPage;
|
extern bool printBackgroundOnMainPage;
|
||||||
|
|
||||||
|
extern int posXNextPageBtn;
|
||||||
|
extern int posYNextPageBtn;
|
||||||
|
extern int posXPrevPageBtn;
|
||||||
|
extern int posYPrevPageBtn;
|
||||||
|
extern int posXClosePageBtn;
|
||||||
|
extern int posYClosePageBtn;
|
||||||
|
extern int posXNextRuneBtn;
|
||||||
|
extern int posYNextRuneBtn;
|
||||||
|
extern int posXPrevRuneBtn;
|
||||||
|
extern int posYPrevRuneBtn;
|
||||||
|
extern int posXRunesList;
|
||||||
|
extern int posYRunesList;
|
||||||
|
extern int runesPerPage;
|
||||||
|
|
||||||
|
DWORD getXNextPageBtn();
|
||||||
|
DWORD getYNextPageBtn();
|
||||||
|
DWORD getXPreviousPageBtn();
|
||||||
|
DWORD getYPreviousPageBtn();
|
||||||
|
DWORD getXCloseBtn();
|
||||||
|
DWORD getYCloseBtn();
|
||||||
|
DWORD getXNextRunesBtn();
|
||||||
|
DWORD getYNextRunesBtn();
|
||||||
|
DWORD getXPrevRunesBtn();
|
||||||
|
DWORD getYPrevRunesBtn();
|
||||||
|
|
||||||
|
#define getLCloseBtn() 32
|
||||||
|
#define getHCloseBtn() 32
|
||||||
|
#define isOnCloseBtn(x,y) isOnRect(x, y, getXCloseBtn(), getYCloseBtn(), getLCloseBtn(), getHCloseBtn())
|
||||||
|
|
||||||
|
#define getLPreviousPageBtn() 32
|
||||||
|
#define getHPreviousPageBtn() 32
|
||||||
|
#define isOnPreviousPageBtn(x,y) isOnRect(x, y, getXPreviousPageBtn(), getYPreviousPageBtn(), getLPreviousPageBtn(), getHPreviousPageBtn())
|
||||||
|
|
||||||
|
#define getLNextPageBtn() 32
|
||||||
|
#define getHNextPageBtn() 32
|
||||||
|
#define isOnNextPageBtn(x,y) isOnRect(x, y, getXNextPageBtn(), getYNextPageBtn(), getLNextPageBtn(), getHNextPageBtn())
|
||||||
|
|
||||||
|
#define getLPrevRunesBtn() 32
|
||||||
|
#define getHPrevRunesBtn() 32
|
||||||
|
#define isOnPrevRunesBtn(x,y) isOnRect(x, y, getXPrevRunesBtn(), getYPrevRunesBtn(), getLPrevRunesBtn(), getHPrevRunesBtn())
|
||||||
|
|
||||||
|
#define getLNextRunesBtn() 32
|
||||||
|
#define getHNextRunesBtn() 32
|
||||||
|
#define isOnNextRunesBtn(x,y) isOnRect(x, y, getXNextRunesBtn(), getYNextRunesBtn(), getLNextRunesBtn(), getHNextRunesBtn())
|
||||||
|
|
||||||
|
DWORD STDCALL statsLeftDown(sWinMessage* msg);
|
||||||
|
DWORD STDCALL statsLeftUp(sWinMessage* msg);
|
||||||
|
|
||||||
void Install_NewInterfaces();
|
void Install_NewInterfaces();
|
||||||
|
|
||||||
/*================================= END OF FILE =================================*/
|
/*================================= END OF FILE =================================*/
|
@ -6,7 +6,7 @@
|
|||||||
=================================================================*/
|
=================================================================*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PLUGY_VERSION "14.01"
|
#define PLUGY_VERSION "14.03 HD"
|
||||||
|
|
||||||
enum TargetMod
|
enum TargetMod
|
||||||
{
|
{
|
||||||
|
@ -47,10 +47,10 @@ BEGIN
|
|||||||
VALUE "CompanyName", "Yohann Nicolas"
|
VALUE "CompanyName", "Yohann Nicolas"
|
||||||
VALUE "FileDescription", "PlugY patcher"
|
VALUE "FileDescription", "PlugY patcher"
|
||||||
VALUE "FileVersion", "1.0.6.0"
|
VALUE "FileVersion", "1.0.6.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2017"
|
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||||
VALUE "OriginalFilename", "PlugYInstall.exe"
|
VALUE "OriginalFilename", "PlugYInstall.exe"
|
||||||
VALUE "ProductName", "PlugY, The Survival Kit"
|
VALUE "ProductName", "PlugY, The Survival Kit"
|
||||||
VALUE "ProductVersion", "14.01"
|
VALUE "ProductVersion", "14.03"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
Binary file not shown.
@ -5,7 +5,7 @@
|
|||||||
; ;
|
; ;
|
||||||
; by Yohann Nicolas ;
|
; by Yohann Nicolas ;
|
||||||
; ;
|
; ;
|
||||||
; version 14.01 ;
|
; version 14.03 ;
|
||||||
; ;
|
; ;
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ Unicode True
|
|||||||
|
|
||||||
!include "MUI2.nsh"
|
!include "MUI2.nsh"
|
||||||
|
|
||||||
!define VERSION "v14.01"
|
!define VERSION "v14.03"
|
||||||
!define D2FILES "."
|
!define D2FILES "."
|
||||||
!define NAME "PlugY, The Survival Kit"
|
!define NAME "PlugY, The Survival Kit"
|
||||||
!define MOD_DIR "Mod PlugY"
|
!define MOD_DIR "Mod PlugY"
|
||||||
|
Binary file not shown.
@ -6,7 +6,7 @@
|
|||||||
; ;
|
; ;
|
||||||
; by Yohann Nicolas ;
|
; by Yohann Nicolas ;
|
||||||
; ;
|
; ;
|
||||||
; version 14.01 ;
|
; version 14.03 ;
|
||||||
; ;
|
; ;
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
; ;
|
; ;
|
||||||
; by Yohann Nicolas ;
|
; by Yohann Nicolas ;
|
||||||
; ;
|
; ;
|
||||||
; version 14.01 ;
|
; version 14.03 ;
|
||||||
; ;
|
; ;
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
; ;
|
; ;
|
||||||
; von Yohann Nicolas ;
|
; von Yohann Nicolas ;
|
||||||
; ;
|
; ;
|
||||||
; version 14.01 ;
|
; version 14.03 ;
|
||||||
; ;
|
; ;
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
||||||
|
|
||||||
@ -75,8 +75,15 @@ Jedes Feature kann via PlugY.ini an/ausgeschaltet werden (siehe "Kommentare aus
|
|||||||
/listcube: (Beta) Erstellt eine "cube.txt" Datei im Savegame-Verzeichnis mit allen Würfelrezepten.
|
/listcube: (Beta) Erstellt eine "cube.txt" Datei im Savegame-Verzeichnis mit allen Würfelrezepten.
|
||||||
/renamechar newname: (Beta) Speichert und benennt den Char um.
|
/renamechar newname: (Beta) Speichert und benennt den Char um.
|
||||||
|
|
||||||
|
v14.03 Änderungen :
|
||||||
|
- Behebung eines Fehlers bei der Anzeige von Gegenständen, wenn nur eine Stash-Seite gefüllt ist.
|
||||||
|
- Koreanische Übersetzung hinzugefügt.
|
||||||
|
|
||||||
|
v14.02 Änderungen :
|
||||||
|
- Behebt Fehler, durch den mehrere identische, einzigartige Charms im Inventar gespeichert werden können.
|
||||||
|
|
||||||
v14.01 Änderungen :
|
v14.01 Änderungen :
|
||||||
- Fix stash items lost on loading a character for the first time.
|
- Fehler behoben, der das Löschen von Truhen-Items hervorgerufen hat, wenn der Character zum ersten Mal geladen wurde.
|
||||||
|
|
||||||
v14.00 Änderungen :
|
v14.00 Änderungen :
|
||||||
- Kompatibilität mit 1.14d (Vielen Dank an Haxifix)
|
- Kompatibilität mit 1.14d (Vielen Dank an Haxifix)
|
||||||
@ -960,5 +967,6 @@ Zur Korrektur der deutschen Übersetzung bitte eine eMail an ChaosEnergy@planetd
|
|||||||
* Polnisch: Serdel
|
* Polnisch: Serdel
|
||||||
* Russisch: L'Autour
|
* Russisch: L'Autour
|
||||||
* Chinesisch: Nagahaku
|
* Chinesisch: Nagahaku
|
||||||
|
* Koreanisch: Woodlac
|
||||||
|
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
@ -4,7 +4,7 @@
|
|||||||
; ;
|
; ;
|
||||||
; par Yohann Nicolas ;
|
; par Yohann Nicolas ;
|
||||||
; ;
|
; ;
|
||||||
; version 14.01 ;
|
; version 14.03 ;
|
||||||
; ;
|
; ;
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
||||||
|
|
||||||
@ -75,11 +75,18 @@ Toutes ces fonctions peuvent être activé/désactivé via PlugY.ini (voir "COMM
|
|||||||
/listcube : (beta) Crée un fichier "cube.txt" dans le répertoire de sauvegarde contenant toutes les formules du cube.
|
/listcube : (beta) Crée un fichier "cube.txt" dans le répertoire de sauvegarde contenant toutes les formules du cube.
|
||||||
/renamechar newname : (beta) Renomme la personnage et le sauvegarde.
|
/renamechar newname : (beta) Renomme la personnage et le sauvegarde.
|
||||||
|
|
||||||
|
Changements apportés par la v14.03 :
|
||||||
|
- Corrige un bug d'affichage d'objects quand une seule page du coffre est remplit.
|
||||||
|
- Ajout de la traduction en coréen.
|
||||||
|
|
||||||
|
Changements apportés par la v14.02 :
|
||||||
|
- Corrige un bug permettant d'avoir plusieurs charmes uniques identiques dans l'inventaire.
|
||||||
|
|
||||||
Changements apportés par la v14.01 :
|
Changements apportés par la v14.01 :
|
||||||
- Corrige la perte des objets du coffre lors du chargement d'un personnage pour la première fois.
|
- Corrige la perte des objets du coffre lors du chargement d'un personnage pour la première fois.
|
||||||
|
|
||||||
Changements apportés par la v14.00:
|
Changements apportés par la v14.00:
|
||||||
- Ajout de la compatibilité avec la version 1.13d de LOD. (merci à Haxifix)
|
- Ajout de la compatibilité avec la version 1.14d de LOD. (merci à Haxifix)
|
||||||
- Crée un backup des fichiers de sauvegardes avant de sauvegarder.
|
- Crée un backup des fichiers de sauvegardes avant de sauvegarder.
|
||||||
- Empéche la fermeture du portail de Nihlathak.
|
- Empéche la fermeture du portail de Nihlathak.
|
||||||
- Déplace Deckar Cain à coté du portail d'Harrogath.
|
- Déplace Deckar Cain à coté du portail d'Harrogath.
|
||||||
@ -835,5 +842,6 @@ Déplace Deckar Cain à coté du portail d'Harrogath.
|
|||||||
* Russe : L'Autour
|
* Russe : L'Autour
|
||||||
* Chinois (Traditionnel): Nagahaku
|
* Chinois (Traditionnel): Nagahaku
|
||||||
* Japanase : CaiMiao
|
* Japanase : CaiMiao
|
||||||
|
* Coréen : Woodlac
|
||||||
|
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
@ -4,7 +4,7 @@
|
|||||||
; ;
|
; ;
|
||||||
; by Yohann Nicolas ;
|
; by Yohann Nicolas ;
|
||||||
; ;
|
; ;
|
||||||
; version 14.01 ;
|
; version 14.03 ;
|
||||||
; ;
|
; ;
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
||||||
|
|
||||||
@ -75,6 +75,13 @@ Each features can be turn on/off via PlugY.ini (see "COMMENTS ON THE CONFIGURATI
|
|||||||
/listcube : (beta) Create a "cube.txt" file in save directory containing all cube's receipts.
|
/listcube : (beta) Create a "cube.txt" file in save directory containing all cube's receipts.
|
||||||
/renamechar newname : (beta) Rename your character and save it.
|
/renamechar newname : (beta) Rename your character and save it.
|
||||||
|
|
||||||
|
v14.03 changes :
|
||||||
|
- Fix a items diplay bug when only one stash page is filled.
|
||||||
|
- Add Korean Translation.
|
||||||
|
|
||||||
|
v14.02 changes :
|
||||||
|
- Fix a bug allowing multiple identical unique charms to be in inventory.
|
||||||
|
|
||||||
v14.01 changes :
|
v14.01 changes :
|
||||||
- Fix stash items lost on loading a character for the first time.
|
- Fix stash items lost on loading a character for the first time.
|
||||||
|
|
||||||
@ -921,5 +928,6 @@ Move Cain near Harrogath waypoint.
|
|||||||
* Russian: L'Autour
|
* Russian: L'Autour
|
||||||
* Chinese (Traditional): Nagahaku
|
* Chinese (Traditional): Nagahaku
|
||||||
* Japanase : CaiMiao
|
* Japanase : CaiMiao
|
||||||
|
* Korean : Woodlac
|
||||||
|
|
||||||
;--------------------------------------------------------------------------------------;
|
;--------------------------------------------------------------------------------------;
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user