diff --git a/.gitignore b/.gitignore index bbc0a27..1a20c6f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,7 @@ currentmap.png /src/mapconfig.ini /src/GameSessionLog.csv /src/d2r-map3.ahk -/src/*.wav \ No newline at end of file +/src/*.wav +/src/game/ +/src/d2-mapgenerator.exe +/src/mapgen/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ecbbef..2a5c6f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. +## [3.0.1] - 2022-09-23 - Fix after latest patch + +- Seed decryption has been reimplemented +- Made some fixes to item stats + ## [3.0.0] - 2022-09-08 - Major rework - Maps no longer have to load when going from one walkable area to another! diff --git a/src/SeedGenerator.dll b/src/SeedGenerator.dll new file mode 100644 index 0000000..7095687 Binary files /dev/null and b/src/SeedGenerator.dll differ diff --git a/src/d2r-map.ahk b/src/d2r-map.ahk index b59a554..9bab119 100644 --- a/src/d2r-map.ahk +++ b/src/d2r-map.ahk @@ -71,7 +71,7 @@ Menu, Tray, Add, Reload, Reload Menu, Tray, Add Menu, Tray, Add, Exit, ExitMH -global version := "3.0.0" +global version := "3.0.1" WriteLog("*******************************************************************") WriteLog("* Map overlay started https://github.com/joffreybesos/d2r-mapview *") diff --git a/src/init/readSettings.ahk b/src/init/readSettings.ahk index b8dc54d..a73d7bc 100644 --- a/src/init/readSettings.ahk +++ b/src/init/readSettings.ahk @@ -7,6 +7,7 @@ readSettings(settingsFile, ByRef settings) { FileInstall, exocetblizzardot-medium.otf, exocetblizzardot-medium.otf , 1 FileInstall, formal436bt-regular.otf, formal436bt-regular.otf , 1 FileInstall, settings.ini, settings.ini, 0 + FileInstall, SeedGenerator.dll, SeedGenerator.dll, 1 ; these are the default values settings := [] diff --git a/src/memory/readGameMemory.ahk b/src/memory/readGameMemory.ahk index 0a94383..1c57728 100644 --- a/src/memory/readGameMemory.ahk +++ b/src/memory/readGameMemory.ahk @@ -8,9 +8,9 @@ #Include %A_ScriptDir%\memory\scanForPlayer.ahk -; global lastdwInitSeedHash1 -; global lastdwInitSeedHash2 -; global lastdwEndSeedHash1 +global lastdwInitSeedHash1 +global lastdwInitSeedHash2 +global lastdwEndSeedHash1 global xorkey global playerLevel global experience @@ -38,16 +38,25 @@ readGameMemory(ByRef d2rprocess, ByRef settings, ByRef gameMemoryData) { ; get playername , playerNameAddress := d2rprocess.read(playerUnit + 0x10, "Int64") , playerName := d2rprocess.readString(playerNameAddress, length := 0) - ; get the map seed , actAddress := d2rprocess.read(playerUnit + 0x20, "Int64") , actMiscAddress := d2rprocess.read(actAddress + 0x78, "Int64") ;0x0000023a64ed4780 ;2449824630656 - , mapSeed := d2rprocess.read(actMiscAddress + 0x840, "UInt") + + dwInitSeedHash1 := d2rprocess.read(actMiscAddress + 0x840, "UInt") + dwInitSeedHash2 := d2rprocess.read(actMiscAddress + 0x844, "UInt") + dwEndSeedHash1 := d2rprocess.read(actMiscAddress + 0x868, "UInt") + + if (dwInitSeedHash1 != lastdwInitSeedHash1 or dwInitSeedHash2 != lastdwInitSeedHash2 or mapSeed == 0) { + mapSeed := calculateMapSeed(dwInitSeedHash1, dwInitSeedHash2, dwEndSeedHash1) + lastdwInitSeedHash1 := dwInitSeedHash1 + lastdwInitSeedHash2 := dwInitSeedHash2 + } + ;mapSeed := d2rprocess.read(actMiscAddress + 0x840, "UInt") ; get the difficulty - , aActUnk2 := d2rprocess.read(actAddress + 0x78, "Int64") + aActUnk2 := d2rprocess.read(actAddress + 0x78, "Int64") , difficulty := d2rprocess.read(aActUnk2 + 0x830, "UShort") if (Mod(ticktock, 6)) { @@ -171,3 +180,11 @@ readGameMemory(ByRef d2rprocess, ByRef settings, ByRef gameMemoryData) { ;OutputDebug, % ElapsedTime "`n" ;ToolTip % "`n`n`n`n" ElapsedTime } + + +calculateMapSeed(InitSeedHash1, InitSeedHash2, EndSeedHash1) { + WriteLog("Calculating new map seed from " InitSeedHash1 " " InitSeedHash2 " " EndSeedHash1) + mapSeed := DllCall("SeedGenerator.dll\GetSeed", "UInt", InitSeedHash1, "UInt", InitSeedHash2, "UInt", EndSeedHash1, "UInt", "0", "UInt") + WriteLog("Found mapSeed " mapSeed) + return mapSeed +} \ No newline at end of file diff --git a/src/memory/readItems.ahk b/src/memory/readItems.ahk index 636cfed..1719289 100644 --- a/src/memory/readItems.ahk +++ b/src/memory/readItems.ahk @@ -34,12 +34,20 @@ ReadItems(ByRef d2rprocess, startingOffset, ByRef items) { , itemx := NumGet(&pPath , 0x10, "UShort") , itemy := NumGet(&pPath , 0x14, "UShort") , pStatsListExPtr := NumGet(&itemStructData , 0x88, "Int64") - d2rprocess.readRaw(pStatsListExPtr, pStatsListEx, 144) + d2rprocess.readRaw(pStatsListExPtr, pStatsListEx, 180) , statPtr := NumGet(&pStatsListEx , 0x30, "Int64") - , statCount := NumGet(&pStatsListEx , 0x38, "Int64") - , statExPtr := NumGet(&pStatsListEx , 0x80, "Int64") - , statExCount := NumGet(&pStatsListEx , 0x88, "Int64") - , item := new GameItem(txtFileNo, itemQuality, uniqueOrSetId) + , statCount := NumGet(&pStatsListEx , 0x38, "UInt") + , statExPtr := NumGet(&pStatsListEx , 0x88, "Int64") + , statExCount := NumGet(&pStatsListEx , 0x90, "UInt") + + ; SetFormat, Integer, Hex + ; OutputDebug, % "UD " + ; Loop, 180 + ; { + ; OutputDebug, % NumGet(&pStatsListEx, A_Index-1, "UChar") " " + ; } + + item := new GameItem(txtFileNo, itemQuality, uniqueOrSetId) , item.name := name , item.itemLoc := itemLoc , item.x := itemx diff --git a/src/settings.ini b/src/settings.ini index 02098f9..e58942a 100644 --- a/src/settings.ini +++ b/src/settings.ini @@ -11,4 +11,3 @@ ; Pressing Ctrl+O in the game will bring up a settings UI [Settings] - diff --git a/src/types/Stats.ahk b/src/types/Stats.ahk index 3f817be..39d2885 100644 --- a/src/types/Stats.ahk +++ b/src/types/Stats.ahk @@ -5,62 +5,66 @@ loadStats(ByRef statCount, ByRef statPtr, ByRef statExCount, ByRef statExPtr) { d2rprocess.readRaw(statPtr, statBuffer, statCount*10) statArray := [] skillsfound := 0 - Loop, %statCount% - { - offset := (A_Index -1) * 8 - , statLayer := NumGet(&statBuffer, offset, Type := "Short") - , statEnum := NumGet(&statBuffer, offset + 0x2, Type := "UShort") - , statValue := NumGet(&statBuffer , offset + 0x4, Type := "Int") - switch (statEnum) { - case 6: statValue := statValue >> 8 ; life - case 7: statValue := statValue >> 8 ; maxlife - case 8: statValue := statValue >> 8 ; mana - case 9: statValue := statValue >> 8 ; maxmana - case 10: statValue := statValue >> 8 ; stamina - case 11: statValue := statValue >> 8 ; maxstamina - case 216: statValue := statValue >> 8 ; item_hp_perlevel - case 217: statValue := statValue >> 8 ; item_mana_perlevel - case 56: statValue := statValue / 25 ; cold length, divided by num frames - case 59: statValue := statValue / 25 ; poison length - } - statName := getStatName(statEnum) - if (statEnum == 107) { - skillsfound++ - statName := statName . skillsfound - + if (statCount < 20) { + Loop, %statCount% + { + offset := (A_Index -1) * 8 + , statLayer := NumGet(&statBuffer, offset, Type := "Short") + , statEnum := NumGet(&statBuffer, offset + 0x2, Type := "UShort") + , statValue := NumGet(&statBuffer , offset + 0x4, Type := "Int") + switch (statEnum) { + case 6: statValue := statValue >> 8 ; life + case 7: statValue := statValue >> 8 ; maxlife + case 8: statValue := statValue >> 8 ; mana + case 9: statValue := statValue >> 8 ; maxmana + case 10: statValue := statValue >> 8 ; stamina + case 11: statValue := statValue >> 8 ; maxstamina + case 216: statValue := statValue >> 8 ; item_hp_perlevel + case 217: statValue := statValue >> 8 ; item_mana_perlevel + case 56: statValue := statValue / 25 ; cold length, divided by num frames + case 59: statValue := statValue / 25 ; poison length + } + statName := getStatName(statEnum) + if (statEnum == 107) { + skillsfound++ + statName := statName . skillsfound + + } + ;OutputDebug, % statName " " statEnum " " statLayer " " statValue "`n" + statArray[statName] := { "statLayer": statLayer, "statValue": statValue } } - ;OutputDebug, % statName " " statEnum " " statLayer " " statValue "`n" - statArray[statName] := { "statLayer": statLayer, "statValue": statValue } } statExCount := statExCount - d2rprocess.readRaw(statExPtr, statBuffer, statExCount*10) - Loop, %statExCount% - { - offset := (A_Index -1) * 8 - , statLayer := NumGet(&statBuffer, offset, Type := "Short") - , statEnum := NumGet(&statBuffer, offset + 0x2, Type := "UShort") - , statValue := NumGet(&statBuffer , offset + 0x4, Type := "Int") - switch (statEnum) { - case 6: statValue := statValue >> 8 ; life - case 7: statValue := statValue >> 8 ; maxlife - case 8: statValue := statValue >> 8 ; mana - case 9: statValue := statValue >> 8 ; maxmana - case 10: statValue := statValue >> 8 ; stamina - case 11: statValue := statValue >> 8 ; maxstamina - case 216: statValue := statValue >> 8 ; item_hp_perlevel - case 217: statValue := statValue >> 8 ; item_mana_perlevel - case 56: statValue := Round(statValue / 25, 0) ; cold length, divided by num frames - case 59: statValue := Round(statValue / 25, 0) ; poison length - } - statName := getStatName(statEnum) - if (statEnum == 107) { - skillsfound++ - statName := statName . skillsfound - + if (statExCount < 20) { + d2rprocess.readRaw(statExPtr, statBuffer, statExCount*10) + Loop, %statExCount% + { + offset := (A_Index -1) * 8 + , statLayer := NumGet(&statBuffer, offset, Type := "Short") + , statEnum := NumGet(&statBuffer, offset + 0x2, Type := "UShort") + , statValue := NumGet(&statBuffer , offset + 0x4, Type := "Int") + switch (statEnum) { + case 6: statValue := statValue >> 8 ; life + case 7: statValue := statValue >> 8 ; maxlife + case 8: statValue := statValue >> 8 ; mana + case 9: statValue := statValue >> 8 ; maxmana + case 10: statValue := statValue >> 8 ; stamina + case 11: statValue := statValue >> 8 ; maxstamina + case 216: statValue := statValue >> 8 ; item_hp_perlevel + case 217: statValue := statValue >> 8 ; item_mana_perlevel + case 56: statValue := Round(statValue / 25, 0) ; cold length, divided by num frames + case 59: statValue := Round(statValue / 25, 0) ; poison length + } + statName := getStatName(statEnum) + if (statEnum == 107) { + skillsfound++ + statName := statName . skillsfound + + } + ;OutputDebug, % statName " " statEnum " " statLayer " " statValue "`n" + statOrder := getStatSortPriority(statName) ;"_" statName + statArray[statName] := { "statLayer": statLayer, "statValue": statValue, "statOrder": statOrder } } - ;OutputDebug, % statName " " statEnum " " statLayer " " statValue "`n" - statOrder := getStatSortPriority(statName) ;"_" statName - statArray[statName] := { "statLayer": statLayer, "statValue": statValue, "statOrder": statOrder } } ; turn list of stats into readable format