Compare commits

..

No commits in common. "master" and "old" have entirely different histories.
master ... old

310 changed files with 1082 additions and 8882 deletions

View file

@ -5,39 +5,29 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Core", "src\Nexus.Core\Nexus.Core.csproj", "{A31E6F94-A702-4B58-8317-83658E556B5C}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Core", "src\Automata.Core\Automata.Core.csproj", "{6432F6A5-11A0-4960-AFFC-E810D4325C35}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.GameOffsets", "src\Nexus.GameOffsets\Nexus.GameOffsets.csproj", "{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Game", "src\Automata.Game\Automata.Game.csproj", "{97B8362D-777C-4ED1-B964-D6598B333E4C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Memory", "src\Nexus.Memory\Nexus.Memory.csproj", "{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Screen", "src\Automata.Screen\Automata.Screen.csproj", "{F92C5EA2-8999-41BC-9B28-D52AD5F3542C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Input", "src\Nexus.Input\Nexus.Input.csproj", "{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Items", "src\Automata.Items\Automata.Items.csproj", "{9CAB0D49-1E24-4F76-ABF8-9A5ED6819F00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Systems", "src\Nexus.Systems\Nexus.Systems.csproj", "{95AC4C34-26A0-4D7F-A712-375EB28B54B8}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Trade", "src\Automata.Trade\Automata.Trade.csproj", "{8F73A696-EB54-4C6F-9603-5A6BAC5D334A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Pathfinding", "src\Nexus.Pathfinding\Nexus.Pathfinding.csproj", "{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Log", "src\Automata.Log\Automata.Log.csproj", "{B68D787D-7A83-4D8F-9F10-0B72C2E99B49}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Data", "src\Nexus.Data\Nexus.Data.csproj", "{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Bot", "src\Automata.Bot\Automata.Bot.csproj", "{188C4F87-153F-4182-B816-9FB56F08CF3A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Engine", "src\Nexus.Engine\Nexus.Engine.csproj", "{C2E97306-20E4-4A69-A7AB-541A72614C76}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Inventory", "src\Automata.Inventory\Automata.Inventory.csproj", "{F186DDC8-6843-43E9-8BD3-9F914C5E784E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Game", "src\Nexus.Game\Nexus.Game.csproj", "{97B8362D-777C-4ED1-B964-D6598B333E4C}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Ui", "src\Automata.Ui\Automata.Ui.csproj", "{859F870E-F013-4C2B-AFEC-7A8C6A5FE3F3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Screen", "src\Nexus.Screen\Nexus.Screen.csproj", "{F92C5EA2-8999-41BC-9B28-D52AD5F3542C}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Automata.Navigation", "src\Automata.Navigation\Automata.Navigation.csproj", "{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Items", "src\Nexus.Items\Nexus.Items.csproj", "{9CAB0D49-1E24-4F76-ABF8-9A5ED6819F00}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roboto.Memory", "src\Roboto.Memory\Roboto.Memory.csproj", "{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Trade", "src\Nexus.Trade\Nexus.Trade.csproj", "{8F73A696-EB54-4C6F-9603-5A6BAC5D334A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Log", "src\Nexus.Log\Nexus.Log.csproj", "{B68D787D-7A83-4D8F-9F10-0B72C2E99B49}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Bot", "src\Nexus.Bot\Nexus.Bot.csproj", "{188C4F87-153F-4182-B816-9FB56F08CF3A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Inventory", "src\Nexus.Inventory\Nexus.Inventory.csproj", "{F186DDC8-6843-43E9-8BD3-9F914C5E784E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Navigation", "src\Nexus.Navigation\Nexus.Navigation.csproj", "{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Ui", "src\Nexus.Ui\Nexus.Ui.csproj", "{859F870E-F013-4C2B-AFEC-7A8C6A5FE3F3}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roboto.GameOffsets", "src\Roboto.GameOffsets\Roboto.GameOffsets.csproj", "{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{652F700E-4F84-4E66-BD62-717D3A8D6FBC}"
EndProject
@ -57,7 +47,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sidekick.Data", "lib\Sideki
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sidekick.Data.Builder", "lib\Sidekick\src\Sidekick.Data.Builder\Sidekick.Data.Builder.csproj", "{E5C26A34-5EDF-488B-93C7-F8738F2CEB97}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nexus.Simulator", "src\Nexus.Simulator\Nexus.Simulator.csproj", "{9198C826-9356-4763-87EF-BBC7166B745B}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "roboto", "roboto", "{D1A2B3C4-E5F6-7890-ABCD-EF1234567890}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roboto.Core", "src\Roboto.Core\Roboto.Core.csproj", "{A31E6F94-A702-4B58-8317-83658E556B5C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roboto.Input", "src\Roboto.Input\Roboto.Input.csproj", "{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roboto.Systems", "src\Roboto.Systems\Roboto.Systems.csproj", "{95AC4C34-26A0-4D7F-A712-375EB28B54B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roboto.Engine", "src\Roboto.Engine\Roboto.Engine.csproj", "{C2E97306-20E4-4A69-A7AB-541A72614C76}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roboto.Navigation", "src\Roboto.Navigation\Roboto.Navigation.csproj", "{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Roboto.Data", "src\Roboto.Data\Roboto.Data.csproj", "{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -68,38 +70,10 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A31E6F94-A702-4B58-8317-83658E556B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A31E6F94-A702-4B58-8317-83658E556B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A31E6F94-A702-4B58-8317-83658E556B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A31E6F94-A702-4B58-8317-83658E556B5C}.Release|Any CPU.Build.0 = Release|Any CPU
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}.Release|Any CPU.Build.0 = Release|Any CPU
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}.Release|Any CPU.Build.0 = Release|Any CPU
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}.Release|Any CPU.Build.0 = Release|Any CPU
{95AC4C34-26A0-4D7F-A712-375EB28B54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95AC4C34-26A0-4D7F-A712-375EB28B54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95AC4C34-26A0-4D7F-A712-375EB28B54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95AC4C34-26A0-4D7F-A712-375EB28B54B8}.Release|Any CPU.Build.0 = Release|Any CPU
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}.Release|Any CPU.Build.0 = Release|Any CPU
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}.Release|Any CPU.Build.0 = Release|Any CPU
{C2E97306-20E4-4A69-A7AB-541A72614C76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2E97306-20E4-4A69-A7AB-541A72614C76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2E97306-20E4-4A69-A7AB-541A72614C76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2E97306-20E4-4A69-A7AB-541A72614C76}.Release|Any CPU.Build.0 = Release|Any CPU
{6432F6A5-11A0-4960-AFFC-E810D4325C35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6432F6A5-11A0-4960-AFFC-E810D4325C35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6432F6A5-11A0-4960-AFFC-E810D4325C35}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6432F6A5-11A0-4960-AFFC-E810D4325C35}.Release|Any CPU.Build.0 = Release|Any CPU
{97B8362D-777C-4ED1-B964-D6598B333E4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{97B8362D-777C-4ED1-B964-D6598B333E4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{97B8362D-777C-4ED1-B964-D6598B333E4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -128,14 +102,22 @@ Global
{F186DDC8-6843-43E9-8BD3-9F914C5E784E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F186DDC8-6843-43E9-8BD3-9F914C5E784E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F186DDC8-6843-43E9-8BD3-9F914C5E784E}.Release|Any CPU.Build.0 = Release|Any CPU
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}.Release|Any CPU.Build.0 = Release|Any CPU
{859F870E-F013-4C2B-AFEC-7A8C6A5FE3F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{859F870E-F013-4C2B-AFEC-7A8C6A5FE3F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{859F870E-F013-4C2B-AFEC-7A8C6A5FE3F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{859F870E-F013-4C2B-AFEC-7A8C6A5FE3F3}.Release|Any CPU.Build.0 = Release|Any CPU
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B}.Release|Any CPU.Build.0 = Release|Any CPU
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B}.Release|Any CPU.Build.0 = Release|Any CPU
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F}.Release|Any CPU.Build.0 = Release|Any CPU
{B858F6F2-389F-475A-87FE-E4E01DA3E948}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B858F6F2-389F-475A-87FE-E4E01DA3E948}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B858F6F2-389F-475A-87FE-E4E01DA3E948}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -168,20 +150,33 @@ Global
{E5C26A34-5EDF-488B-93C7-F8738F2CEB97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5C26A34-5EDF-488B-93C7-F8738F2CEB97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5C26A34-5EDF-488B-93C7-F8738F2CEB97}.Release|Any CPU.Build.0 = Release|Any CPU
{9198C826-9356-4763-87EF-BBC7166B745B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9198C826-9356-4763-87EF-BBC7166B745B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9198C826-9356-4763-87EF-BBC7166B745B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9198C826-9356-4763-87EF-BBC7166B745B}.Release|Any CPU.Build.0 = Release|Any CPU
{A31E6F94-A702-4B58-8317-83658E556B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A31E6F94-A702-4B58-8317-83658E556B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A31E6F94-A702-4B58-8317-83658E556B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A31E6F94-A702-4B58-8317-83658E556B5C}.Release|Any CPU.Build.0 = Release|Any CPU
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A}.Release|Any CPU.Build.0 = Release|Any CPU
{95AC4C34-26A0-4D7F-A712-375EB28B54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95AC4C34-26A0-4D7F-A712-375EB28B54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95AC4C34-26A0-4D7F-A712-375EB28B54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95AC4C34-26A0-4D7F-A712-375EB28B54B8}.Release|Any CPU.Build.0 = Release|Any CPU
{C2E97306-20E4-4A69-A7AB-541A72614C76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2E97306-20E4-4A69-A7AB-541A72614C76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2E97306-20E4-4A69-A7AB-541A72614C76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2E97306-20E4-4A69-A7AB-541A72614C76}.Release|Any CPU.Build.0 = Release|Any CPU
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D}.Release|Any CPU.Build.0 = Release|Any CPU
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A31E6F94-A702-4B58-8317-83658E556B5C} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{95AC4C34-26A0-4D7F-A712-375EB28B54B8} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{C2E97306-20E4-4A69-A7AB-541A72614C76} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{6432F6A5-11A0-4960-AFFC-E810D4325C35} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{97B8362D-777C-4ED1-B964-D6598B333E4C} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{F92C5EA2-8999-41BC-9B28-D52AD5F3542C} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{9CAB0D49-1E24-4F76-ABF8-9A5ED6819F00} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
@ -189,8 +184,10 @@ Global
{B68D787D-7A83-4D8F-9F10-0B72C2E99B49} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{188C4F87-153F-4182-B816-9FB56F08CF3A} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{F186DDC8-6843-43E9-8BD3-9F914C5E784E} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{859F870E-F013-4C2B-AFEC-7A8C6A5FE3F3} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{D3F7A2E1-9B4C-4E8D-A6F5-1C2D3E4F5A6B} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{B7E3F1A2-4D5C-6E7F-8A9B-0C1D2E3F4A5B} = {D1A2B3C4-E5F6-7890-ABCD-EF1234567890}
{C8D9E0F1-2A3B-4C5D-6E7F-8A9B0C1D2E3F} = {D1A2B3C4-E5F6-7890-ABCD-EF1234567890}
{B858F6F2-389F-475A-87FE-E4E01DA3E948} = {652F700E-4F84-4E66-BD62-717D3A8D6FBC}
{6FEA655D-18E4-4DA1-839F-A41433B03FBB} = {652F700E-4F84-4E66-BD62-717D3A8D6FBC}
{74FD0F88-86BC-49AE-9A16-136D92A10090} = {652F700E-4F84-4E66-BD62-717D3A8D6FBC}
@ -199,6 +196,12 @@ Global
{8CEE036C-A229-4F22-BD0E-D7CDAE13E54F} = {652F700E-4F84-4E66-BD62-717D3A8D6FBC}
{9428D5D4-4061-467A-BD26-C1FEED95E8E6} = {652F700E-4F84-4E66-BD62-717D3A8D6FBC}
{E5C26A34-5EDF-488B-93C7-F8738F2CEB97} = {652F700E-4F84-4E66-BD62-717D3A8D6FBC}
{9198C826-9356-4763-87EF-BBC7166B745B} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{D1A2B3C4-E5F6-7890-ABCD-EF1234567890} = {67A27DFE-D2C5-479D-86FE-7E156BD0CFAA}
{A31E6F94-A702-4B58-8317-83658E556B5C} = {D1A2B3C4-E5F6-7890-ABCD-EF1234567890}
{E61E96C5-3DE7-4B31-A7AD-CCA99BEF8E4A} = {D1A2B3C4-E5F6-7890-ABCD-EF1234567890}
{95AC4C34-26A0-4D7F-A712-375EB28B54B8} = {D1A2B3C4-E5F6-7890-ABCD-EF1234567890}
{C2E97306-20E4-4A69-A7AB-541A72614C76} = {D1A2B3C4-E5F6-7890-ABCD-EF1234567890}
{F4B5C6D7-E8F9-0A1B-2C3D-4E5F6A7B8C9D} = {D1A2B3C4-E5F6-7890-ABCD-EF1234567890}
{1A2B3C4D-5E6F-7A8B-9C0D-E1F2A3B4C5D6} = {D1A2B3C4-E5F6-7890-ABCD-EF1234567890}
EndGlobalSection
EndGlobal

View file

@ -1,188 +0,0 @@
# Nexus — Architecture Overview
## What Is This
A modular C# automation framework for POE2. The system reads game memory, builds a structured game state, runs AI systems (combat, navigation, threat assessment), and emits input commands. A separate trade pipeline monitors the trade site via a Node.js daemon and executes buy flows.
When the real game isn't available, a standalone **Simulator** replaces the memory layer with a procedural game world — same bot systems, same interfaces, zero game dependency.
## Solution Structure
```
Nexus.sln (net8.0-windows10.0.19041.0)
├── Core Layer (shared types, no dependencies)
│ └── Nexus.Core
├── Infrastructure Layer (reads from external sources)
│ ├── Nexus.GameOffsets Pure offset structs for memory reading
│ ├── Nexus.Memory Process memory reading (RPM, pattern scan)
│ ├── Nexus.Screen Screen capture, OCR, grid detection
│ ├── Nexus.Log Client.txt game log watcher
│ └── Nexus.Input Win32 SendInput / Interception driver
├── Data Layer (transforms raw data into typed game state)
│ └── Nexus.Data EntityMapper, EntityClassifier, GameDataCache, MemoryPoller, GameStateEnricher
├── Logic Layer (AI systems that decide what to do)
│ ├── Nexus.Systems ThreatSystem, MovementSystem, CombatSystem, ResourceSystem, LootSystem
│ ├── Nexus.Engine BotEngine (orchestrator), AreaProgressionSystem, MovementKeyTracker
│ └── Nexus.Pathfinding NavigationController, A* PathFinder
├── Game Interaction Layer (acts on the game)
│ ├── Nexus.Game Window focus, input sending, clipboard
│ ├── Nexus.Items Item parsing via Sidekick
│ ├── Nexus.Inventory Stash/inventory grid management
│ ├── Nexus.Navigation Minimap-based real-time navigation
│ └── Nexus.Trade Trade daemon IPC (Node.js Playwright)
├── Orchestration Layer (top-level coordination)
│ ├── Nexus.Bot BotOrchestrator, Trade/Mapping/Crafting executors
│ └── Nexus.Ui Avalonia 11.2 desktop GUI (entry point)
└── Testing Layer
└── Nexus.Simulator Standalone game world for bot testing
```
## Dependency Flow
```
Nexus.Core
├── Nexus.GameOffsets ──→ Nexus.Memory ──→ Nexus.Data ──→ Nexus.Engine
│ │ │
├── Nexus.Input │ Nexus.Systems
│ │ │
├── Nexus.Screen ◄───────────────────────────────┘ │
├── Nexus.Game │
├── Nexus.Log │
│ │
├── Nexus.Pathfinding ◄─────────────────────────────────────────┘
├── Nexus.Items, Nexus.Inventory, Nexus.Navigation, Nexus.Trade
├── Nexus.Bot (consumes all above)
├── Nexus.Ui (DI hub, entry point, consumes all)
└── Nexus.Simulator (Core, Data, Systems, Pathfinding — NOT Memory/Input/Screen)
```
## Data Flow — Per Tick
```
┌─────────────────────────────────────────────────────────────────────┐
│ MemoryPoller Thread (60Hz hot / 10Hz cold) │
│ │
│ Hot tick (4 RPM calls): │
│ Camera matrix, Player position, Player vitals, Loading state │
│ │
│ Cold tick (full hierarchical read): │
│ Entity tree traversal → classification → EntitySnapshot[] │
│ Terrain grid, Skills, Quests, UI elements │
│ │
│ Writes to GameDataCache (volatile references, lock-free) │
└────────────────────────────┬────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ BotEngine Logic Thread (25Hz default) │
│ │
│ 1. Read latest GameState from cache │
│ 2. GameStateEnricher → NearestEnemies, ThreatMap, DangerLevel │
│ 3. Clear ActionQueue │
│ 4. NavigationController.Update() → path, DesiredDirection │
│ 5. Run systems in priority order: │
│ ThreatSystem (50) → MovementSystem (100) → │
│ AreaProgressionSystem (199) → NavigationSystem (200) → │
│ CombatSystem (300) → ResourceSystem (400) → LootSystem (500) │
│ 6. ActionQueue.Resolve() → conflict resolution │
│ 7. ExecuteActions() → IInputController │
└────────────────────────────┬────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ IInputController (Win32 SendInput or Interception driver) │
│ │
│ WASD keys (scan codes), mouse movement (Bézier curves), │
│ skill casts, flask presses, clicks │
└─────────────────────────────────────────────────────────────────────┘
```
## Action Resolution
Systems submit actions to a shared `ActionQueue`. The queue resolves conflicts:
| Action Type | Behavior |
|-------------|----------|
| FlaskAction | Always passes through |
| MoveAction (priority ≤ 10) | Urgent flee — blocks CastAction |
| MoveAction (priority > 10) | Normal move — allows CastAction alongside |
| CastAction | Passes unless blocked by urgent flee |
| Other (Key, Click, Chat) | Always passes through |
Priority values: lower number = higher priority. ThreatSystem uses priority 5 for emergency flee (blocks all casting).
## System Priority Table
| Priority | System | Purpose |
|----------|--------|---------|
| 50 | ThreatSystem | Emergency flee on High/Critical danger |
| 100 | MovementSystem | Soft avoidance via inverse-square repulsion |
| 199 | AreaProgressionSystem | Quest-driven area traversal and transitions |
| 200 | NavigationSystem | Submits NavigationController's direction |
| 300 | CombatSystem | Skill rotation, target selection, kiting |
| 400 | ResourceSystem | Flask usage on life/mana thresholds |
| 500 | LootSystem | Item pickup (stub) |
## Thread Model
| Thread | Rate | Responsibility |
|--------|------|----------------|
| MemoryPoller | 60Hz hot, 10Hz cold | Read game memory → GameDataCache |
| BotEngine Logic | 25Hz | Run AI systems → emit actions |
| Render (Simulator only) | vsync | ImGui + Veldrid drawing |
| Trade Daemon | event-driven | Node.js Playwright → stdin/stdout JSON IPC |
| Log Watcher | 200ms poll | Client.txt → area/whisper/trade events |
Cross-thread safety: GameDataCache uses `volatile` references. No locks — writer (MemoryPoller) atomically swaps reference types, readers (BotEngine) get consistent snapshots.
## Simulator Architecture
When the real game isn't available, `Nexus.Simulator` replaces the memory pipeline:
```
┌─────────────────────────────────────────────────────┐
│ Nexus.Simulator.exe │
│ │
│ ┌──────────┐ GameState ┌──────────────────┐ │
│ │ SimWorld │───────────────►│ GameDataCache │ │
│ │ (terrain, │ SimPoller + │ (same as prod) │ │
│ │ enemies, │ StateBuilder └────────┬─────────┘ │
│ │ player) │ │ │
│ └─────┬────┘ ┌────────▼─────────┐ │
│ │ │ Bot Systems │ │
│ │◄─────────────────────│ (unchanged) │ │
│ │ SimInputController └──────────────────┘ │
│ │ │
│ ┌─────▼───────────────────────────────────────┐ │
│ │ ImGui + Veldrid Renderer (isometric 2D) │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
```
Bot systems don't know they're in a simulation — they see identical `GameState` objects and emit actions to `IInputController`.
## Key Design Decisions
| Decision | Rationale |
|----------|-----------|
| Immutable records (GameState, EntitySnapshot) | Thread-safe sharing without locks |
| Priority-based ActionQueue | Natural conflict resolution without hardcoded if-else |
| Two-tier memory polling (hot/cold) | Balance responsiveness (position at 60Hz) with CPU cost (entities at 10Hz) |
| Scan codes over virtual keys | Games read hardware scan codes, not VK codes |
| Separate Memory → Data layers | Memory reads raw bytes; Data interprets and classifies. Clean testability. |
| IInputController interface | Swap real Win32 input for simulated input without changing bot logic |
| BFS exploration + A* pathfinding | BFS finds what to explore; A* finds how to get there |
| CharacterProfile auto-detection | Automatically applies combat/flask settings per character name |
| External daemons (Trade, OCR) | Isolate browser/OCR concerns from main process |

View file

@ -1,158 +0,0 @@
# Nexus.Core — Shared Types & Abstractions
The foundation layer. Every other project depends on Core. Contains no logic — only types, interfaces, configuration, and utilities.
## GameState
Central immutable snapshot updated once per tick. All systems read from this; none mutate it.
```
GameState
├── Timing: TickNumber, DeltaTime, TimestampMs
├── Player: PlayerState
│ ├── CharacterName, Position, Z, HasPosition
│ ├── Life/Mana/ES: Current, Total, Percent (derived)
│ ├── ActionId (actor animation state)
│ ├── Skills: SkillState[] (cooldowns, charges, cast state)
│ ├── Flasks: FlaskState[] (charges, active, cooldown)
│ └── Buffs: Buff[] (name, duration, charges, isDebuff)
├── Entities: EntitySnapshot[] (all game entities)
├── HostileMonsters: EntitySnapshot[] (alive monsters, filtered)
├── NearbyLoot: EntitySnapshot[] (world items, filtered)
├── NearestEnemies: EntitySnapshot[] (sorted by distance — enriched)
├── Terrain: WalkabilitySnapshot (grid, offsets)
├── Area: AreaHash, AreaLevel, CurrentAreaName
├── UI: IsLoading, IsEscapeOpen, CameraMatrix
├── Quests: ActiveQuests[], UiQuests[], Quests[] (enriched with paths)
├── Threats: ThreatMap (zone buckets, centroid, rarity flags)
├── Danger: DangerLevel (Safe/Low/Medium/High/Critical — enriched)
└── GroundEffects: GroundEffect[] (hazard positions)
```
## EntitySnapshot
Immutable record for any game entity:
- **Identity**: Id (uint), Path, Metadata, Category (EntityCategory enum)
- **Spatial**: Position (Vector2), Z, DistanceToPlayer
- **Combat**: IsAlive, LifeCurrent/Total, IsTargetable, ThreatLevel, Rarity, ModNames
- **State**: ActionId, IsAttacking, IsMoving, Components (HashSet)
- **Special**: TransitionName/State, ItemBaseName, IsQuestItem, LabelOffset
**EntityCategory** (17 types): Unknown, Player, Monster, Npc, WorldItem, Chest, Shrine, Portal, AreaTransition, Effect, Terrain, MiscObject, Waypoint, Door, Doodad, TownPortal, Critter
**MonsterRarity**: White, Magic, Rare, Unique
**MonsterThreatLevel**: None, Normal, Magic, Rare, Unique
## Actions
Polymorphic action system. All inherit from `BotAction` with a `Priority` field.
| Action | Fields | Purpose |
|--------|--------|---------|
| MoveAction | Direction (Vector2) | WASD movement |
| CastAction | SkillScanCode, TargetScreenPos or TargetEntityId | Skill usage |
| FlaskAction | FlaskScanCode | Flask consumption |
| KeyAction | ScanCode, Type (Press/Down/Up) | Raw keyboard |
| ClickAction | ScreenPosition, Type (Left/Right/Middle) | Mouse click |
| ChatAction | Message | Send chat message |
| WaitAction | DurationMs | Delay |
## ActionQueue
Manages conflict resolution between competing system outputs.
**Resolve() rules:**
1. FlaskActions always pass through
2. Get highest-priority MoveAction and CastAction
3. If MoveAction priority ≤ 10 (urgent flee): include move, **block** cast
4. Else: include both move and cast
5. All other action types pass through
## ISystem Interface
```csharp
public interface ISystem
{
int Priority { get; } // Execution order (lower = first)
string Name { get; }
bool IsEnabled { get; set; }
void Update(GameState state, ActionQueue actions);
}
```
**SystemPriority constants**: Threat=50, Movement=100, Navigation=200, Combat=300, Resource=400, Loot=500
## IInputController Interface
Abstraction over Win32 input. Two implementations: SendInputController (vanilla), InterceptionInputController (driver).
```csharp
public interface IInputController
{
bool IsInitialized { get; }
void KeyDown(ushort scanCode);
void KeyUp(ushort scanCode);
void KeyPress(ushort scanCode, int holdMs = 50);
void MouseMoveTo(int x, int y);
void SmoothMoveTo(int x, int y); // Bézier curve interpolation
void LeftClick(int x, int y);
void RightClick(int x, int y);
void MiddleClick(int x, int y);
void LeftDown(); void LeftUp();
void RightDown(); void RightUp();
}
```
## WalkabilitySnapshot
Grid-based terrain with offset support for infinite expansion:
```csharp
public record WalkabilitySnapshot
{
public int Width, Height;
public byte[] Data; // Row-major; 0=wall, nonzero=walkable
public int OffsetX, OffsetY; // Absolute grid coords of top-left corner
public bool IsWalkable(int gx, int gy)
{
var lx = gx - OffsetX; // Absolute → local
var ly = gy - OffsetY;
if (out of bounds) return false;
return Data[ly * Width + lx] != 0;
}
}
```
Coordinate conversion: `WorldToGrid = 23f / 250f ≈ 0.092`
- World → Grid: `gx = (int)(worldX * WorldToGrid)`
- Grid → World: `worldX = gx / WorldToGrid`
## Configuration
**BotConfig** — Static bot parameters:
- Tick rates: LogicTickRateHz=60, MemoryPollRateHz=30
- Movement: SafeDistance=400, RepulsionWeight=1.5, WaypointReachedDistance=80
- Humanization: MinReactionDelayMs=50, MaxReactionDelayMs=150, ClickJitterRadius=3, MaxApm=250
**CharacterProfile** — Per-character settings:
- Skills (8 slots: LMB, RMB, MMB, Q, E, R, T, F) with priority, cooldown, range, target selection
- Flasks (thresholds, scan codes, cooldown)
- Combat (global cooldown, attack/safe/kite ranges)
**SkillProfile** — Per-skill configuration:
- InputType (KeyPress/LeftClick/RightClick/MiddleClick)
- TargetSelection (Nearest/All/Rarest/MagicPlus/RarePlus/UniqueOnly)
- RequiresTarget, IsAura, IsMovementSkill, MaintainPressed
- MinMonstersInRange (AOE threshold)
## Utilities
- **WorldToScreen.Project()** — Matrix projection: world coords → screen coords via camera matrix
- **TerrainQuery.HasLineOfSight()** — Bresenham line walk on walkability grid
- **TerrainQuery.FindWalkableDirection()** — Rotates direction ±45°/90°/135°/180° to find clear path
- **Helpers.Sleep()** — Task delay with ±10% variance
- **DangerLevel**: Safe, Low, Medium, High, Critical
- **ThreatMap**: TotalHostiles, CloseRange(<300), MidRange(300-600), FarRange(600-1200), ClosestDistance, ThreatCentroid, HasRareOrUnique

View file

@ -1,229 +0,0 @@
# Nexus.Data & Nexus.Memory — The Data Pipeline
## Overview
Two-layer architecture: **Memory** reads raw bytes from the game process; **Data** interprets, classifies, and caches them. This separation keeps memory reading logic free of business rules and makes the data layer testable independently.
```
Game Process (RPM)
Nexus.Memory (raw reads, no business logic)
│ GameMemoryReader → hierarchical state tree
│ EntityList → red-black tree traversal
│ ComponentReader → ECS component extraction
Nexus.Data (interpretation, classification, caching)
│ MemoryPoller → two-tier event loop
│ EntityMapper → Memory.Entity → Core.EntitySnapshot
│ EntityClassifier → path + components → EntityCategory
│ GameStateEnricher → derived threat/danger metrics
GameDataCache (volatile references, lock-free)
Bot Systems (read-only consumers)
```
---
## GameDataCache — Single Source of Truth
Thread-safe, volatile reference holder. Writer: MemoryPoller thread. Readers: bot systems.
**Hot fields** (updated at 60Hz — 4 lightweight RPM calls):
- CameraMatrix (64 bytes)
- PlayerPosition (X, Y, Z)
- PlayerVitals (HP, mana, ES current/max)
- IsLoading, IsEscapeOpen
**Cold fields** (updated at 10Hz — full hierarchical read):
- Entities, HostileMonsters, NearbyLoot
- Terrain (WalkabilitySnapshot)
- AreaHash, AreaLevel, CurrentAreaName
- Quest data (linked lists, UI groups, state entries)
- LatestState (complete GameState)
**Slow fields** (updated at 1Hz):
- Character name
- Quest linked lists, quest state entries
No locks — relies on volatile reference semantics for atomic swaps.
---
## MemoryPoller — Two-Tier Event Loop
Owns the memory-reading background thread.
### Hot Tick (60Hz)
4 pre-resolved RPM calls using cached addresses:
1. Camera matrix (64 bytes from cached address)
2. Player position (12 bytes: X, Y, Z)
3. Player vitals (24 bytes: HP, mana, ES)
4. Loading/escape state (pointer dereference + int)
No allocations, no GC. Targeting ~3-5ms per tick.
### Cold Tick (10Hz, every 6th hot tick)
Full hierarchical read:
1. `GameMemoryReader.ReadSnapshot()` — cascades through state tree
2. Re-resolve hot addresses via `ResolveHotAddresses()`
3. `BuildGameState()` — map entities, filter lists, process quests
4. `GameStateEnricher.Enrich()` — compute derived fields
5. Update all cache fields
### BuildGameState() Flow
```
ReadSnapshot() → GameStateSnapshot (raw)
├── Entity mapping:
│ for each entity in snapshot:
│ EntityMapper.MapEntity(entity, playerPos) → EntitySnapshot
├── Filter into:
│ - HostileMonsters (Category==Monster && IsAlive)
│ - NearbyLoot (Category==WorldItem)
│ - All entities
├── Quest processing:
│ - Filter active (StateId > 0)
│ - Resolve state text via QuestStateLookup
│ - Convert to QuestProgress, QuestInfo
└── Returns GameState
```
---
## GameMemoryReader — Hierarchical State Tree
Top-level orchestrator. Creates sub-readers on `Attach()`:
```
GameStates (top)
└── InGameState
├── AreaInstance
│ ├── EntityList (MSVC std::map red-black tree)
│ ├── PlayerSkills (Actor component)
│ ├── QuestStates (dat file entries)
│ └── Terrain (walkability grid)
├── UIElements (quest linked lists, UI tree)
└── WorldData (camera matrix)
```
Each `RemoteObject` caches its data and depends on parent for context. Single `Update()` call cascades through tree.
### Infrastructure
- **ProcessMemory**: P/Invoke wrapper for ReadProcessMemory. Tracks reads/sec and KB/sec.
- **MemoryContext**: Shared state — process handle, offsets, module base, pattern scanner.
- **ComponentReader**: Reads ECS components (Life, Render, Mods, etc.) from entities.
- **MsvcStringReader**: Reads MSVC std::wstring (SSO-aware: inline if capacity ≤ 8, heap pointer otherwise).
- **PatternScanner**: AOB scan for resolving base addresses.
---
## EntityList — Tree Traversal
Reads entities from AreaInstance's MSVC std::map (red-black tree, in-order traversal).
**Tree node layout:**
```
+0x00: left child ptr
+0x08: parent ptr
+0x10: right child ptr
+0x28: entity pointer
```
**Optimization**: Tree order is cached — re-walked only when entity count changes.
**Per-entity reads:**
1. Path (EntityDetails → std::wstring)
2. Skip low-priority types (effects, terrain, critters — no components read)
3. Position (Render component: X, Y, Z)
4. Component lookup (STL hash map: name → index)
5. Component data:
- Targetable (bool flag)
- Mods/ObjectMagicProperties (rarity)
- Life (HP, dynamic — re-read every frame for monsters)
- Actor (action ID)
- WorldItem (inner entity for ground loot)
- AreaTransition (destination area)
**Caching strategy:**
- Stable per entity: path, component list, targetable, rarity, transition name
- Dynamic (re-read every frame): monster HP, action ID
---
## EntityClassifier — Path + Components → Category
Single source of truth for entity classification.
1. **Path-based** (primary): Parses `Metadata/[Category]/...` path segments
2. **Component override**: Monster, Chest, Shrine, Waypoint, AreaTransition, Portal, TownPortal, NPC, Player
Output: `EntityCategory` (Core enum, 17 types)
---
## EntityMapper — Memory.Entity → Core.EntitySnapshot
Transforms raw memory data to enriched snapshots:
```
Memory.Entity (raw)
├── Copy: ID, path, metadata, position, Z, vitals, components, mods
├── Classify: EntityClassifier.Classify(path, components) → EntityCategory
├── Threat level: Rarity → MonsterThreatLevel
├── Area name: AreaNameLookup.Resolve() for transitions
├── Distance: Vector2.Distance(position, playerPos)
└── Alive state: HasVitals ? LifeCurrent > 0 : true
Core.EntitySnapshot (public, classified, enriched)
```
---
## GameStateEnricher — Derived Metrics
Computed once per cold tick, before systems run.
**NearestEnemies**: HostileMonsters sorted by distance to player.
**ThreatMap**:
- TotalHostiles, CloseRange (<300u), MidRange (300-600u), FarRange (600-1200u)
- ClosestDistance, ThreatCentroid (position average), HasRareOrUnique
**DangerLevel** — Weighted threat score:
```
score = Σ (distance_weight × rarity_multiplier)
Distance weights: <200u = 3×, <400u = 2×, else = 1×
Rarity multipliers: Unique=5×, Rare=3×, Magic=1.5×, White=1×
Life override: HP < 30% Critical, HP < 50% High
Score thresholds: ≥15 = Critical, ≥8 = High, ≥4 = Medium, >0 = Low, 0 = Safe
```
---
## Key Architectural Patterns
| Pattern | Implementation |
|---------|---------------|
| Lock-free cross-thread | Volatile references in GameDataCache; no locks needed |
| Two-tier polling | Hot (4 RPM, 60Hz) + Cold (full read, 10Hz) |
| Hierarchical caching | Each RemoteObject caches data, re-reads only on change |
| Entity caching | Stable data cached per entity/zone; dynamic data (HP) re-read per frame |
| Separation of concerns | Memory: raw bytes. Data: interpretation + classification |
| Area name resolution | AreaNameLookup loads areas.json, caches ID → display name |
| Area graph | BFS pathfinding for quest progression ordering |

View file

@ -1,197 +0,0 @@
# Nexus.Engine & Nexus.Systems — Bot Brain
## BotEngine (Orchestrator)
The main loop. Owns systems, navigation, profiles, and action execution.
### Logic Loop (25Hz, background thread)
```
1. Wait for MemoryPoller to provide latest GameState
2. CheckCharacterProfile() → auto-load profile if character changed
3. GameStateEnricher.Enrich() → compute NearestEnemies, ThreatMap, DangerLevel
4. Clear ActionQueue
5. NavigationController.Update(state) → compute path, set DesiredDirection
6. Run all ISystem implementations in priority order
7. NavigationSystem submits MoveAction if DesiredDirection is set
8. ActionQueue.Resolve() → merge conflicts
9. ExecuteActions() → emit key/mouse/click commands via IInputController
```
### Action Execution
| Action | Execution |
|--------|-----------|
| MoveAction | Direction → MovementKeyTracker → WASD key state changes (delta-based) |
| CastAction | SmoothMoveTo target + key press. Re-projects moving entities. Adds ±30-50px jitter. |
| FlaskAction | Direct key press |
| KeyAction | Press/Down/Up operations |
| ClickAction | Left/Right/Middle click at screen position |
### MovementKeyTracker
Converts world-space direction vectors to WASD keys for isometric camera:
```
1. Rotate direction 45° to align with isometric axes
2. sx = dir.X * cos(45°) - dir.Y * sin(45°)
3. sy = dir.X * sin(45°) + dir.Y * cos(45°)
4. W if sy > 0.3, S if sy < -0.3, D if sx > 0.3, A if sx < -0.3
5. Only emit key changes (delta-based — no redundant KeyDown/KeyUp)
```
### Mouse Drift (Navigation)
During navigation, lazily repositions the mouse toward enemy clusters:
- Projects enemy centroid ahead of player movement
- Applies ±25° angular offset for organic appearance
- Fires every 800-1500ms (randomized)
### Safety
- Releases all held keys when loading screen or escape menu detected
- CombatSystem's `ReleaseAllHeld()` called on state transitions
---
## Systems
### ThreatSystem (Priority 50)
Emergency threat response. Runs first, only acts on elevated danger.
| Danger | Response |
|--------|----------|
| Safe / Low | No action |
| Medium | No action (MovementSystem handles soft avoidance) |
| High | Flee toward safety (priority 50, allows casting) |
| Critical or point-blank (<150 units) | **Urgent flee (priority 5) — blocks all casting** |
**Flee direction**: `Player.Position - ThreatCentroid`, validated against terrain via `FindWalkableDirection()`.
### MovementSystem (Priority 100)
Continuous soft avoidance via **inverse-square repulsion field**.
For each hostile monster within SafeDistance (400 units):
```
force += (playerPos - enemyPos) / distanceSquared * RepulsionWeight
```
Normalizes sum, validates against terrain, submits as lower-priority MoveAction.
Effect: Player gently drifts away from enemies without hard fleeing.
### AreaProgressionSystem (Priority 199)
High-level area traversal. Runs before NavigationSystem to take precedence.
**State machine (7 phases):**
```
Exploring → Looting → NavigatingToChest → InteractingChest →
NavigatingToTransition → Interacting → TalkingToNpc
```
**Exploration strategy:**
1. Check for elite enemies (Rare/Unique within 800u) → yield to combat
2. Check for quest chests → navigate and interact
3. Check for loot (if danger ≤ Low) → pick up within 600u
4. Once fully explored → find area transition matching quest target
5. In towns with active quest → talk to NPC
**Quest integration**: Queries active quests for target areas. Prioritizes tracked quests, then lowest act, then shortest path. Blacklists failed transitions after 5s timeout.
**Navigation delegation**: Uses `NavigationController.NavigateToEntity()` and `.Explore()`. Sets targets and yields until reached.
### NavigationSystem (Priority 200)
Ultra-thin passthrough. If `NavigationController.DesiredDirection` is set, submits a MoveAction. All actual pathfinding logic lives in NavigationController (see [pathfinding.md](pathfinding.md)).
### CombatSystem (Priority 300)
Skill rotation and target selection. Hot-swappable via CharacterProfile.
**Rotation loop:**
```
1. Check global cooldown (skip if recently cast)
2. For each skill in priority order:
a. Check per-skill cooldown
b. Match skill to memory via slot index (fallback to name)
c. If aura: cast once per zone
d. If damage: find target → submit CastAction
3. Release held keys for skills without valid targets
```
**Target selection pipeline:**
```
1. Filter by TargetSelection (Nearest, Rarest, MagicPlus, RarePlus, UniqueOnly)
2. Filter by range (SkillProfile.RangeMin/RangeMax)
3. Filter by line-of-sight (terrain query)
4. Check MinMonstersInRange (AOE threshold)
5. Pick best: Rarest mode → prefer higher rarity then nearer; others → nearest
6. Project to screen coordinates
```
**Skill input types:**
- LeftClick/RightClick/MiddleClick: Direct click at target position
- KeyPress with MaintainPressed: Hold key continuously
- KeyPress normal: Single tap
**Kiting/orbit (during global cooldown):**
- Computes enemy centroid
- Moves perpendicular to centroid (orbital movement)
- Applies radial bias to maintain ideal distance
- Flips orbit direction if terrain blocks path
- Persists orbit sign across ticks for smooth motion
**Cooldown management:**
- Per-skill: `max(skill.CooldownMs, globalCd + 50)` for rotation
- MaintainPressed skills: use skill.CooldownMs directly
- Area reset: clears aura tracking, resets orbit
### ResourceSystem (Priority 400)
Flask automation based on life/mana thresholds.
```
if LifePercent < LifeFlaskThreshold (50%) && cooldown expired FlaskAction
if ManaPercent < ManaFlaskThreshold (50%) && cooldown expired FlaskAction
```
Flask cooldown: 4000ms default. Hot-swappable on character profile change.
### LootSystem (Priority 500)
Stub — disabled by default. Item pickup logic handled by AreaProgressionSystem's looting phase.
---
## System Interaction Diagram
```
GameState (read-only, shared)
├─→ ThreatSystem ──→ MoveAction (priority 5 or 50)
│ [blocks casting if priority ≤ 10]
├─→ MovementSystem ──→ MoveAction (priority 100)
│ [soft repulsion, overridable]
├─→ AreaProgressionSystem ──→ NavigateTo/Explore commands
│ [drives NavigationController]
├─→ NavigationSystem ──→ MoveAction (priority 200)
│ [passthrough from NavigationController]
├─→ CombatSystem ──→ CastAction (priority 300)
│ [skill rotation + target selection]
├─→ ResourceSystem ──→ FlaskAction (priority 400)
│ [always passes through]
└─→ ActionQueue.Resolve()
├── Highest MoveAction wins
├── CastAction passes unless blocked by urgent flee
├── FlaskAction always passes
└──→ ExecuteActions() → IInputController
```

View file

@ -1,207 +0,0 @@
# Infrastructure & Game Interaction Projects
## Nexus.GameOffsets — Memory Layout Definitions
Pure offset structs for POE2 game memory. No logic, no reading — just struct layouts.
**Contents:**
- **Entities/**: `EntityStruct`, `EntityDetails`, `ComponentLookup`, `ComponentNameAndIndex`, `ItemStruct`, `EntityTreeNode`
- **Components/** (22 structs): Actor, Animated, Buffs, Chest, Life, Mods, Player, Positioned, Render, Stats, Targetable, Transitionable, WorldItem, etc.
- **States/**: `InGameState`, `AreaInstance`, `AreaLoading`, `ServerData`, `WorldData`, `Inventory`, `ImportantUiElements`
- **Natives/**: C++ STL memory layouts — `StdVector`, `StdMap`, `StdList`, `StdBucket`, `StdWString`, `StdTuple`
**Key offsets:**
- Actor skills: 0xB00 (ActiveSkillsVector), 0xB18 (CooldownsVector)
- UIElement: 0x10 (Children), 0x98 (StringId), 0x180 (Flags), 0x448 (Text)
- Entity: 0x80 (ID), 0x84 (Flags), 0x08 (EntityDetails)
**Dependencies**: None. Used by Memory and Data layers.
---
## Nexus.Screen — Screen Capture, OCR & Detection
Screen capture, OCR, image processing, grid/item detection, loot label detection.
### Core Components
| Class | Purpose |
|-------|---------|
| ScreenReader | Main facade — OCR, template matching, screenshot, diff OCR |
| IScreenCapture | Desktop duplication or GDI capture |
| IOcrEngine | Interface for OCR backends (Win native, EasyOCR, OneOCR, WinOCR) |
| PythonOcrBridge | Calls Python script via subprocess for EasyOCR/YOLO |
### Grid & Item Detection
| Class | Purpose |
|-------|---------|
| GridReader | Reads stash/inventory grids (12-col 70×70px or 24-col 35×35px) |
| GridHandler | Template matching for cell occupancy, item size detection |
| TemplateMatchHandler | NCC-based visual matching (find identical items in grid) |
| DetectGridHandler | Edge detection to find grid boundaries |
### Detection Systems
| Class | Purpose |
|-------|---------|
| EnemyDetector | YOLO/ONNX object detection for enemy positions |
| BossDetector | Boss-specific recognition |
| HudReader | HUD element OCR (HP bar, mana, buffs) |
| GameStateDetector | Main menu vs in-game state |
| ScreenReader.DetectLootLabels() | Three-pass loot detection (polygon, contour, yellow text) |
### Frame Pipeline
Pub-sub for screen frames: `FramePipeline` distributes captured frames to multiple `IFrameConsumer` implementations (GameState, Enemy, Boss detectors, Minimap, Navigation).
**Used by**: Bot, Navigation, Inventory, Ui
---
## Nexus.Game — Game Interaction
Low-level game control — window focus, input sending, clipboard operations.
| Class | Purpose |
|-------|---------|
| GameController | Main facade — focus, chat, input, shortcuts |
| InputSender | Win32 SendInput (scan codes), Bézier mouse movement, Ctrl+click |
| WindowManager | SetForegroundWindow (with alt-key trick), GetWindowRect |
| ClipboardHelper | System clipboard read/write |
**Key operations:**
- `FocusWindow()` — SetForegroundWindow + alt-key trick (required for background processes)
- `CtrlRightClick()` — buying from seller stash
- `MoveMouse()` — Bézier curve smooth move
- `MoveMouseInstant()` — direct teleport (no interpolation)
- `TypeText()`, `SelectAll()`, `Paste()` — clipboard operations
**Used by**: Inventory, Trade, Items, Navigation, Bot
---
## Nexus.Log — Game Log Watcher
Parses Client.txt game log at 200ms poll intervals.
| Event | Pattern |
|-------|---------|
| AreaEntered | `[SCENE] Set Source [AreaName]` or `You have entered AreaName` |
| WhisperReceived | Incoming whisper messages |
| WhisperSent | Outgoing whisper messages |
| TradeAccepted | Trade completion |
| PartyJoined/Left | Party state changes |
| LineReceived | Raw log lines |
`CurrentArea` detected from log tail on startup. Used by Bot (reset navigation on area change), Inventory (wait for area transitions), Navigation.
---
## Nexus.Trade — Trade Daemon IPC
Manages trade search monitoring via external Node.js Playwright daemon.
### TradeDaemonBridge
Spawns `node tools/trade-daemon/daemon.mjs`, communicates via stdin/stdout JSON.
**Commands (→ daemon):**
- `start`, `addSearch`, `addDiamondSearch`
- `pauseSearch`, `clickTravel`
- `openScrapPage`, `reloadScrapPage`, `closeScrapPage`
**Events (← daemon):**
- `newListings``NewListings(searchId, items[])`
- `diamondListings``DiamondListings(searchId, pricedItems[])`
- `wsClose` → websocket disconnection
**Trade flow**: Website "Travel to Hideout" button → stash opens → Ctrl+right-click to buy → `/hideout` to go home → store items
---
## Nexus.Items — Item Parsing
Parse item text from clipboard (Ctrl+C) using Sidekick item parser library.
| Class | Purpose |
|-------|---------|
| ItemReader | Move to item → Ctrl+C → read clipboard → parse |
| SidekickBootstrapper | Initialize Sidekick parser on first use |
**Used by**: Bot (identify items during scraping)
---
## Nexus.Inventory — Stash & Grid Management
Scan player inventory, track item placement, deposit to stash.
| Class | Purpose |
|-------|---------|
| InventoryManager | Main interface — scan, deposit, clear |
| InventoryTracker | Cell occupancy matrix + item metadata |
| StashCalibrator | Grid boundary calibration via edge detection |
**Key operations:**
- `ScanInventory()` → screenshot + grid scan → populate tracker
- `DepositItemsToStash()` → find stash NPC → click items with Shift+Ctrl
- `DepositAllToOpenStash()` → scan → click first occupied → repeat
- `ClearToStash()` → scan → deposit all → return to hideout
- `EnsureAtOwnHideout()``/hideout` command if needed
**Grid calibration (2560×1440):**
- Cell sizes: 70×70px (12-col) or 35×35px (24-col), all 840px wide
- Inventory (12×5): origin (1696, 788)
- Stash 12×12: origin (23, 169) or (23, 216) in folder
---
## Nexus.Navigation — Minimap-Based Movement
Real-time navigation using minimap image matching + pathfinding. Separate from Nexus.Pathfinding (which is grid-based A*).
| Class | Purpose |
|-------|---------|
| NavigationExecutor | State machine: Capture → Process → Plan → Move → Stuck |
| MinimapCapture | Frame pipeline consumer — wall color detection, checkpoint detection |
| WorldMap | Position matching via cross-correlation, canvas stitching |
| StuckDetector | No-progress detection |
| WallColorTracker | Learns wall palette from initial spawn |
**Flow**: Capture minimap → detect position via wall color stitching → pathfind → send WASD keys
---
## Nexus.Bot — Top-Level Orchestration
Central coordinator that wires everything together.
| Class | Purpose |
|-------|---------|
| BotOrchestrator | DI container, state machine, frame pipeline management |
| TradeExecutor | Single trade flow (navigate → buy → deposit) |
| MappingExecutor | Map exploration (navigate + loot) |
| KulemakExecutor | Boss fight with arena mechanics |
| CraftingExecutor | Crafting bench operations |
| DiamondExecutor | Diamond trade handling |
| ScrapExecutor | Vendor scrapping |
| TradeQueue | FIFO queue of trade tasks |
| LinkManager | Trade search management |
**Bot modes**: Trading, Mapping, Crafting (via BotMode enum)
---
## Nexus.Ui — Avalonia Desktop Application
Entry point executable. Avalonia 11.2 + CommunityToolkit.MVVM + FluentTheme.
**App.xaml.cs** wires all DI:
- Services: ConfigStore, GameController, ScreenReader, ClientLogWatcher, TradeMonitor, InventoryManager
- Bot: FramePipelineService, LinkManager, TradeExecutor, TradeQueue, BotOrchestrator, ModPoolService
- ViewModels: Main, Debug, Settings, Mapping, Atlas, Crafting, Memory, Nexus, ObjectBrowser
**Additional dependencies**: Vortice.Direct2D1 (overlay rendering), Microsoft.Extensions.DependencyInjection
**Views**: MainWindow, DebugWindow, SettingsWindow, MappingWindow, etc. with MVVM bindings.

View file

@ -1,67 +0,0 @@
# Nexus.Input — Input Controllers & Humanization
## IInputController Implementations
### SendInputController (Default, No Driver)
Uses Win32 `SendInput` API with **KEYEVENTF_SCANCODE** flag. Games read hardware scan codes, not virtual key codes.
- **KeyDown/KeyUp**: Raw keyboard scan code via SendInput struct
- **KeyPress**: Down → Sleep(holdMs) → Up with humanization
- **SmoothMoveTo**: Cubic Bézier curve interpolation (10-40 steps) with random perpendicular spread
- **MouseMoveTo**: Direct `SetCursorPos()` (instant teleport)
- **Clicks**: Smooth move to target → humanized delay → click
### InterceptionInputController (Driver-Based)
Uses Interception keyboard/mouse driver for lower-level control:
- Delegates to `KeyboardHook` and `MouseHook` via InputInterceptor COM library
- Same smooth movement and humanization as SendInput
- Returns false from `Initialize()` if driver not installed (graceful fallback)
### SimInputController (Simulator)
Implements `IInputController` but doesn't make Win32 calls. Instead:
- **WASD** → Tracks held state, converts to direction vector with 45° isometric rotation
- **Skills** → Queues skill casts to SimWorld via `QueueSkill()`
- **Mouse** → Tracks screen position, converts to world coords via inverse camera matrix
- **Visualization** → Maintains flash timers (0.15s) for InputOverlayRenderer
## Scan Codes
```
Movement: W=0x11 A=0x1E S=0x1F D=0x20
Skills: Q=0x10 E=0x12 R=0x13 T=0x14
Numbers: 1=0x02 2=0x03 3=0x04 4=0x05 5=0x06
Modifiers: LShift=0x2A LCtrl=0x1D LAlt=0x38
Other: Space=0x39 Enter=0x1C Escape=0x01 Slash=0x35
```
## Humanizer
Anti-detection layer applied to all input operations.
| Method | Purpose |
|--------|---------|
| GaussianDelay(baseMs) | Adds gaussian noise (Box-Muller transform), clamped to [50ms, 150ms] |
| JitterPosition(x, y) | Random pixel offset within ClickJitterRadius (3px) |
| ShouldThrottle() | Tracks actions in 60-second rolling window, blocks if APM > MaxApm (250) |
| RecordAction() | Enqueues timestamp for APM tracking |
| RandomizedInterval(baseMs) | Adds ±20% jitter to poll intervals |
## MovementKeyTracker
Converts normalized direction vectors to WASD key state for isometric camera:
```
Rotate direction 45°:
sx = dir.X * cos(45°) - dir.Y * sin(45°)
sy = dir.X * sin(45°) + dir.Y * cos(45°)
Key mapping:
W if sy > 0.3, S if sy < -0.3
D if sx > 0.3, A if sx < -0.3
Delta-based: only sends KeyDown/KeyUp when state changes.
Supports holding multiple keys (W+D for diagonal).
```

View file

@ -1,153 +0,0 @@
# Nexus.Pathfinding — Navigation & Exploration
## Overview
Two classes: **NavigationController** (state machine — decides *where* to go) and **PathFinder** (A* algorithm — decides *how* to get there).
---
## NavigationController
### Modes
| Mode | Trigger | Behavior |
|------|---------|----------|
| Idle | `Stop()` | No movement |
| NavigatingToPosition | `NavigateTo(pos)` | Path to fixed world coordinates |
| NavigatingToEntity | `NavigateToEntity(id)` | Chase a moving entity (re-targets each tick) |
| Exploring | `Explore()` | BFS frontier exploration of unmapped terrain |
### Update Loop (called every tick)
```
1. Area change detection → clear path, explored grid, stuck history
2. EnsureExploredGrid() → allocate/resize to match terrain (preserves old data on expansion)
3. MarkExplored(playerPos) → mark cells near player as visited (radius 150 grid cells)
4. ResolveGoal() → get target position based on mode
5. If no goal and Exploring → PickExploreTarget() via BFS
6. Reach detection → within WaypointReachedDistance (80u), clear goal or stop
7. Stuck detection → if < 30u movement in 60 ticks (~1s), repath or pick new target
8. Pathfinding → A* from player to goal (with explored grid bias in explore mode)
9. Waypoint advancement → advance index as player reaches each waypoint
10. Output → DesiredDirection (normalized vector to next waypoint)
```
### Explored Grid
Parallel bool array matching terrain dimensions. Tracks which cells the player has visited.
- **Mark radius**: 150 grid cells (~1630 world units) — circular region around player
- **Preservation**: On terrain expansion, overlapping explored data is copied to new grid
- **Offset-aware**: Uses same OffsetX/OffsetY as terrain for absolute grid coordinates
### BFS Exploration (PickExploreTarget)
When Exploring mode needs a new goal:
1. **BFS frontier search** (up to 100,000 iterations)
- 8-directional BFS outward from player
- Finds nearest unexplored walkable cell
- Returns that cell as world coordinates
2. **Random distant target** (if BFS finds nothing)
- 20 attempts at random directions, 1500-3500 world units away
- Pushes player toward terrain edges where expansion triggers
3. **Edge fallback** (if random fails)
- Heads toward nearest terrain boundary (10 cells from edge)
- Guarantees continued exploration with infinite terrain
4. **Exploration complete** (only if all fallbacks fail)
- Sets `IsExplorationComplete = true`
- Prevents expensive re-BFS every tick
- Reset on area change
### Stuck Detection
- **Window**: Last 60 positions (~1 second at 60Hz)
- **Threshold**: Must move at least 30 world units in window
- **Grace period**: 120 ticks (2 seconds) after picking new explore target
- **On stuck while exploring**: Mark failed goal as explored, pick new target, set grace period
- **On stuck otherwise**: Repath
### Path Failure Handling
- **Explored bias fallback**: If A* with explored grid bias fails, retry without bias (bias can make distant targets unreachable)
- **Cooldown**: 3 seconds before retrying after path failure (prevents CPU burn on impossible paths)
---
## PathFinder — A* Implementation
### Signature
```csharp
public static List<Vector2>? FindPath(
WalkabilitySnapshot terrain, Vector2 start, Vector2 goal, float worldToGrid,
bool[]? exploredGrid, int exploredWidth, int exploredHeight,
int exploredOffsetX, int exploredOffsetY)
```
Returns world-coordinate waypoints or null if unreachable.
### Movement Model
- **8-directional grid**: Cardinal + diagonal
- **Costs**: Cardinal = 1.0, Diagonal = √2 ≈ 1.414
- **Explored penalty**: ×1.5 multiplier for explored cells (biases paths through unexplored territory)
### Heuristic
```
h = max(dx, dy) + 0.414 * min(dx, dy)
```
Diagonal/Chebyshev-based. Admissible and consistent.
### Algorithm
1. **Snap to walkable**: If start/goal in wall, BFS search for nearest walkable cell (radius up to 20)
2. **A* search** (budget: 200,000 iterations):
- Priority queue ordered by f = g + h
- 8 neighbors per expansion
- **Corner-cut check**: Diagonals require at least one adjacent cardinal cell walkable
- **Explored grid bias**: Multiply step cost by 1.5 for explored cells
- Track `bestNode` (closest reachable) for fallback
3. **Path reconstruction**: Backtrack via cameFrom map
4. **Simplification**: Remove collinear waypoints, keep only turning points
5. **Fallback**: If goal unreachable but bestNode is meaningfully closer (within 80% of starting heuristic), path to closest reachable cell
### Data Structures
| Structure | Type | Purpose |
|-----------|------|---------|
| Open set | PriorityQueue<(int,int), float> | Nodes to expand, ordered by f-score |
| Closed set | HashSet<(int,int)> | Already expanded nodes |
| gScore | Dictionary<(int,int), float> | Best known cost to each node |
| cameFrom | Dictionary<(int,int), (int,int)> | Backtracking map |
---
## Integration
```
AreaProgressionSystem
│ .Explore() / .NavigateTo() / .NavigateToEntity()
NavigationController
│ .Update(GameState) → computes path, sets DesiredDirection
│ calls PathFinder.FindPath() for A* routing
NavigationSystem
│ reads DesiredDirection → submits MoveAction
ActionQueue → BotEngine → MovementKeyTracker → WASD keys
```
### Coordinate Systems
| Space | Example | Conversion |
|-------|---------|------------|
| World | (1517, 4491) | Raw game units |
| Grid | (139, 413) | world × WorldToGrid (23/250) |
| Local grid | (139-ox, 413-oy) | grid - terrain offset |
| Screen | project via CameraMatrix | WorldToScreen.Project() |

View file

@ -1,180 +0,0 @@
# Nexus.Simulator — Standalone Game World
## Purpose
Test bot systems (combat, navigation, threat assessment) without the real game. Replaces the memory-reading pipeline with a procedural game world. Bot systems run unmodified — they see identical `GameState` objects and emit actions to `IInputController`.
## Architecture
```
SimWorld (game tick loop)
├── SimPoller (60Hz background thread)
│ ├── FlushToWorld() → transfer input to SimWorld
│ ├── Tick(dt) → advance simulation
│ ├── SimStateBuilder.Build() → SimWorld → GameState
│ └── Push to GameDataCache
├── SimInputController (captures bot actions)
│ ├── WASD → MoveDirection vector (45° isometric conversion)
│ ├── Skills → QueueSkill(scanCode, targetWorldPos)
│ ├── Mouse → track position, screen↔world conversion
│ └── Flash timers for input visualization
├── Bot Logic Thread (60Hz)
│ ├── GameStateEnricher.Enrich(state)
│ ├── All 6 systems: Threat, Movement, Navigation, Combat, Resource, Loot
│ ├── NavigationController.Update()
│ └── ExecuteActions() → SimInputController
└── Render Thread (ImGui + Veldrid)
├── TerrainRenderer (diamond cells, isometric)
├── EntityRenderer (player, enemies, health bars)
├── EffectRenderer (melee cones, AOE circles, projectile lines)
├── PathRenderer (A* waypoints)
├── InputOverlayRenderer (keyboard + mouse state)
└── DebugPanel (system toggles, stats, spawn controls)
```
## SimWorld — Game Loop
### Tick (dt-based, 60Hz)
```
1. CheckAndExpandTerrain() → expand when player within 50 cells of edge
2. MovePlayer(dt) → WASD direction × speed × dt, collision with terrain
3. ProcessSkills() → dequeue skill casts, dispatch by scan code
4. UpdateProjectiles(dt) → move, check terrain/enemy collisions
5. UpdateEffects(dt) → decay visual effects (0.3s duration)
6. UpdateEnemies(dt) → AI state machine per enemy
7. UpdateRespawns(dt) → cull far enemies, spawn new groups
```
### Terrain
- Procedural: all walkable with scattered obstacles (rock clusters, wall segments, pillars)
- 500×500 initial grid, `WorldToGrid = 23/250`
- **Infinite expansion**: Expands 250 cells per side when player within 50 cells of edge
- Preserves existing data via array copy with offset adjustment
### Player
- Position (Vector2), Health/Mana with regen (5 HP/s, 10 MP/s)
- Move speed: 400 world units/s
- Collision: slide-along-X / slide-along-Y fallback if direct move blocked
### Skills
| Scan Code | Type | Behavior |
|-----------|------|----------|
| Q (0x10), R (0x13) | AOE | Damage all enemies within 250u of target position |
| E (0x12), T (0x14) | Projectile | Spawn projectile, 1200 speed, 800 range, 80u hit radius |
| LMB, RMB | Melee | 150u cone, 120° angle from player toward target |
Base damage: 200 per hit. Configurable via SimConfig.
### Enemy AI
```
State machine per SimEnemy:
Idle → wander randomly within 200u of spawn, new target every 2-5s
│ player within 600u (aggro range)
Chasing → move toward player at 75% player speed
│ player within 100u (attack range)
Attacking → stand still, deal 30 damage every 1.5s
│ player escapes attack range
▼ back to Chasing
│ health ≤ 0
Dead → visible for 2s → queue for respawn (5s delay)
```
### Enemy Spawning
- **Groups**: 3-7 enemies per spawn, leader keeps rolled rarity, rest are Normal
- **Rarity distribution**: 70% Normal, 20% Magic, 8% Rare, 2% Unique
- **HP multipliers**: Magic=1.5×, Rare=3×, Unique=5× base (200)
- **Spawn ring**: 800-2000 world units from player
- **Direction bias**: ±90° cone ahead of player's movement direction
- **Culling**: Remove enemies > 3000u from player
- **Population**: Maintain 25 enemies, spawn new groups as needed
## Bridge Layer
### SimPoller
Replaces MemoryPoller. Background thread at 60Hz:
1. `FlushToWorld()` — transfer accumulated input
2. `world.Tick(dt)` — advance simulation (dt clamped to 0.1s max)
3. `SimStateBuilder.Build()` — convert to GameState
4. Push to GameDataCache (same fields as production)
### SimStateBuilder
Converts SimWorld state → GameState:
- Each SimEnemy → EntitySnapshot (with rarity, threat level, AI state, HP)
- SimPlayer → PlayerState (position, vitals, skills)
- Camera matrix: orthographic projection (12800×7200 world units → 2560×1440 screen)
### SimInputController
Implements IInputController, captures actions instead of sending Win32 input:
- WASD → direction vector (with 45° isometric inversion)
- Skills → `SimWorld.QueueSkill(scanCode, worldPos)`
- Mouse → screen position tracking, inverse camera transform for world coords
- Input visualization: flash timers for keyboard/mouse overlay
## Rendering
### ViewTransform (Isometric Camera)
45° counter-clockwise rotation matching the game's camera:
```
World → Grid: gx = worldX × WorldToGrid
Grid → Screen: rx = (gx - gy) × cos(45°)
ry = -(gx + gy) × cos(45°)
Screen = canvasOrigin + viewOffset + (rx, ry) × zoom
```
### Renderers
| Renderer | Draws |
|----------|-------|
| TerrainRenderer | Diamond cells (rotated grid), explored overlay, minimap |
| EntityRenderer | Player (green circle), enemies (colored by rarity), health/mana bars |
| EffectRenderer | Melee cones (red triangle fan), AOE circles (blue), projectile lines (cyan) |
| PathRenderer | Cyan waypoint lines and dots from A* path |
| InputOverlayRenderer | Keyboard (3 rows: 1-5, QWERT, ASDF) + mouse (L/R/M buttons) |
| DebugPanel | Pause/speed, player stats, enemy counts, system toggles, threat info |
### VeldridImGuiRenderer
Custom ImGui backend for Veldrid 4.9.0 + D3D11:
- HLSL shaders compiled at runtime via D3DCompiler P/Invoke
- Dynamic vertex/index buffers, font texture from ImGui atlas
- Alpha blending pipeline with scissor rect support
## SimConfig
```
Terrain: 500×500, WorldToGrid=23/250, ExpandThreshold=50, ExpandAmount=250
Player: Speed=400, HP=1000, MP=500, HPRegen=5/s, MPRegen=10/s
Enemies: Count=25, Aggro=600u, Attack=100u, Speed=75%, HP=200, Damage=30
Spawning: Ring=800-2000u, Groups=3-7, Cull=3000u
Skills: Melee=150u/120°, AOE=250u, Projectile=1200speed/800range, Damage=200
Rarity: Normal=70%, Magic=20%, Rare=8%, Unique=2%
Simulation: SpeedMultiplier=1×, Pauseable
```
## Running
```
dotnet run --project src/Nexus.Simulator
```
Dependencies: Core, Data, Systems, Pathfinding, ImGui.NET, Veldrid, Veldrid.StartupUtilities
Does NOT depend on: Memory, Input, Screen, Game, Bot, Ui, Trade

View file

@ -1,95 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hold Timer</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
min-height: 100vh;
margin: 0;
align-items: center;
justify-content: center;
background: #111;
color: #fff;
}
.wrap {
text-align: center;
}
button {
font-size: 24px;
padding: 30px 60px;
cursor: pointer;
border: none;
border-radius: 12px;
}
#result {
margin-top: 24px;
font-size: 32px;
}
#live {
margin-top: 12px;
font-size: 20px;
opacity: 0.85;
}
</style>
</head>
<body>
<div class="wrap">
<button id="btn">PRESS AND HOLD</button>
<div id="result">Last hold: 0 ms</div>
<div id="live">Current hold: 0 ms</div>
</div>
<script>
const btn = document.getElementById("btn");
const result = document.getElementById("result");
const live = document.getElementById("live");
let startTime = 0;
let holding = false;
let rafId = 0;
function updateLive() {
if (!holding) return;
const now = performance.now();
live.textContent = "Current hold: " + (now - startTime).toFixed(2) + " ms";
rafId = requestAnimationFrame(updateLive);
}
function startHold() {
if (holding) return;
holding = true;
startTime = performance.now();
updateLive();
}
function endHold() {
if (!holding) return;
holding = false;
cancelAnimationFrame(rafId);
const duration = performance.now() - startTime;
result.textContent = "Last hold: " + duration.toFixed(2) + " ms";
live.textContent = "Current hold: 0 ms";
}
btn.addEventListener("mousedown", startHold);
btn.addEventListener("mouseup", endHold);
btn.addEventListener("mouseleave", endHold);
btn.addEventListener("touchstart", (e) => {
e.preventDefault();
startHold();
}, { passive: false });
btn.addEventListener("touchend", endHold);
btn.addEventListener("touchcancel", endHold);
</script>
</body>
</html>

View file

@ -1,15 +0,0 @@
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Simulator Controls]
Pos=29,51
Size=432,649
Collapsed=0
[Window][Simulator]
Pos=564,96
Size=1023,810
Collapsed=0

View file

@ -1,11 +1,11 @@
using Nexus.Core;
using Nexus.Game;
using Nexus.Inventory;
using Nexus.Navigation;
using Nexus.Screen;
using Automata.Core;
using Automata.Game;
using Automata.Inventory;
using Automata.Navigation;
using Automata.Screen;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
/// <summary>
/// Captures the full endgame atlas as a panorama image.

View file

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Automata.Core\Automata.Core.csproj" />
<ProjectReference Include="..\Automata.Game\Automata.Game.csproj" />
<ProjectReference Include="..\Automata.Screen\Automata.Screen.csproj" />
<ProjectReference Include="..\Automata.Trade\Automata.Trade.csproj" />
<ProjectReference Include="..\Automata.Log\Automata.Log.csproj" />
<ProjectReference Include="..\Automata.Inventory\Automata.Inventory.csproj" />
<ProjectReference Include="..\Automata.Navigation\Automata.Navigation.csproj" />
<ProjectReference Include="..\Automata.Items\Automata.Items.csproj" />
</ItemGroup>
</Project>

View file

@ -1,13 +1,13 @@
using Nexus.Core;
using Nexus.Game;
using Nexus.Inventory;
using Nexus.GameLog;
using Nexus.Navigation;
using Nexus.Screen;
using Nexus.Trade;
using Automata.Core;
using Automata.Game;
using Automata.Inventory;
using Automata.GameLog;
using Automata.Navigation;
using Automata.Screen;
using Automata.Trade;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
public class BotStatus
{

View file

@ -1,10 +1,10 @@
using System.Diagnostics;
using Nexus.Core;
using Nexus.Game;
using Nexus.Screen;
using Automata.Core;
using Automata.Game;
using Automata.Screen;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
/// <summary>
/// Manages the attack state machine (click → hold) with mana monitoring and flask usage.

View file

@ -1,9 +1,9 @@
using Nexus.Core;
using Nexus.Game;
using Nexus.Items;
using Automata.Core;
using Automata.Game;
using Automata.Items;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
public class CraftingExecutor
{

View file

@ -1,12 +1,12 @@
using System.Collections.Concurrent;
using Nexus.Core;
using Nexus.Game;
using Nexus.Inventory;
using Nexus.Screen;
using Nexus.Trade;
using Automata.Core;
using Automata.Game;
using Automata.Inventory;
using Automata.Screen;
using Automata.Trade;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
public class DiamondExecutor
{

View file

@ -1,9 +1,9 @@
using System.Diagnostics;
using Nexus.Game;
using Nexus.Screen;
using Automata.Game;
using Automata.Screen;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
/// <summary>
/// Monitors life/mana and presses flask keys when they drop below thresholds.

View file

@ -1,11 +1,11 @@
using System.Diagnostics;
using Nexus.Core;
using Nexus.Game;
using Nexus.Inventory;
using Nexus.Screen;
using Automata.Core;
using Automata.Game;
using Automata.Inventory;
using Automata.Screen;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
/// <summary>
/// Base class for game executors that interact with the game world.

View file

@ -1,12 +1,12 @@
using Nexus.Core;
using Nexus.Game;
using Nexus.GameLog;
using Nexus.Inventory;
using Nexus.Navigation;
using Nexus.Screen;
using Automata.Core;
using Automata.Game;
using Automata.GameLog;
using Automata.Inventory;
using Automata.Navigation;
using Automata.Screen;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
/// <summary>
/// Kulemak-specific boss run executor: scripted 4-phase + ring fight,

View file

@ -1,13 +1,13 @@
using System.Diagnostics;
using Nexus.Core;
using Nexus.Game;
using Nexus.GameLog;
using Nexus.Inventory;
using Nexus.Navigation;
using Nexus.Screen;
using Automata.Core;
using Automata.Game;
using Automata.GameLog;
using Automata.Inventory;
using Automata.Navigation;
using Automata.Screen;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
/// <summary>
/// Shared infrastructure for any map/boss activity: combat loop, WASD navigation,

View file

@ -1,11 +1,11 @@
using Nexus.Core;
using Nexus.Game;
using Nexus.Inventory;
using Nexus.Screen;
using Nexus.Trade;
using Automata.Core;
using Automata.Game;
using Automata.Inventory;
using Automata.Screen;
using Automata.Trade;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
public class ScrapExecutor
{

View file

@ -1,11 +1,11 @@
using Nexus.Core;
using Nexus.Game;
using Nexus.Inventory;
using Nexus.Screen;
using Nexus.Trade;
using Automata.Core;
using Automata.Game;
using Automata.Inventory;
using Automata.Screen;
using Automata.Trade;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
public class TradeExecutor
{

View file

@ -1,7 +1,7 @@
using Nexus.Core;
using Automata.Core;
using Serilog;
namespace Nexus.Bot;
namespace Automata.Bot;
public class TradeQueue
{

View file

@ -8,6 +8,6 @@
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>
</Project>

View file

@ -2,7 +2,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using Serilog;
namespace Nexus.Core;
namespace Automata.Core;
public class SavedLink
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Core;
namespace Automata.Core;
public static class Delays
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Core;
namespace Automata.Core;
public static class Helpers
{

View file

@ -1,6 +1,6 @@
using Serilog;
namespace Nexus.Core;
namespace Automata.Core;
public class TradeLink
{

View file

@ -1,14 +1,14 @@
using Serilog;
using Serilog.Events;
namespace Nexus.Core;
namespace Automata.Core;
public static class Logging
{
public static void Setup()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Information()
.WriteTo.Console(
outputTemplate: "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.WriteTo.File("logs/poe2trade-.log",

View file

@ -2,7 +2,7 @@ using System.Net.Http;
using System.Text.Json;
using Serilog;
namespace Nexus.Core;
namespace Automata.Core;
public class ModPoolService
{

View file

@ -1,7 +1,7 @@
using System.Text.Json;
using Serilog;
namespace Nexus.Core;
namespace Automata.Core;
public static class Poe2ScoutClient
{

View file

@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace Nexus.Core;
namespace Automata.Core;
public class RePoEMod
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Core;
namespace Automata.Core;
public class StashTabInfo
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Core;
namespace Automata.Core;
public record Region(int X, int Y, int Width, int Height);

View file

@ -6,6 +6,6 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Nexus.Core\Nexus.Core.csproj" />
<ProjectReference Include="..\Automata.Core\Automata.Core.csproj" />
</ItemGroup>
</Project>

View file

@ -1,7 +1,7 @@
using System.Runtime.InteropServices;
using System.Text;
namespace Nexus.Game;
namespace Automata.Game;
/// <summary>
/// Win32 clipboard access without WinForms dependency.

View file

@ -1,7 +1,7 @@
using Nexus.Core;
using Automata.Core;
using Serilog;
namespace Nexus.Game;
namespace Automata.Game;
public class GameController : IGameController
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Game;
namespace Automata.Game;
public interface IGameController
{

View file

@ -1,7 +1,7 @@
using System.Runtime.InteropServices;
using Nexus.Core;
using Automata.Core;
namespace Nexus.Game;
namespace Automata.Game;
public class InputSender
{

View file

@ -1,7 +1,7 @@
using System.Runtime.InteropServices;
using Serilog;
namespace Nexus.Game;
namespace Automata.Game;
public class WindowManager
{

View file

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Automata.Core\Automata.Core.csproj" />
<ProjectReference Include="..\Automata.Game\Automata.Game.csproj" />
<ProjectReference Include="..\Automata.Screen\Automata.Screen.csproj" />
<ProjectReference Include="..\Automata.Log\Automata.Log.csproj" />
</ItemGroup>
</Project>

View file

@ -1,7 +1,7 @@
using Nexus.Core;
using Nexus.Screen;
using Automata.Core;
using Automata.Screen;
namespace Nexus.Inventory;
namespace Automata.Inventory;
public interface IInventoryManager
{

View file

@ -1,10 +1,10 @@
using Nexus.Core;
using Nexus.Game;
using Nexus.GameLog;
using Nexus.Screen;
using Automata.Core;
using Automata.Game;
using Automata.GameLog;
using Automata.Screen;
using Serilog;
namespace Nexus.Inventory;
namespace Automata.Inventory;
public class InventoryManager : IInventoryManager
{

View file

@ -1,8 +1,8 @@
using Nexus.Core;
using Nexus.Screen;
using Automata.Core;
using Automata.Screen;
using Serilog;
namespace Nexus.Inventory;
namespace Automata.Inventory;
public class PlacedItem
{

View file

@ -1,9 +1,9 @@
using Nexus.Core;
using Nexus.Game;
using Nexus.Screen;
using Automata.Core;
using Automata.Game;
using Automata.Screen;
using Serilog;
namespace Nexus.Inventory;
namespace Automata.Inventory;
public class StashCalibrator
{

View file

@ -5,8 +5,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Nexus.Core\Nexus.Core.csproj" />
<ProjectReference Include="..\Nexus.Game\Nexus.Game.csproj" />
<ProjectReference Include="..\Automata.Core\Automata.Core.csproj" />
<ProjectReference Include="..\Automata.Game\Automata.Game.csproj" />
<ProjectReference Include="..\..\lib\Sidekick\src\Sidekick.Apis.Poe.Trade\Sidekick.Apis.Poe.Trade.csproj" />
<ProjectReference Include="..\..\lib\Sidekick\src\Sidekick.Apis.Poe\Sidekick.Apis.Poe.csproj" />
</ItemGroup>

View file

@ -1,10 +1,10 @@
using Nexus.Core;
using Nexus.Game;
using Automata.Core;
using Automata.Game;
using Sidekick.Apis.Poe.Items;
using Sidekick.Apis.Poe.Trade.Parser;
using Serilog;
namespace Nexus.Items;
namespace Automata.Items;
/// <summary>
/// Reads item data by hovering and pressing Ctrl+C to copy item text to clipboard.

View file

@ -9,7 +9,7 @@ using Sidekick.Common.Settings;
using Sidekick.Data;
using Serilog;
namespace Nexus.Items;
namespace Automata.Items;
/// <summary>
/// Bootstraps a minimal Sidekick DI container for item parsing.

View file

@ -1,6 +1,6 @@
using Sidekick.Common.Settings;
namespace Nexus.Items;
namespace Automata.Items;
/// <summary>
/// Minimal ISettingsService returning defaults for Sidekick initialization.

View file

@ -1,10 +1,10 @@
using System.Diagnostics;
using OpenCvSharp;
using Nexus.Core;
using Nexus.Screen;
using Automata.Core;
using Automata.Screen;
using Serilog;
namespace Nexus.Navigation;
namespace Automata.Navigation;
public record AtlasProgress(int TilesCaptured, int Row, string Phase);

View file

@ -12,8 +12,8 @@
<PackageReference Include="System.Drawing.Common" Version="8.0.12" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Nexus.Core\Nexus.Core.csproj" />
<ProjectReference Include="..\Nexus.Game\Nexus.Game.csproj" />
<ProjectReference Include="..\Nexus.Screen\Nexus.Screen.csproj" />
<ProjectReference Include="..\Automata.Core\Automata.Core.csproj" />
<ProjectReference Include="..\Automata.Game\Automata.Game.csproj" />
<ProjectReference Include="..\Automata.Screen\Automata.Screen.csproj" />
</ItemGroup>
</Project>

View file

@ -1,7 +1,7 @@
using OpenCvSharp;
using Serilog;
namespace Nexus.Navigation;
namespace Automata.Navigation;
/// <summary>
/// Detects minimap icons (doors, checkpoints) via template matching.

View file

@ -1,10 +1,10 @@
using OpenCvSharp;
using Nexus.Screen;
using Automata.Screen;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
using Size = OpenCvSharp.Size;
namespace Nexus.Navigation;
namespace Automata.Navigation;
public class MinimapCapture : IFrameConsumer, IDisposable
{

View file

@ -1,11 +1,11 @@
using System.Diagnostics;
using OpenCvSharp;
using Nexus.Core;
using Nexus.Game;
using Nexus.Screen;
using Automata.Core;
using Automata.Game;
using Automata.Screen;
using Serilog;
namespace Nexus.Navigation;
namespace Automata.Navigation;
public class NavigationExecutor : IDisposable
{

View file

@ -1,7 +1,7 @@
using Nexus.Core;
using Automata.Core;
using OpenCvSharp;
namespace Nexus.Navigation;
namespace Automata.Navigation;
public enum MinimapMode
{

View file

@ -1,7 +1,7 @@
using OpenCvSharp;
using Serilog;
namespace Nexus.Navigation;
namespace Automata.Navigation;
/// <summary>
/// Last BFS result for visualization.

View file

@ -1,9 +1,9 @@
using OpenCvSharp;
using Nexus.Core;
using Nexus.Screen;
using Automata.Core;
using Automata.Screen;
using Serilog;
namespace Nexus.Navigation;
namespace Automata.Navigation;
public record CalibrationResult(float BestFactor, double BestConfidence, Dictionary<float, double> AllResults);

View file

@ -1,4 +1,4 @@
namespace Nexus.Navigation;
namespace Automata.Navigation;
/// <summary>
/// Detects when the player hasn't moved significantly over a window of frames.

View file

@ -1,7 +1,7 @@
using OpenCvSharp;
using Serilog;
namespace Nexus.Navigation;
namespace Automata.Navigation;
/// <summary>
/// Tracks HSV distribution of confirmed wall pixels and computes an adaptive

View file

@ -2,7 +2,7 @@ using System.Diagnostics;
using OpenCvSharp;
using Serilog;
namespace Nexus.Navigation;
namespace Automata.Navigation;
public class WorldMap : IDisposable
{

View file

@ -15,6 +15,6 @@
<PackageReference Include="Vortice.DXGI" Version="3.8.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Nexus.Core\Nexus.Core.csproj" />
<ProjectReference Include="..\Automata.Core\Automata.Core.csproj" />
</ItemGroup>
</Project>

View file

@ -1,8 +1,8 @@
using OpenCvSharp;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
namespace Nexus.Screen;
namespace Automata.Screen;
/// <summary>
/// Detects bosses using YOLO running on a background thread.

View file

@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace Nexus.Screen;
namespace Automata.Screen;
public class OcrWord
{
@ -49,7 +49,7 @@ public class DiffOcrResponse
{
public string Text { get; set; } = "";
public List<OcrLine> Lines { get; set; } = [];
public Nexus.Core.Region? Region { get; set; }
public Automata.Core.Region? Region { get; set; }
}
public class TemplateMatchResult

View file

@ -5,9 +5,9 @@ using SharpGen.Runtime;
using Vortice.Direct3D;
using Vortice.Direct3D11;
using Vortice.DXGI;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
namespace Nexus.Screen;
namespace Automata.Screen;
public sealed class DesktopDuplication : IScreenCapture
{

View file

@ -1,10 +1,10 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
class DetectGridHandler
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
public record DetectedEnemy(
float Confidence,

View file

@ -1,10 +1,10 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
class DiffCropHandler
{

View file

@ -1,10 +1,10 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
class EdgeCropHandler
{

View file

@ -1,9 +1,9 @@
using OpenCvSharp;
using Nexus.Core;
using Automata.Core;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
namespace Nexus.Screen;
namespace Automata.Screen;
/// <summary>
/// Detects enemies on screen using two-stage approach:

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
public class FramePipeline : IDisposable
{

View file

@ -1,6 +1,6 @@
using Serilog;
namespace Nexus.Screen;
namespace Automata.Screen;
public class FramePipelineService : IDisposable
{

View file

@ -1,8 +1,8 @@
using OpenCvSharp;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
namespace Nexus.Screen;
namespace Automata.Screen;
/// <summary>
/// Saves full-screen frames as JPEGs for YOLO training data collection.

View file

@ -1,7 +1,7 @@
using Nexus.Core;
using Automata.Core;
using Serilog;
namespace Nexus.Screen;
namespace Automata.Screen;
/// <summary>
/// Classifies the current game UI state by probing known pixel positions on each frame.

View file

@ -3,9 +3,9 @@ using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
namespace Nexus.Screen;
namespace Automata.Screen;
public sealed class GdiCapture : IScreenCapture
{

View file

@ -1,8 +1,8 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Drawing;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
public class GridHandler
{

View file

@ -1,7 +1,7 @@
using Nexus.Core;
using Automata.Core;
using Serilog;
namespace Nexus.Screen;
namespace Automata.Screen;
public class GridLayout
{

View file

@ -1,9 +1,9 @@
using OpenCvSharp;
using Nexus.Core;
using Automata.Core;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
namespace Nexus.Screen;
namespace Automata.Screen;
public record HudSnapshot
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
public interface IFrameConsumer
{

View file

@ -1,6 +1,6 @@
using System.Drawing;
namespace Nexus.Screen;
namespace Automata.Screen;
public interface IOcrEngine : IDisposable
{

View file

@ -1,7 +1,7 @@
using OpenCvSharp;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
namespace Nexus.Screen;
namespace Automata.Screen;
public interface IScreenCapture : IDisposable
{

View file

@ -1,6 +1,6 @@
using Nexus.Core;
using Automata.Core;
namespace Nexus.Screen;
namespace Automata.Screen;
public interface IScreenReader : IDisposable
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Drawing;
using OpenCvSharp;

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Drawing;
using System.Drawing.Imaging;

View file

@ -1,6 +1,6 @@
using Serilog;
namespace Nexus.Screen;
namespace Automata.Screen;
/// <summary>
/// Debug-only: periodically captures the screen, runs loot label detection,

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
/// <summary>
/// A detected loot label on screen with its position and classified tier.

View file

@ -1,6 +1,6 @@
using System.Drawing;
namespace Nexus.Screen.Ocr;
namespace Automata.Screen.Ocr;
/// <summary>
/// OCR engine wrapping the Python EasyOCR daemon.

View file

@ -1,6 +1,6 @@
using Serilog;
namespace Nexus.Screen.Ocr;
namespace Automata.Screen.Ocr;
public static class OcrEngineFactory
{

View file

@ -3,7 +3,7 @@ using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Serilog;
namespace Nexus.Screen.Ocr;
namespace Automata.Screen.Ocr;
/// <summary>
/// OCR engine using OneOCR (Windows 11 Snipping Tool's built-in engine).

View file

@ -7,7 +7,7 @@ using Windows.Storage.Streams;
using BitmapDecoder = Windows.Graphics.Imaging.BitmapDecoder;
using SdImageFormat = System.Drawing.Imaging.ImageFormat;
namespace Nexus.Screen.Ocr;
namespace Automata.Screen.Ocr;
public sealed class WinOcrEngine : IOcrEngine
{

View file

@ -5,7 +5,7 @@ using OpenCvSharp;
using OpenCvSharp.Dnn;
using Serilog;
namespace Nexus.Screen;
namespace Automata.Screen;
/// <summary>
/// YOLO11 object detection via ONNX Runtime with CUDA GPU acceleration.

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Diagnostics;
using System.Text.Json;

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Diagnostics;
using System.Drawing;

View file

@ -1,9 +1,9 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
static class ScreenCapture
{

View file

@ -1,7 +1,7 @@
using OpenCvSharp;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
namespace Nexus.Screen;
namespace Automata.Screen;
public class ScreenFrame : IDisposable
{

View file

@ -3,12 +3,12 @@ using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using Nexus.Core;
using Automata.Core;
using Serilog;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
using Size = OpenCvSharp.Size;
namespace Nexus.Screen;
namespace Automata.Screen;
public class ScreenReader : IScreenReader
{

View file

@ -1,4 +1,4 @@
namespace Nexus.Screen;
namespace Automata.Screen;
static class SignalProcessing
{

View file

@ -1,9 +1,9 @@
namespace Nexus.Screen;
namespace Automata.Screen;
using System.Drawing;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using Region = Nexus.Core.Region;
using Region = Automata.Core.Region;
class TemplateMatchHandler
{

View file

@ -5,6 +5,6 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Nexus.Core\Nexus.Core.csproj" />
<ProjectReference Include="..\Automata.Core\Automata.Core.csproj" />
</ItemGroup>
</Project>

View file

@ -1,6 +1,6 @@
using Nexus.Core;
using Automata.Core;
namespace Nexus.Trade;
namespace Automata.Trade;
public interface ITradeMonitor : IAsyncDisposable
{

Some files were not shown because too many files have changed in this diff Show more