diff --git a/features/MapReveal.cpp b/features/MapReveal.cpp index 2050a34..4d42bb2 100644 --- a/features/MapReveal.cpp +++ b/features/MapReveal.cpp @@ -45,11 +45,14 @@ void __stdcall D2GFX_DrawSprite6_override(D2::Types::DC6Context *pDC6Context, in if (cellno < 0) { if (Settings["revealLevel"]) { DWORD width = 0, height = 0, fontNum = 6; - wchar_t* levelNameUnicode = D2::GetLevelText(-cellno)->wName; - D2::SetFont(fontNum); - height = D2::GetTextSize(levelNameUnicode, &width, &fontNum); - int offsetx = 8 - ((int)width / 2), offsety = -16; - D2::DrawGameText(levelNameUnicode, x + offsetx, y + offsety, 0, false); + auto test = D2::GetLevelText(-cellno); + if (test != nullptr) { + wchar_t *levelNameUnicode = test->wName; + D2::SetFont(fontNum); + height = D2::GetTextSize(levelNameUnicode, &width, &fontNum); + int offsetx = 8 - ((int) width / 2), offsety = -16; + D2::DrawGameText(levelNameUnicode, x + offsetx, y + offsety, 0, false); + } } } else { diff --git a/features/WorldEvent.cpp b/features/WorldEvent.cpp new file mode 100644 index 0000000..19d8a16 --- /dev/null +++ b/features/WorldEvent.cpp @@ -0,0 +1,137 @@ +// +// Created by jaenster on 15/11/2020. +// + +#include "headers/feature.h" +#include "headers/common.h" +#include "headers/hook.h" +#include "headers/remote.h" +#include "iostream" + +namespace WorldEvent { + + bool isSpawned = false; + bool shouldSpawn = false; + REMOTEFUNC( + D2::Types::UnitAny * __stdcall, + SERVER_SpawnMonsterInternal, + (D2::Types::Room1 * pRoom, DWORD * unknown, int nX, int nY, int nGUID, BOOL bSetOrNotUnknown), + 0x5a09e0 + ) + + [[maybe_unused]] int __stdcall myTest(int classid) { + if (!isSpawned && shouldSpawn) { + isSpawned = true; + return 333; + } + return classid; + } + + __declspec(naked) D2::Types::UnitAny * intercept2() { + static ASMPTR continueIf = 0x5a4a5d; + static ASMPTR skipIf = 0x5a4e65; + __asm { + + // original code + MOV EDI,EAX + CMP EBX, 333 + JE itIsDiablo + + // original code + OriginalCode: + CMP EDI, 0 // if (edi == 0) { + JZ skip + + JMP continueIf // (.. in if) + + itIsDiablo: + MOV EDI, 0 + JMP OriginalCode + + skip: + JMP skipIf // else + + } + } + + __declspec(naked) D2::Types::UnitAny * intercept() { + __asm { + // backup + push eax + + // first argument + push ebx + call myTest + mov ebx, eax + + // restore + pop eax + jmp SERVER_SpawnMonsterInternal + //jmp back + } + } + + REMOTEFUNC(void __fastcall, NET_D2GS_SERVER_Send_0x5A_EventMessages,(int param_1,char *param_2),0x53c850) + REMOTEFUNC(int __fastcall, PLAYER_GetClientFromUnitData,(D2::Types::UnitAny *pUnit),0x5531c0); + + + REMOTEFUNC(D2::Types::UnitAny * __fastcall, + SERVER_FindUnitFromTable, + (D2::Types::IncompleteGameData *pGame,int eD2UnitType,DWORD dwFindGUID), + 0x552f60 + ) + + REMOTEFUNC(void __fastcall, D2GS_Client_RawPacketRecv,(char *pBytes,size_t nSize),0x45f7b0) + D2::Types::UnitAny* __fastcall checkIfSoj(D2::Types::IncompleteGameData *pGame,int eD2UnitType,DWORD dwFindGUID) { + D2::Types::UnitAny* unit = SERVER_FindUnitFromTable(pGame, eD2UnitType, dwFindGUID); + if (unit->dwTxtFileNo == 522 && unit->pItemData->dwQuality == 7 && unit->pItemData->dwFileIndex == 122) { + int count = Settings["sojCount"] += 1; + { + char *aPacket = new char[40]; + aPacket[0] = 0x5A; // right hand skill + *(BYTE *) &aPacket[1] = 0x11; + *(BYTE *) &aPacket[2] = 4; + *(DWORD *) &aPacket[3] = count; + + D2GS_Client_RawPacketRecv(aPacket, 40); + } + + int random = pGame->seed % 100; + + if (!shouldSpawn && count > random) { + shouldSpawn = true; + { + char *aPacket = new char[40]; + aPacket[0] = 0x5A; // right hand skill + *(BYTE *) &aPacket[1] = 0x12; + *(BYTE *) &aPacket[2] = 4; + D2GS_Client_RawPacketRecv(aPacket, 40); + } + } + + SaveSettings(); + } + return unit; // 522 + } + + class : public Feature { + public: + void init() { +// MemoryPatch(0x5a4a4e) << CALL(SERVER_SpawnMonsterInternalOverride); + + // Patching to spawn dia clone + MemoryPatch(0x5a4a4e) << CALL(intercept); + MemoryPatch(0x5a4a53) << CALL(intercept2) << NOP_TO(0x5a4a5d); + + MemoryPatch(0x579566) << CALL(checkIfSoj); + } + + void gameLoop() { + + } + void oogLoop() { + isSpawned = false; + } + } feature; + +} diff --git a/headers/D2Structs.h b/headers/D2Structs.h index a4503b1..fb63e3b 100644 --- a/headers/D2Structs.h +++ b/headers/D2Structs.h @@ -1345,6 +1345,49 @@ namespace D2 { FIELDTYPE_DATA_BIT = 26, }; + struct UIFlagStrc { + BOOL None; + BOOL Inventory; + BOOL CharStat; + BOOL QuickSkill; + BOOL Skill; + BOOL ChatInput; + BOOL EquipmentPane; + BOOL NewSkill; + BOOL NpcMenu; + BOOL EscMenu; + BOOL Automap; + BOOL ConfigControls; + BOOL NpcShop; + BOOL AltShowItems; + BOOL Cash; + BOOL Quest; + BOOL PartyPane; + BOOL QuestLogButton; + BOOL StatusArea; + BOOL PartyIcons; + BOOL WaypointMenu; + BOOL MiniPanel; + BOOL PartyMenu; + BOOL TradePrompt; + BOOL MessageLog; + BOOL StashMenu; + BOOL CubeMenu; + BOOL Unknown0x1B; + BOOL Unknown0x1C; + BOOL Unknown0x1D; + BOOL Unknown0x1E; + BOOL FullBelt; + BOOL Unknown0x20; + BOOL HelpMenu; + BOOL HelpScreenRedButton; + BOOL HireIcons; + BOOL MercMenu; + BOOL UnusedScroll; + }; + + + struct BINField { char* fieldName; BINFieldType type; diff --git a/headers/remote.h b/headers/remote.h index 5dd429e..bddf9a3 100644 --- a/headers/remote.h +++ b/headers/remote.h @@ -4,6 +4,7 @@ #include "D2Structs.h" typedef unsigned long ASMPTR; +typedef unsigned int uint; #ifdef DEFINE_REMOTE_REFERENCES @@ -33,6 +34,7 @@ namespace D2 { GLOBALREF(HINSTANCE, hInst, 0x7C8CA8); GLOBALREF(HWND, hWnd, 0x7C8CBC); GLOBALREF(int, CurrentGameType, 0x7A0610); + GLOBALREF(Types::UIFlagStrc, GFX_bShowUIFlag, 0x7a27c0); // For referencing D2's functions use this specialized macro instead GLOBALFUNC(DWORD __fastcall, SetFont, (DWORD dwFileNo), 0x502EF0); @@ -66,6 +68,9 @@ namespace D2 { GLOBALFUNC(void __fastcall, FindSpawnablePosition, (D2::Types::Room1* pDrlgRoom, POINT* pos, DWORD param_1_00, DWORD param_2_00, D2::Types::Room1** pRoomsNear, DWORD param_6, int param_7), 0x545340); GLOBALFUNC(void __stdcall, UnitLocation, (D2::Types::UnitAny* pUnit, POINT* pPoint), 0x620870); GLOBALFUNC(DWORD __stdcall, GetAct, (int levelId), 0x6427f0); + + GLOBALFUNC(Types::UnitAny* __fastcall, UNIT_CreateUnit, (BYTE type ,int nClassId,int x,int y,Types::IncompleteGameData *pGame,Types::Room1 *pDrlgRoom,BYTE unknown), 0x555230); + GLOBALFUNC(Types::UnitAny* * __fastcall, SERVER_CreateUnit,(Types::IncompleteGameData *pGame,Types::Room1 *pRoom,BYTE eD2UnitType,int nMonStatsId, int nPositionX,int nPositionY,BOOL bUseMonStats),0x5557d0) } #pragma warning( default : 4229 )