├── Resources
├── Icon1.ico
└── Icon2.ico
├── Settings
├── Shape.cs
├── MapPosition.cs
├── PointOfInterestRendering.cs
├── Utils.cs
└── Settings.cs
├── Structs
├── RoomEx.cs
├── UiSettings.cs
├── Level.cs
├── Act.cs
├── UnitHashTable.cs
├── ActMisc.cs
├── Path.cs
├── Room.cs
├── Monster.cs
└── UnitAny.cs
├── MapAssist.sln
├── Types
├── PointOfInterest.cs
├── Difficulty.cs
├── Offsets.cs
├── AreaData.cs
├── GameData.cs
├── RawAreaData.cs
├── Area.cs
├── Stats.cs
└── GameObject.cs
├── .github
└── workflows
│ ├── msbuild.yml
│ ├── release.yml
│ └── nightly.yml
├── Helpers
├── Extensions.cs
├── WindowsExternal.cs
├── MapApi.cs
├── PointOfInterestHandler.cs
├── ImageUtils.cs
├── Compositor.cs
└── GameMemory.cs
├── README.md
├── Program.cs
├── Properties
└── AssemblyInfo.cs
├── Overlay.Designer.cs
├── .gitignore
├── App.config
├── MapAssist.csproj
├── .editorconfig
└── Overlay.cs
/Resources/Icon1.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RushTheOne/MapAssist/HEAD/Resources/Icon1.ico
--------------------------------------------------------------------------------
/Resources/Icon2.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RushTheOne/MapAssist/HEAD/Resources/Icon2.ico
--------------------------------------------------------------------------------
/Settings/Shape.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | namespace MapAssist.Settings
21 | {
22 | public enum Shape
23 | {
24 | None,
25 | Rectangle,
26 | Ellipse
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Settings/MapPosition.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | namespace MapAssist.Settings
21 | {
22 | public enum MapPosition
23 | {
24 | TopLeft,
25 | TopRight,
26 | Center
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Structs/RoomEx.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Runtime.InteropServices;
21 |
22 | namespace MapAssist.Structs
23 | {
24 | [StructLayout(LayoutKind.Explicit)]
25 | unsafe public struct RoomEx
26 | {
27 | [FieldOffset(0x90)] public Level* pLevel;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Structs/UiSettings.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Runtime.InteropServices;
21 |
22 | namespace MapAssist.Structs
23 | {
24 | [StructLayout(LayoutKind.Explicit)]
25 | unsafe public struct UiSettings
26 | {
27 | [FieldOffset(0x00)] public byte MapShown;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Structs/Level.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Runtime.InteropServices;
21 | using MapAssist.Types;
22 |
23 | namespace MapAssist.Structs
24 | {
25 | [StructLayout(LayoutKind.Explicit)]
26 | unsafe public struct Level
27 | {
28 | [FieldOffset(0x1F8)] public Area LevelId;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/MapAssist.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31727.386
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapAssist", "MapAssist.csproj", "{FB3AC437-B7BB-42FF-A2A2-F10551F95F6C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {FB3AC437-B7BB-42FF-A2A2-F10551F95F6C}.Debug|x64.ActiveCfg = Debug|x64
15 | {FB3AC437-B7BB-42FF-A2A2-F10551F95F6C}.Debug|x64.Build.0 = Debug|x64
16 | {FB3AC437-B7BB-42FF-A2A2-F10551F95F6C}.Release|x64.ActiveCfg = Release|x64
17 | {FB3AC437-B7BB-42FF-A2A2-F10551F95F6C}.Release|x64.Build.0 = Release|x64
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {F3FD903D-7D06-41F3-BEE3-6AEF2D88C726}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Types/PointOfInterest.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Drawing;
21 | using MapAssist.Settings;
22 |
23 | namespace MapAssist.Types
24 | {
25 | public class PointOfInterest
26 | {
27 | public string Label;
28 | public Point Position;
29 | public PointOfInterestRendering RenderingSettings;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Structs/Act.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Runtime.InteropServices;
21 |
22 | namespace MapAssist.Structs
23 | {
24 | [StructLayout(LayoutKind.Explicit)]
25 | unsafe public struct Act
26 | {
27 | [FieldOffset(0x14)] public uint MapSeed;
28 | [FieldOffset(0x20)] public uint ActId;
29 | [FieldOffset(0x70)] public ActMisc* ActMisc;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.github/workflows/msbuild.yml:
--------------------------------------------------------------------------------
1 | name: MSBuild
2 |
3 | on: [push]
4 |
5 | env:
6 | # Path to the solution file relative to the root of the project.
7 | SOLUTION_FILE_PATH: .
8 |
9 | # Configuration type to build.
10 | # You can convert this to a build matrix if you need coverage of multiple configuration types.
11 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
12 | BUILD_CONFIGURATION: Release
13 |
14 | jobs:
15 | build:
16 | runs-on: windows-latest
17 |
18 | steps:
19 | - uses: actions/checkout@v2
20 |
21 | - name: Add MSBuild to PATH
22 | uses: microsoft/setup-msbuild@v1.0.2
23 |
24 | - name: Restore NuGet packages
25 | working-directory: ${{env.GITHUB_WORKSPACE}}
26 | run: nuget restore ${{env.SOLUTION_FILE_PATH}}
27 |
28 | - name: Build
29 | working-directory: ${{env.GITHUB_WORKSPACE}}
30 | # Add additional options to the MSBuild command line here (like platform or verbosity level).
31 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
32 | run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}}
33 |
--------------------------------------------------------------------------------
/Structs/UnitHashTable.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Runtime.InteropServices;
22 |
23 | namespace MapAssist.Structs
24 | {
25 | [StructLayout(LayoutKind.Explicit)]
26 | unsafe public struct UnitHashTable
27 | {
28 | [FieldOffset(0x00)]
29 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
30 | public IntPtr[] UnitTable;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Structs/ActMisc.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Runtime.InteropServices;
21 | using MapAssist.Types;
22 |
23 | namespace MapAssist.Structs
24 | {
25 | [StructLayout(LayoutKind.Explicit)]
26 | unsafe public struct ActMisc
27 | {
28 | [FieldOffset(0x830)] public Difficulty GameDifficulty;
29 | [FieldOffset(0x858)] public Act* pAct;
30 | [FieldOffset(0x868)] public Level* pLevelFirst;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Structs/Path.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Runtime.InteropServices;
21 |
22 | namespace MapAssist.Structs
23 | {
24 | [StructLayout(LayoutKind.Explicit)]
25 | unsafe public struct Path
26 | {
27 | [FieldOffset(0x02)] public ushort DynamicX;
28 | [FieldOffset(0x06)] public ushort DynamicY;
29 | [FieldOffset(0x10)] public ushort StaticX;
30 | [FieldOffset(0x14)] public ushort StaticY;
31 | [FieldOffset(0x20)] public Room* pRoom;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Helpers/Extensions.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo, OneXDeveloper
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Drawing;
21 | using MapAssist.Types;
22 |
23 | namespace MapAssist.Helpers
24 | {
25 | public static class Extensions
26 | {
27 | public static bool IsWaypoint(this GameObject obj) => obj.ToString().Contains("Waypoint");
28 |
29 | public static Point OffsetFrom(this Point point, Point offset)
30 | {
31 | return new Point(point.X - offset.X, point.Y - offset.Y);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Types/Difficulty.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | namespace MapAssist.Types
21 | {
22 | public enum Difficulty : ushort
23 | {
24 | None = 99,
25 | Normal = 0,
26 | Nightmare = 1,
27 | Hell = 2
28 | }
29 |
30 | public static class DifficultyExtension
31 | {
32 | public static bool IsValid(this Difficulty difficulty)
33 | {
34 | return (ushort)difficulty >= 0 && (ushort)difficulty <= 2;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Types/Offsets.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 | using System;
20 | using System.Configuration;
21 |
22 | namespace MapAssist.Types
23 | {
24 | public static class Offsets
25 | {
26 | public static int UnitHashTable = Convert.ToInt32(ConfigurationManager.AppSettings["UnitHashTable"], 16);
27 | public static int UiSettings = Convert.ToInt32(ConfigurationManager.AppSettings["UiSettings"], 16);
28 | public static int ExpansionCheck = Convert.ToInt32(ConfigurationManager.AppSettings["ExpansionCheck"], 16);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Structs/Room.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Runtime.InteropServices;
21 |
22 | namespace MapAssist.Structs
23 | {
24 | [StructLayout(LayoutKind.Explicit)]
25 | unsafe public struct Room
26 | {
27 | [FieldOffset(0x00)] public Room** pRoomsNear;
28 | [FieldOffset(0x18)] public RoomEx* pRoomEx;
29 | [FieldOffset(0x40)] public uint numRoomsNear;
30 | [FieldOffset(0x48)] public Act* pAct;
31 | [FieldOffset(0xA8)] public UnitAny* pUnitFirst;
32 | [FieldOffset(0xB0)] public Room* pRoomNext;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Discord server down? Try this new invite link
2 |
3 | https://discord.gg/2ehpxyS3YZ
4 |
5 | # MapAssist
6 |
7 |
8 | THE 'MapAssist' TOOL AND CONTENTS THEREIN WERE INTENDED FOR INFORMATIONAL AND LEARNING PURPOSES ONLY.
9 |
10 | Join the discussion: https://discord.gg/5b2B7QrVqa
11 |
12 | Feel free to contribute a pull request with new features or fixes, the code is under GPL so make sure to please follow the license.
13 |
14 | The software is free and open source licensed under the GPLv3. You may download a copy of the source code and follow the instructions to build the software for yourself. In certain instances there may be direct links to precompiled versions of the software, you are free to use these as well. The best place to start looking is inside of the repository.
15 |
16 | Use at your own risk! The MapAssist team makes no expression of warranty or claim about the safety in regards to the usage of this program. We have done our best to provide an open project for learning and educational purposes only. The contents of the official source code are known to not contain any malicious or disingenuous code. If you have additional information in regards to the safety of this program please do not hesitate to raise a concern.
17 |
18 | All software projects are subject to their own licensing, and copyrights. All other product names and any registered and unregistered trademarks mentioned are used for identification purposes only and remain the exclusive property of their respective owners.
19 |
--------------------------------------------------------------------------------
/Types/AreaData.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Collections.Generic;
21 | using System.Drawing;
22 |
23 | namespace MapAssist.Types
24 | {
25 | public class AdjacentLevel
26 | {
27 | public Area Area;
28 | public Point[] Exits;
29 | public Point Origin;
30 | public int Width;
31 | public int Height;
32 | }
33 |
34 | public class AreaData
35 | {
36 | public Area Area;
37 | public Point Origin;
38 | public Dictionary AdjacentLevels;
39 | public int[][] CollisionGrid;
40 | public Dictionary NPCs;
41 | public Dictionary Objects;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Windows.Forms;
22 | using Gma.System.MouseKeyHook;
23 |
24 | namespace MapAssist
25 | {
26 | static class Program
27 | {
28 | ///
29 | /// The main entry point for the application.
30 | ///
31 | [STAThread]
32 | static void Main()
33 | {
34 | using (IKeyboardMouseEvents globalHook = Hook.GlobalEvents())
35 | {
36 | Application.EnableVisualStyles();
37 | Application.SetCompatibleTextRenderingDefault(false);
38 | Application.Run(new Overlay(globalHook));
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - "main"
7 | workflow_dispatch:
8 |
9 | env:
10 | # Path to the solution file relative to the root of the project.
11 | SOLUTION_FILE_PATH: .
12 |
13 | # Configuration type to build.
14 | # You can convert this to a build matrix if you need coverage of multiple configuration types.
15 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
16 | BUILD_CONFIGURATION: Release
17 |
18 | jobs:
19 | tagged-release:
20 | name: "Tagged Release"
21 | runs-on: windows-latest
22 |
23 | steps:
24 | - uses: actions/checkout@v2
25 |
26 | - name: Add MSBuild to PATH
27 | uses: microsoft/setup-msbuild@v1.0.2
28 |
29 | - name: Restore NuGet packages
30 | working-directory: ${{env.GITHUB_WORKSPACE}}
31 | run: nuget restore ${{env.SOLUTION_FILE_PATH}}
32 |
33 | - name: Build
34 | working-directory: ${{env.GITHUB_WORKSPACE}}
35 | # Add additional options to the MSBuild command line here (like platform or verbosity level).
36 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
37 | run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} /p:DebugSymbols=false
38 |
39 | - name: Zip release
40 | uses: papeloto/action-zip@v1
41 | with:
42 | files: bin/x64/Release/ LICENSE README.md
43 | recursive: true
44 | dest: MapAssist.zip
45 |
46 | - name: Publish release
47 | uses: "marvinpinto/action-automatic-releases@latest"
48 | with:
49 | repo_token: "${{ secrets.GITHUB_TOKEN }}"
50 | automatic_release_tag: "latest"
51 | prerelease: false
52 | files: |
53 | LICENSE
54 | README.md
55 | MapAssist.zip
56 |
--------------------------------------------------------------------------------
/Types/GameData.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Drawing;
22 |
23 | namespace MapAssist.Types
24 | {
25 | public class GameData
26 | {
27 | public Point PlayerPosition;
28 | public uint MapSeed;
29 | public Difficulty Difficulty;
30 | public Area Area;
31 | public bool MapShown;
32 | public IntPtr MainWindowHandle;
33 | public string PlayerName;
34 |
35 | public bool HasGameChanged(GameData other)
36 | {
37 | if (other == null) return true;
38 | if (MapSeed != other.MapSeed) return true;
39 | if (Difficulty != other.Difficulty) return true;
40 | if (PlayerName != other.PlayerName) return true;
41 | return false;
42 | }
43 |
44 | public bool HasMapChanged(GameData other)
45 | {
46 | return HasGameChanged(other) || Area != other.Area;
47 | }
48 |
49 | public override string ToString()
50 | {
51 | return
52 | $"{nameof(PlayerPosition)}: {PlayerPosition}, {nameof(MapSeed)}: {MapSeed}, {nameof(Difficulty)}: {Difficulty}, {nameof(Area)}: {Area}, {nameof(MapShown)}: {MapShown}";
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Structs/Monster.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Runtime.InteropServices;
21 | using System.Drawing;
22 | using System.Collections.Generic;
23 | using MapAssist.Types;
24 | using System;
25 |
26 | namespace MapAssist.Structs
27 | {
28 | public struct Monster
29 | {
30 | public Point Position;
31 | public uint UniqueFlag;
32 | public List Immunities;
33 | }
34 | [StructLayout(LayoutKind.Explicit)]
35 | public struct MonStats
36 | {
37 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
38 | [FieldOffset(0x00)] public byte[] Name;
39 | }
40 |
41 | [StructLayout(LayoutKind.Explicit)]
42 | public struct MonsterData
43 | {
44 | [FieldOffset(0x0)] public IntPtr pMonStats;
45 | [FieldOffset(0x8)] public ulong ShrineType;
46 | [FieldOffset(0x1A)] public MonsterTypeFlags MonsterType;
47 | }
48 | [Flags]
49 | public enum MonsterTypeFlags : byte
50 | {
51 | None = 0,
52 | Other = 1,
53 | SuperUnique = 1 << 1,
54 | Champion = 1 << 2,
55 | Unique = 1 << 3,
56 | Minion = 1 << 4,
57 | Possessed = 1 << 5,
58 | Ghostly = 1 << 6,
59 | Multishot = 1 << 7,
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Settings/PointOfInterestRendering.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Drawing;
21 |
22 | namespace MapAssist.Settings
23 | {
24 | public class PointOfInterestRendering
25 | {
26 | public Color IconColor;
27 | public Shape IconShape;
28 | public int IconSize;
29 |
30 | public Color LineColor;
31 | public float LineThickness;
32 |
33 | public int ArrowHeadSize;
34 |
35 | public Color LabelColor;
36 | public string LabelFont;
37 | public int LabelFontSize;
38 |
39 | public bool CanDrawIcon()
40 | {
41 | return IconShape != Shape.None && IconSize > 0 && IconColor != Color.Transparent;
42 | }
43 |
44 | public bool CanDrawLine()
45 | {
46 | return LineColor != Color.Transparent && LineThickness > 0;
47 | }
48 |
49 | public bool CanDrawArrowHead()
50 | {
51 | return CanDrawLine() && ArrowHeadSize > 0;
52 | }
53 |
54 | public bool CanDrawLabel()
55 | {
56 | return LabelColor != Color.Transparent && !string.IsNullOrWhiteSpace(LabelFont) &&
57 | LabelFontSize > 0;
58 | }
59 | }
60 | public class MobRendering
61 | {
62 | public Color NormalColor;
63 | public Color UniqueColor;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | #if DEBUG
21 | using System.Reflection;
22 | using System.Runtime.InteropServices;
23 |
24 | // General Information about an assembly is controlled through the following
25 | // set of attributes. Change these attribute values to modify the information
26 | // associated with an assembly.
27 | [assembly: AssemblyTitle("")]
28 | [assembly: AssemblyDescription("")]
29 | [assembly: AssemblyConfiguration("")]
30 | [assembly: AssemblyCompany("")]
31 | [assembly: AssemblyProduct("MapAssist")]
32 | [assembly: AssemblyCopyright("Copyright © 2021")]
33 | [assembly: AssemblyTrademark("")]
34 | [assembly: AssemblyCulture("")]
35 |
36 | // Setting ComVisible to false makes the types in this assembly not visible
37 | // to COM components. If you need to access a type in this assembly from
38 | // COM, set the ComVisible attribute to true on that type.
39 | [assembly: ComVisible(false)]
40 |
41 | // The following GUID is for the ID of the typelib if this project is exposed to COM
42 | [assembly: Guid("fb3ac437-b7bb-42ff-a2a2-f10551f95f6c")]
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.2.0")]
55 | [assembly: AssemblyFileVersion("1.2.0")]
56 | #endif
57 |
--------------------------------------------------------------------------------
/Overlay.Designer.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Windows.Forms;
6 |
7 | namespace MapAssist
8 | {
9 | partial class Overlay
10 | {
11 | ///
12 | /// Required designer variable.
13 | ///
14 | private IContainer components = null;
15 |
16 | ///
17 | /// Clean up any resources being used.
18 | ///
19 | /// true if managed resources should be disposed; otherwise, false.
20 | protected override void Dispose(bool disposing)
21 | {
22 | if (disposing && (components != null))
23 | {
24 | components.Dispose();
25 | }
26 | base.Dispose(disposing);
27 | }
28 |
29 | #region Windows Form Designer generated code
30 |
31 | ///
32 | /// Required method for Designer support - do not modify
33 | /// the contents of this method with the code editor.
34 | ///
35 | private void InitializeComponent()
36 | {
37 | ComponentResourceManager resources = new ComponentResourceManager(typeof(Overlay));
38 | mapOverlay = new PictureBox();
39 | ((ISupportInitialize)(mapOverlay)).BeginInit();
40 | this.SuspendLayout();
41 | //
42 | // mapOverlay
43 | //
44 | mapOverlay.BackColor = Color.Transparent;
45 | mapOverlay.Location = new Point(12, 3);
46 | mapOverlay.Name = "mapOverlay";
47 | mapOverlay.Size = new Size(0, 0);
48 | mapOverlay.TabIndex = 0;
49 | mapOverlay.TabStop = false;
50 | mapOverlay.Paint += new PaintEventHandler(MapOverlay_Paint);
51 |
52 | //
53 | // frmOverlay
54 | //
55 | AutoScaleDimensions = new SizeF(6F, 13F);
56 | AutoScaleMode = AutoScaleMode.Font;
57 | ClientSize = new Size(1767, 996);
58 | Controls.Add(mapOverlay);
59 | FormBorderStyle = FormBorderStyle.None;
60 | Icon = (Icon)(resources.GetObject("$this.Icon"));
61 | Name = "Overlay";
62 | TransparencyKey = Color.Black;
63 | BackColor = Color.Black;
64 | WindowState = FormWindowState.Maximized;
65 | Load += new EventHandler(Overlay_Load);
66 | FormClosing += new FormClosingEventHandler(Overlay_FormClosing);
67 | ((ISupportInitialize)(mapOverlay)).EndInit();
68 | ResumeLayout(false);
69 | }
70 |
71 | #endregion
72 |
73 | private PictureBox mapOverlay;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Structs/UnitAny.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Runtime.InteropServices;
22 | using MapAssist.Types;
23 |
24 | namespace MapAssist.Structs
25 | {
26 | [StructLayout(LayoutKind.Explicit)]
27 | unsafe public struct UnitAny
28 | {
29 | [FieldOffset(0x00)] public uint UnitType;
30 | [FieldOffset(0x04)] public uint TxtFileNo;
31 | [FieldOffset(0x08)] public uint UnitId;
32 | [FieldOffset(0x0C)] public uint Mode;
33 | [FieldOffset(0x10)] public IntPtr UnitData;
34 | [FieldOffset(0x10)] public IntPtr IsPlayer;
35 | [FieldOffset(0x20)] public Act* pAct;
36 | [FieldOffset(0x38)] public Path* pPath;
37 | [FieldOffset(0x88)] public IntPtr StatsListEx;
38 | [FieldOffset(0x90)] public IntPtr Inventory;
39 | [FieldOffset(0xB8)] public uint OwnerType; // ?
40 | [FieldOffset(0xC4)] public ushort X;
41 | [FieldOffset(0xC6)] public ushort Y;
42 | [FieldOffset(0x150)] public UnitAny* pListNext;
43 | [FieldOffset(0x158)] public UnitAny* pRoomNext;
44 |
45 | public override bool Equals(object obj) => obj is UnitAny other && Equals(other);
46 |
47 | public bool Equals(UnitAny unit) => UnitId == unit.UnitId;
48 |
49 | public override int GetHashCode() => UnitId.GetHashCode();
50 |
51 | public static bool operator ==(UnitAny unit1, UnitAny unit2) => unit1.Equals(unit2);
52 |
53 | public static bool operator !=(UnitAny unit1, UnitAny unit2) => !(unit1 == unit2);
54 | }
55 | [StructLayout(LayoutKind.Explicit)]
56 | public readonly struct StatValue
57 | {
58 | [FieldOffset(0x0)] public readonly ushort Layer;
59 | [FieldOffset(0x2)] public readonly Stat Stat;
60 | [FieldOffset(0x4)] public readonly int Value;
61 | }
62 |
63 | [StructLayout(LayoutKind.Explicit)]
64 | public readonly struct StatArrayStruct
65 | {
66 | [FieldOffset(0x0)] public readonly IntPtr FirstStatPtr;
67 | [FieldOffset(0x8)] public readonly ulong Size;
68 | [FieldOffset(0x10)] public readonly ulong Capacity;
69 | }
70 |
71 | [StructLayout(LayoutKind.Explicit)]
72 | public readonly struct StatListStruct
73 | {
74 | [FieldOffset(0x8)] public readonly uint OwnerType;
75 | [FieldOffset(0xC)] public readonly uint OwnerId;
76 | [FieldOffset(0x1C)] public readonly uint Flags;
77 | [FieldOffset(0x30)] public readonly StatArrayStruct Stats;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/.github/workflows/nightly.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Nightly
2 | on:
3 | schedule:
4 | - cron: '0 2 * * *'
5 | workflow_dispatch:
6 |
7 | env:
8 | # Path to the solution file relative to the root of the project.
9 | SOLUTION_FILE_PATH: .
10 |
11 | # Configuration type to build.
12 | # You can convert this to a build matrix if you need coverage of multiple configuration types.
13 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
14 | BUILD_CONFIGURATION: Release
15 |
16 | jobs:
17 | nightly-develop:
18 | name: Nightly Develop
19 | strategy:
20 | fail-fast: false
21 | matrix:
22 | os: [windows-latest]
23 | runs-on: ${{ matrix.os }}
24 | steps:
25 | - uses: actions/checkout@v2
26 | with:
27 | ref: "develop"
28 |
29 | - name: Add MSBuild to PATH
30 | uses: microsoft/setup-msbuild@v1.0.2
31 |
32 | - name: Restore NuGet packages
33 | working-directory: ${{env.GITHUB_WORKSPACE}}
34 | run: nuget restore ${{env.SOLUTION_FILE_PATH}}
35 |
36 | - name: Build
37 | working-directory: ${{env.GITHUB_WORKSPACE}}
38 | # Add additional options to the MSBuild command line here (like platform or verbosity level).
39 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
40 | run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} /p:DebugSymbols=false
41 |
42 | - name: Zip release
43 | uses: papeloto/action-zip@v1
44 | with:
45 | files: bin/x64/Release/ LICENSE README.md
46 | recursive: true
47 | dest: MapAssist.zip
48 |
49 | - name: Publish release
50 | uses: "marvinpinto/action-automatic-releases@latest"
51 | with:
52 | repo_token: "${{ secrets.GITHUB_TOKEN }}"
53 | automatic_release_tag: "develop"
54 | prerelease: false
55 | files: |
56 | LICENSE
57 | README.md
58 | MapAssist.zip
59 | nightly-latest:
60 | name: Nightly Latest
61 | strategy:
62 | fail-fast: false
63 | matrix:
64 | os: [windows-latest]
65 | runs-on: ${{ matrix.os }}
66 | steps:
67 | - uses: actions/checkout@v2
68 | with:
69 | ref: "main"
70 |
71 | - name: Add MSBuild to PATH
72 | uses: microsoft/setup-msbuild@v1.0.2
73 |
74 | - name: Restore NuGet packages
75 | working-directory: ${{env.GITHUB_WORKSPACE}}
76 | run: nuget restore ${{env.SOLUTION_FILE_PATH}}
77 |
78 | - name: Build
79 | working-directory: ${{env.GITHUB_WORKSPACE}}
80 | # Add additional options to the MSBuild command line here (like platform or verbosity level).
81 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
82 | run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} /p:DebugSymbols=false
83 |
84 | - name: Zip release
85 | uses: papeloto/action-zip@v1
86 | with:
87 | files: bin/x64/Release/ LICENSE README.md
88 | recursive: true
89 | dest: MapAssist.zip
90 |
91 | - name: Publish release
92 | uses: "marvinpinto/action-automatic-releases@latest"
93 | with:
94 | repo_token: "${{ secrets.GITHUB_TOKEN }}"
95 | automatic_release_tag: "latest"
96 | prerelease: false
97 | files: |
98 | LICENSE
99 | README.md
100 | MapAssist.zip
101 |
--------------------------------------------------------------------------------
/Helpers/WindowsExternal.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Runtime.InteropServices;
22 |
23 | namespace MapAssist.Helpers
24 | {
25 | public static class WindowsExternal
26 | {
27 | [DllImport("kernel32.dll", SetLastError = true)]
28 | public static extern IntPtr OpenProcess(
29 | uint processAccess,
30 | bool bInheritHandle,
31 | int processId
32 | );
33 |
34 | [DllImport("kernel32.dll", SetLastError = true)]
35 | public static extern bool CloseHandle(
36 | IntPtr hObject
37 | );
38 |
39 | [Flags]
40 | public enum ProcessAccessFlags : uint
41 | {
42 | All = 0x001F0FFF,
43 | Terminate = 0x00000001,
44 | CreateThread = 0x00000002,
45 | VirtualMemoryOperation = 0x00000008,
46 | VirtualMemoryRead = 0x00000010,
47 | VirtualMemoryWrite = 0x00000020,
48 | DuplicateHandle = 0x00000040,
49 | CreateProcess = 0x000000080,
50 | SetQuota = 0x00000100,
51 | SetInformation = 0x00000200,
52 | QueryInformation = 0x00000400,
53 | QueryLimitedInformation = 0x00001000,
54 | Synchronize = 0x00100000
55 | }
56 |
57 | [DllImport("kernel32.dll", SetLastError = true)]
58 | public static extern bool ReadProcessMemory(
59 | IntPtr hProcess,
60 | IntPtr lpBaseAddress,
61 | [Out] byte[] lpBuffer,
62 | int dwSize,
63 | out IntPtr lpNumberOfBytesRead);
64 |
65 | // This helper static method is required because the 32-bit version of user32.dll does not contain this API
66 | // (on any versions of Windows), so linking the method will fail at run-time. The bridge dispatches the request
67 | // to the correct function (GetWindowLong in 32-bit mode and GetWindowLongPtr in 64-bit mode)
68 |
69 | // If that doesn't work, the following signature can be used alternatively.
70 | [DllImport("user32.dll")]
71 | public static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
72 |
73 | [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
74 | private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex);
75 |
76 | [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
77 | private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
78 |
79 | // This static method is required because Win32 does not support
80 | // GetWindowLongPtr directly
81 | public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
82 | {
83 | if (IntPtr.Size == 8)
84 | return GetWindowLongPtr64(hWnd, nIndex);
85 | else
86 | return GetWindowLongPtr32(hWnd, nIndex);
87 | }
88 |
89 | [DllImport("user32.dll")]
90 | [return: MarshalAs(UnmanagedType.Bool)]
91 | public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy,
92 | uint uFlags);
93 |
94 | [DllImport("user32.dll")]
95 | public static extern IntPtr GetForegroundWindow();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # The following command works for downloading when using Git for Windows:
2 | # curl -LOf http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
3 | #
4 | # Download this file using PowerShell v3 under Windows with the following comand:
5 | # Invoke-WebRequest https://gist.githubusercontent.com/kmorcinek/2710267/raw/ -OutFile .gitignore
6 | #
7 | # or wget:
8 | # wget --no-check-certificate http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
9 |
10 | # User-specific files
11 | *.suo
12 | *.user
13 | *.sln.docstates
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Rr]elease/
18 | x64/
19 | [Bb]in/
20 | [Oo]bj/
21 | # build folder is nowadays used for build scripts and should not be ignored
22 | #build/
23 |
24 | # NuGet Packages
25 | *.nupkg
26 | # The packages folder can be ignored because of Package Restore
27 | **/packages/*
28 | # except build/, which is used as an MSBuild target.
29 | !**/packages/build/
30 | # Uncomment if necessary however generally it will be regenerated when needed
31 | #!**/packages/repositories.config
32 |
33 | # MSTest test Results
34 | [Tt]est[Rr]esult*/
35 | [Bb]uild[Ll]og.*
36 |
37 | *_i.c
38 | *_p.c
39 | *.ilk
40 | *.meta
41 | *.obj
42 | *.pch
43 | *.pdb
44 | *.pgc
45 | *.pgd
46 | *.rsp
47 | *.sbr
48 | *.tlb
49 | *.tli
50 | *.tlh
51 | *.tmp
52 | *.tmp_proj
53 | *.log
54 | *.vspscc
55 | *.vssscc
56 | .builds
57 | *.pidb
58 | *.log
59 | *.scc
60 |
61 | # OS generated files #
62 | .DS_Store*
63 | Icon?
64 |
65 | # Visual C++ cache files
66 | ipch/
67 | *.aps
68 | *.ncb
69 | *.opensdf
70 | *.sdf
71 | *.cachefile
72 |
73 | # Visual Studio profiler
74 | *.psess
75 | *.vsp
76 | *.vspx
77 |
78 | # Guidance Automation Toolkit
79 | *.gpState
80 |
81 | # ReSharper is a .NET coding add-in
82 | _ReSharper*/
83 | *.[Rr]e[Ss]harper
84 |
85 | # TeamCity is a build add-in
86 | _TeamCity*
87 |
88 | # DotCover is a Code Coverage Tool
89 | *.dotCover
90 |
91 | # NCrunch
92 | *.ncrunch*
93 | .*crunch*.local.xml
94 |
95 | # Installshield output folder
96 | [Ee]xpress/
97 |
98 | # DocProject is a documentation generator add-in
99 | DocProject/buildhelp/
100 | DocProject/Help/*.HxT
101 | DocProject/Help/*.HxC
102 | DocProject/Help/*.hhc
103 | DocProject/Help/*.hhk
104 | DocProject/Help/*.hhp
105 | DocProject/Help/Html2
106 | DocProject/Help/html
107 |
108 | # Click-Once directory
109 | publish/
110 |
111 | # Publish Web Output
112 | *.Publish.xml
113 |
114 | # Windows Azure Build Output
115 | csx
116 | *.build.csdef
117 |
118 | # Windows Store app package directory
119 | AppPackages/
120 |
121 | # Others
122 | *.Cache
123 | ClientBin/
124 | [Ss]tyle[Cc]op.*
125 | ~$*
126 | *~
127 | *.dbmdl
128 | *.[Pp]ublish.xml
129 | *.pfx
130 | *.publishsettings
131 | modulesbin/
132 | tempbin/
133 |
134 | # EPiServer Site file (VPP)
135 | AppData/
136 |
137 | # RIA/Silverlight projects
138 | Generated_Code/
139 |
140 | # Backup & report files from converting an old project file to a newer
141 | # Visual Studio version. Backup files are not needed, because we have git ;-)
142 | _UpgradeReport_Files/
143 | Backup*/
144 | UpgradeLog*.XML
145 | UpgradeLog*.htm
146 |
147 | # vim
148 | *.txt~
149 | *.swp
150 | *.swo
151 |
152 | # Temp files when opening LibreOffice on ubuntu
153 | .~lock.*
154 |
155 | # svn
156 | .svn
157 |
158 | # CVS - Source Control
159 | **/CVS/
160 |
161 | # Remainings from resolving conflicts in Source Control
162 | *.orig
163 |
164 | # SQL Server files
165 | **/App_Data/*.mdf
166 | **/App_Data/*.ldf
167 | **/App_Data/*.sdf
168 |
169 |
170 | #LightSwitch generated files
171 | GeneratedArtifacts/
172 | _Pvt_Extensions/
173 | ModelManifest.xml
174 |
175 | # =========================
176 | # Windows detritus
177 | # =========================
178 |
179 | # Windows image file caches
180 | Thumbs.db
181 | ehthumbs.db
182 |
183 | # Folder config file
184 | Desktop.ini
185 |
186 | # Recycle Bin used on file shares
187 | $RECYCLE.BIN/
188 |
189 | # Mac desktop service store files
190 | .DS_Store
191 |
192 | # SASS Compiler cache
193 | .sass-cache
194 |
195 | # Visual Studio 2014 CTP
196 | **/*.sln.ide
197 |
198 | # Visual Studio temp something
199 | .vs/
200 |
201 | # dotnet stuff
202 | project.lock.json
203 |
204 | # VS 2015+
205 | *.vc.vc.opendb
206 | *.vc.db
207 |
208 | # Rider
209 | .idea/
210 |
211 | # Visual Studio Code
212 | .vscode/
213 |
214 | # Output folder used by Webpack or other FE stuff
215 | **/node_modules/*
216 | **/wwwroot/*
217 |
218 | # SpecFlow specific
219 | *.feature.cs
220 | *.feature.xlsx.*
221 | *.Specs_*.html
222 |
223 | #####
224 | # End of core ignore list, below put you custom 'per project' settings (patterns or path)
225 | #####
226 |
--------------------------------------------------------------------------------
/Types/RawAreaData.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Collections.Generic;
21 | using System.Drawing;
22 | using System.Linq;
23 |
24 | // ReSharper disable ClassNeverInstantiated.Global
25 | // ReSharper disable InconsistentNaming
26 | // ReSharper disable MemberCanBePrivate.Global
27 | // ReSharper disable UnassignedField.Global
28 | // ReSharper disable CollectionNeverUpdated.Global
29 |
30 | namespace MapAssist.Types
31 | {
32 | public class XY
33 | {
34 | public int x;
35 | public int y;
36 |
37 | public Point ToPoint()
38 | {
39 | return new Point(x, y);
40 | }
41 | }
42 |
43 | public class RawAdjacentLevel
44 | {
45 | public XY[] exits;
46 | public XY origin;
47 | public int width;
48 | public int height;
49 |
50 | public AdjacentLevel ToInternal(Area area)
51 | {
52 | return new AdjacentLevel
53 | {
54 | Area = area,
55 | Origin = origin.ToPoint(),
56 | Exits = exits.Select(o => o.ToPoint()).ToArray(),
57 | Width = width,
58 | Height = height,
59 | };
60 | }
61 | }
62 |
63 | public class RawAreaData
64 | {
65 | public XY levelOrigin;
66 | public Dictionary adjacentLevels;
67 | public int[][] mapRows;
68 | public Dictionary npcs;
69 | public Dictionary objects;
70 |
71 | public AreaData ToInternal(Area area)
72 | {
73 | return new AreaData
74 | {
75 | Area = area,
76 | Origin = levelOrigin.ToPoint(),
77 | AdjacentLevels = adjacentLevels
78 | .Select(o =>
79 | {
80 | var adjacentArea = Area.None;
81 | if (int.TryParse(o.Key, out int parsed))
82 | {
83 | adjacentArea = (Area)parsed;
84 | }
85 |
86 | AdjacentLevel level = o.Value.ToInternal(adjacentArea);
87 | return (adjacentArea, level);
88 | })
89 | .Where(o => o.adjacentArea != Area.None)
90 | .ToDictionary(k => k.adjacentArea, v => v.level),
91 | NPCs = npcs.Select(o =>
92 | {
93 | Point[] positions = o.Value.Select(j => j.ToPoint()).ToArray();
94 | var npc = Npc.Invalid;
95 | if (int.TryParse(o.Key, out int parsed))
96 | {
97 | npc = (Npc)parsed;
98 | }
99 |
100 | return (npc, positions);
101 | })
102 | .Where(o => o.npc != Npc.Invalid)
103 | .ToDictionary(k => k.npc, v => v.positions),
104 | Objects = objects.Select(o =>
105 | {
106 | Point[] positions = o.Value.Select(j => j.ToPoint()).ToArray();
107 | var gameObject = GameObject.NotApplicable;
108 | if (int.TryParse(o.Key, out int parsed))
109 | {
110 | gameObject = (GameObject)parsed;
111 | }
112 |
113 | return (gameObject, positions);
114 | })
115 | .Where(o => o.gameObject != GameObject.NotApplicable)
116 | .ToDictionary(k => k.gameObject, v => v.positions),
117 | CollisionGrid = mapRows
118 | };
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Settings/Utils.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Configuration;
22 | using System.Diagnostics;
23 | using System.Drawing;
24 | using System.Linq;
25 | using MapAssist.Types;
26 |
27 | namespace MapAssist.Settings
28 | {
29 | public static class Utils
30 | {
31 | public static string[] ParseCommaSeparatedNpcsByName(string npc)
32 | {
33 | return npc
34 | .Split(',')
35 | .Select(o => LookupNpcByName(o.Trim()))
36 | .Where(o => o != "")
37 | .ToArray();
38 | }
39 | public static Area[] ParseCommaSeparatedAreasByName(string areas)
40 | {
41 | return areas
42 | .Split(',')
43 | .Select(o => LookupAreaByName(o.Trim()))
44 | .Where(o => o != Area.None)
45 | .ToArray();
46 | }
47 |
48 | private static string LookupNpcByName(string name)
49 | {
50 | var name2 = "";
51 | try
52 | {
53 | name2 = Enum.GetName(typeof(Npc), name);
54 | }
55 | catch
56 | {
57 | return name;
58 | }
59 | return name2;
60 | }
61 | private static Area LookupAreaByName(string name)
62 | {
63 | return Enum.GetValues(typeof(Area)).Cast().FirstOrDefault(area => area.Name() == name);
64 | }
65 |
66 | private static T GetConfigValue(string key, Func converter, T fallback = default)
67 | {
68 | string valueString = ConfigurationManager.AppSettings[key];
69 | return string.IsNullOrWhiteSpace(valueString) ? fallback : converter.Invoke(valueString);
70 | }
71 |
72 | public static Color ParseColor(string value)
73 | {
74 | if (value.StartsWith("#"))
75 | {
76 | return ColorTranslator.FromHtml(value);
77 | }
78 |
79 | if (!value.Contains(","))
80 | {
81 | return Color.FromName(value);
82 | }
83 |
84 | int[] ints = value.Split(',').Select(o => int.Parse(o.Trim())).ToArray();
85 | switch (ints.Length)
86 | {
87 | case 4:
88 | return Color.FromArgb(ints[0], ints[1], ints[2], ints[3]);
89 | case 3:
90 | return Color.FromArgb(ints[0], ints[1], ints[2]);
91 | }
92 |
93 | return Color.FromName(value);
94 | }
95 |
96 | public static PointOfInterestRendering GetRenderingSettingsForPrefix(string name)
97 | {
98 | return new PointOfInterestRendering
99 | {
100 | IconColor = GetConfigValue($"{name}.IconColor", ParseColor, Color.Transparent),
101 | IconShape = GetConfigValue($"{name}.IconShape", t => (Shape)Enum.Parse(typeof(Shape), t, true)),
102 | IconSize = GetConfigValue($"{name}.IconSize", Convert.ToInt32),
103 | LineColor = GetConfigValue($"{name}.LineColor", ParseColor, Color.Transparent),
104 | LineThickness = GetConfigValue($"{name}.LineThickness", Convert.ToSingle, 1),
105 | ArrowHeadSize = GetConfigValue($"{name}.ArrowHeadSize", Convert.ToInt32),
106 | LabelColor = GetConfigValue($"{name}.LabelColor", ParseColor, Color.Transparent),
107 | LabelFont = GetConfigValue($"{name}.LabelFont", t => t, "Arial"),
108 | LabelFontSize = GetConfigValue($"{name}.LabelFontSize", Convert.ToInt32, 8),
109 | };
110 | }
111 | public static MobRendering GetMobRendering()
112 | {
113 | return new MobRendering
114 | {
115 | NormalColor = GetConfigValue($"MobColor.Normal", ParseColor, Color.Transparent),
116 | UniqueColor = GetConfigValue($"MobColor.Unique", ParseColor, Color.Transparent)
117 | };
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
100 |
101 |
102 |
103 |
104 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/Settings/Settings.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Collections.Generic;
22 | using System.Configuration;
23 | using System.Drawing;
24 | using MapAssist.Types;
25 |
26 | // ReSharper disable FieldCanBeMadeReadOnly.Global
27 |
28 | namespace MapAssist.Settings
29 | {
30 | public static class Rendering
31 | {
32 | public static PointOfInterestRendering
33 | NextArea = Utils.GetRenderingSettingsForPrefix("NextArea");
34 |
35 | public static PointOfInterestRendering PreviousArea =
36 | Utils.GetRenderingSettingsForPrefix("PreviousArea");
37 |
38 | public static PointOfInterestRendering Waypoint = Utils.GetRenderingSettingsForPrefix("Waypoint");
39 | public static PointOfInterestRendering Quest = Utils.GetRenderingSettingsForPrefix("Quest");
40 | public static PointOfInterestRendering Player = Utils.GetRenderingSettingsForPrefix("Player");
41 |
42 | public static PointOfInterestRendering SuperChest =
43 | Utils.GetRenderingSettingsForPrefix("SuperChest");
44 | }
45 |
46 | public static class Map
47 | {
48 | public static readonly Dictionary MapColors = new Dictionary();
49 |
50 | public static void InitMapColors()
51 | {
52 | for (var i = -1; i < 600; i++)
53 | {
54 | LookupMapColor(i);
55 | }
56 | }
57 |
58 | public static Color? LookupMapColor(int type)
59 | {
60 | var key = "MapColor[" + type + "]";
61 |
62 | if (!MapColors.ContainsKey(type))
63 | {
64 | var mapColorString = ConfigurationManager.AppSettings[key];
65 | if (!string.IsNullOrEmpty(mapColorString))
66 | {
67 | MapColors[type] = Utils.ParseColor(mapColorString);
68 | }
69 | else
70 | {
71 | MapColors[type] = null;
72 | }
73 | }
74 |
75 | return MapColors[type];
76 | }
77 |
78 | public static double Opacity = Convert.ToDouble(ConfigurationManager.AppSettings["Opacity"],
79 | System.Globalization.CultureInfo.InvariantCulture);
80 |
81 | public static bool OverlayMode = Convert.ToBoolean(ConfigurationManager.AppSettings["OverlayMode"]);
82 |
83 | public static bool AlwaysOnTop = Convert.ToBoolean(ConfigurationManager.AppSettings["AlwaysOnTop"]);
84 |
85 | public static bool ToggleViaInGameMap =
86 | Convert.ToBoolean(ConfigurationManager.AppSettings["ToggleViaInGameMap"]);
87 |
88 | public static int Size = Convert.ToInt16(ConfigurationManager.AppSettings["Size"]);
89 |
90 | public static MapPosition Position =
91 | (MapPosition)Enum.Parse(typeof(MapPosition), ConfigurationManager.AppSettings["MapPosition"], true);
92 |
93 | public static int UpdateTime = Convert.ToInt16(ConfigurationManager.AppSettings["UpdateTime"]);
94 | public static bool Rotate = Convert.ToBoolean(ConfigurationManager.AppSettings["Rotate"]);
95 | public static char ToggleKey = Convert.ToChar(ConfigurationManager.AppSettings["ToggleKey"]);
96 | public static char ZoomInKey = Convert.ToChar(ConfigurationManager.AppSettings["ZoomInKey"]);
97 | public static char ZoomOutKey = Convert.ToChar(ConfigurationManager.AppSettings["ZoomOutKey"]);
98 | public static float ZoomLevel = Convert.ToSingle(ConfigurationManager.AppSettings["ZoomLevelDefault"]);
99 |
100 | public static Area[] PrefetchAreas =
101 | Utils.ParseCommaSeparatedAreasByName(ConfigurationManager.AppSettings["PrefetchAreas"]);
102 |
103 | public static Area[] HiddenAreas =
104 | Utils.ParseCommaSeparatedAreasByName(ConfigurationManager.AppSettings["HiddenAreas"]);
105 |
106 | public static string[] WarnImmuneNPC =
107 | Utils.ParseCommaSeparatedNpcsByName(ConfigurationManager.AppSettings["WarnNPCImmune"]);
108 | public static int WarnImmuneNPCFontSize = Convert.ToInt32(ConfigurationManager.AppSettings["WarnNPCFontSize"]);
109 | public static string WarnImmuneNPCFont = Convert.ToString(ConfigurationManager.AppSettings["WarnNPCFont"]);
110 | public static StringAlignment WarnNPCVerticalAlign = (StringAlignment)Enum.Parse(typeof(StringAlignment), ConfigurationManager.AppSettings["WarnNPCVerticalAlign"]);
111 | public static StringAlignment WarnNPCHorizontalAlign = (StringAlignment)Enum.Parse(typeof(StringAlignment), ConfigurationManager.AppSettings["WarnNPCHorizontalAlign"]);
112 | public static Color WarnNPCFontColor = Utils.ParseColor(Convert.ToString(ConfigurationManager.AppSettings["WarnNPCFontColor"]));
113 |
114 | public static bool ClearPrefetchedOnAreaChange =
115 | Convert.ToBoolean(ConfigurationManager.AppSettings["ClearPrefetchedOnAreaChange"]);
116 | }
117 |
118 | public static class Api
119 | {
120 | public static string Endpoint = ConfigurationManager.AppSettings["ApiEndpoint"];
121 | public static string Token = ConfigurationManager.AppSettings["ApiToken"];
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/Helpers/MapApi.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using MapAssist.Types;
21 | using Newtonsoft.Json;
22 | using System;
23 | using System.Collections.Concurrent;
24 | using System.Collections.Generic;
25 | using System.Diagnostics.CodeAnalysis;
26 | using System.Linq;
27 | using System.Net;
28 | using System.Net.Http;
29 | using System.Net.Http.Headers;
30 | using System.Text;
31 | using System.Threading;
32 | #pragma warning disable 649
33 |
34 | namespace MapAssist.Helpers
35 | {
36 | public class MapApi : IDisposable
37 | {
38 | public static readonly HttpClient Client = HttpClient(Settings.Api.Endpoint, Settings.Api.Token);
39 | private readonly string _sessionId;
40 | private readonly ConcurrentDictionary _cache;
41 | private readonly BlockingCollection _prefetchRequests;
42 | private readonly Thread _thread;
43 | private readonly HttpClient _client;
44 |
45 | private string CreateSession(Difficulty difficulty, uint mapSeed)
46 | {
47 | var values = new Dictionary
48 | {
49 | { "difficulty", (uint)difficulty },
50 | { "mapid", mapSeed }
51 | };
52 |
53 | var json = JsonConvert.SerializeObject(values);
54 | var content = new StringContent(json, Encoding.UTF8, "application/json");
55 | HttpResponseMessage response = _client.PostAsync("sessions/", content).GetAwaiter().GetResult();
56 | response.EnsureSuccessStatusCode();
57 | var session =
58 | JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().GetAwaiter()
59 | .GetResult());
60 | return session.id;
61 | }
62 |
63 | private void DestroySession(string sessionId)
64 | {
65 | HttpResponseMessage response =
66 | _client.DeleteAsync("sessions/" + sessionId).GetAwaiter().GetResult();
67 | response.EnsureSuccessStatusCode();
68 | }
69 |
70 | public MapApi(HttpClient client, Difficulty difficulty, uint mapSeed)
71 | {
72 | _client = client;
73 | _sessionId = CreateSession(difficulty, mapSeed);
74 | // Cache for pre-fetching maps for the surrounding areas.
75 | _cache = new ConcurrentDictionary();
76 | _prefetchRequests = new BlockingCollection();
77 | _thread = new Thread(Prefetch)
78 | {
79 | IsBackground = true
80 | };
81 | _thread.Start();
82 |
83 | if (Settings.Map.PrefetchAreas.Any())
84 | {
85 | _prefetchRequests.Add(Settings.Map.PrefetchAreas);
86 | }
87 | }
88 |
89 | public AreaData GetMapData(Area area)
90 | {
91 | if (!_cache.TryGetValue(area, out AreaData areaData))
92 | {
93 | // Not in the cache, block.
94 | Console.WriteLine($"Cache miss on {area}");
95 | areaData = GetMapDataInternal(area);
96 | }
97 |
98 | Area[] adjacentAreas = areaData.AdjacentLevels.Keys.ToArray();
99 | if (adjacentAreas.Any())
100 | {
101 | _prefetchRequests.Add(adjacentAreas);
102 | }
103 |
104 | return areaData;
105 | }
106 |
107 | private void Prefetch()
108 | {
109 | while (true)
110 | {
111 | Area[] areas = _prefetchRequests.Take();
112 | if (Settings.Map.ClearPrefetchedOnAreaChange)
113 | {
114 | _cache.Clear();
115 | }
116 |
117 | // Special value telling us to exit.
118 | if (areas.Length == 0)
119 | {
120 | Console.WriteLine("Prefetch thread terminating");
121 | return;
122 | }
123 |
124 | foreach (Area area in areas)
125 | {
126 | if (_cache.ContainsKey(area)) continue;
127 |
128 | _cache[area] = GetMapDataInternal(area);
129 | Console.WriteLine($"Prefetched {area}");
130 | }
131 | }
132 | }
133 |
134 | private AreaData GetMapDataInternal(Area area)
135 | {
136 | HttpResponseMessage response = _client.GetAsync("sessions/" + _sessionId +
137 | "/areas/" + (uint)area).GetAwaiter().GetResult();
138 | response.EnsureSuccessStatusCode();
139 | var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
140 | var rawMapData = JsonConvert.DeserializeObject(content);
141 | return rawMapData.ToInternal(area);
142 | }
143 |
144 | private static HttpClient HttpClient(string endpoint, string token)
145 | {
146 | var client = new HttpClient(new HttpClientHandler
147 | {
148 | AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
149 | })
150 | {
151 | BaseAddress = new Uri(endpoint)
152 | };
153 | client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
154 | client.DefaultRequestHeaders.AcceptEncoding.Add(
155 | new StringWithQualityHeaderValue("gzip"));
156 | client.DefaultRequestHeaders.AcceptEncoding.Add(
157 | new StringWithQualityHeaderValue("deflate"));
158 | if (!string.IsNullOrEmpty(token))
159 | {
160 | client.DefaultRequestHeaders.Authorization =
161 | new AuthenticationHeaderValue("Bearer", token);
162 | }
163 | return client;
164 | }
165 |
166 | public void Dispose()
167 | {
168 | _prefetchRequests.Add(new Area[] { });
169 | _thread.Join();
170 | try
171 | {
172 | DestroySession(_sessionId);
173 | }
174 | catch (HttpRequestException) // Prevent HttpRequestException if D2MapAPI is closed before this program.
175 | {
176 | Console.WriteLine("D2MapAPI server was closed, session was already destroyed.");
177 | }
178 | }
179 |
180 | [SuppressMessage("ReSharper", "InconsistentNaming")]
181 | [SuppressMessage("CodeQuality", "IDE0079:Remove unnecessary suppression", Justification = "ReSharper")]
182 | private class MapApiSession
183 | {
184 | public string id;
185 | public uint difficulty;
186 | public uint mapId;
187 | }
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/MapAssist.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | win-x64
6 | $([System.Guid]::NewGuid())
7 | Release
8 | x64
9 | {FB3AC437-B7BB-42FF-A2A2-F10551F95F6C}
10 | WinExe
11 | MapAssist
12 |
13 |
14 | $(CustomAssemblyName)
15 | $(RandomGuid)
16 | MapAssist
17 | v4.7.2
18 | 512
19 | true
20 | true
21 | false
22 | publish\
23 | true
24 | Disk
25 | false
26 | Foreground
27 | 7
28 | Days
29 | false
30 | false
31 | true
32 | 1
33 | 1.0.0.%2a
34 | false
35 | true
36 | true
37 |
38 |
39 | true
40 | bin\x64\Debug\
41 | DEBUG;TRACE
42 | full
43 | x64
44 | 7.3
45 | prompt
46 | false
47 | true
48 |
49 |
50 | bin\x64\Release\
51 | TRACE
52 | true
53 | none
54 | x64
55 | 7.3
56 | prompt
57 | false
58 | true
59 |
60 |
61 | 3DB9B26A33D3BC5805AF01B7BC6B71FE986ABD87
62 |
63 |
64 | MapAssist_TemporaryKey.pfx
65 |
66 |
67 | false
68 |
69 |
70 | false
71 |
72 |
73 | true
74 |
75 |
76 |
77 |
78 |
79 |
80 | false
81 |
82 |
83 | LocalIntranet
84 |
85 |
86 |
87 | Resources\Icon1.ico
88 |
89 |
90 |
91 | true
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | Form
112 |
113 |
114 | Overlay.cs
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | Overlay.cs
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 | False
161 | Microsoft .NET Framework 4.7.2 %28x86 and x64%29
162 | true
163 |
164 |
165 | False
166 | .NET Framework 3.5 SP1
167 | false
168 |
169 |
170 |
171 |
172 | 5.6.0
173 |
174 |
175 | 13.0.1
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/Helpers/PointOfInterestHandler.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Collections.Generic;
21 | using System.Drawing;
22 | using System.Linq;
23 | using System.Threading.Tasks;
24 | using MapAssist.Types;
25 |
26 | namespace MapAssist.Helpers
27 | {
28 | public static class PointOfInterestHandler
29 | {
30 | private static readonly HashSet QuestObjects = new HashSet
31 | {
32 | GameObject.HoradricCubeChest,
33 | GameObject.HoradricScrollChest,
34 | GameObject.StaffOfKingsChest,
35 | GameObject.HoradricOrifice,
36 | GameObject.YetAnotherTome, // Summoner in Arcane Sanctuary
37 | GameObject.FrozenAnya,
38 | GameObject.InifussTree,
39 | GameObject.CairnStoneAlpha,
40 | GameObject.WirtCorpse,
41 | GameObject.HellForge
42 | };
43 |
44 | private static readonly HashSet GoodChests = new HashSet
45 | {
46 | GameObject.GoodChest,
47 | GameObject.SparklyChest,
48 | GameObject.ArcaneLargeChestLeft,
49 | GameObject.ArcaneLargeChestRight,
50 | GameObject.ArcaneSmallChestLeft,
51 | GameObject.ArcaneSmallChestRight
52 | };
53 |
54 | public static List Get(MapApi mapApi, AreaData areaData)
55 | {
56 | List pointOfInterest = new List();
57 |
58 | switch (areaData.Area)
59 | {
60 | case Area.CanyonOfTheMagi:
61 | // Work out which tomb is the right once.
62 | // Load the maps for all of the tombs, and check which one has the Orifice.
63 | // Declare that tomb as point of interest.
64 | Area[] tombs = new[]
65 | {
66 | Area.TalRashasTomb1, Area.TalRashasTomb2, Area.TalRashasTomb3, Area.TalRashasTomb4,
67 | Area.TalRashasTomb5, Area.TalRashasTomb6, Area.TalRashasTomb7
68 | };
69 | var realTomb = Area.None;
70 | Parallel.ForEach(tombs, tombArea =>
71 | {
72 | AreaData tombData = mapApi.GetMapData(tombArea);
73 | if (tombData.Objects.ContainsKey(GameObject.HoradricOrifice))
74 | {
75 | realTomb = tombArea;
76 | }
77 | });
78 |
79 | if (realTomb != Area.None && areaData.AdjacentLevels[realTomb].Exits.Any())
80 | {
81 | pointOfInterest.Add(new PointOfInterest
82 | {
83 | Label = realTomb.Name(),
84 | Position = areaData.AdjacentLevels[realTomb].Exits[0],
85 | RenderingSettings = Settings.Rendering.NextArea
86 | }); ;
87 | }
88 |
89 | break;
90 | default:
91 | // By default, draw a line to the next highest neighbouring area.
92 | // Also draw labels and previous doors for all other areas.
93 | if (areaData.AdjacentLevels.Any())
94 | {
95 | Area highestArea = areaData.AdjacentLevels.Keys.Max();
96 | if (highestArea > areaData.Area)
97 | {
98 | if (areaData.AdjacentLevels[highestArea].Exits.Any())
99 | {
100 | pointOfInterest.Add(new PointOfInterest
101 | {
102 | Label = highestArea.Name(),
103 | Position = areaData.AdjacentLevels[highestArea].Exits[0],
104 | RenderingSettings = Settings.Rendering.NextArea
105 | });
106 | }
107 | }
108 |
109 | foreach (AdjacentLevel level in areaData.AdjacentLevels.Values)
110 | {
111 | // Already have something drawn for this.
112 | if (level.Area == highestArea)
113 | {
114 | continue;
115 | }
116 |
117 | foreach (Point position in level.Exits)
118 | {
119 | pointOfInterest.Add(new PointOfInterest
120 | {
121 | Label = level.Area.Name(),
122 | Position = position,
123 | RenderingSettings = Settings.Rendering.PreviousArea
124 | });
125 | }
126 | }
127 | }
128 |
129 | break;
130 | }
131 |
132 | foreach (KeyValuePair objAndPoints in areaData.Objects)
133 | {
134 | GameObject obj = objAndPoints.Key;
135 | Point[] points = objAndPoints.Value;
136 |
137 | if (!points.Any())
138 | {
139 | continue;
140 | }
141 |
142 | // Waypoints
143 | if (obj.IsWaypoint())
144 | {
145 | pointOfInterest.Add(new PointOfInterest
146 | {
147 | Label = obj.ToString(),
148 | Position = points[0],
149 | RenderingSettings = Settings.Rendering.Waypoint
150 | });
151 | }
152 | // Quest objects
153 | else if (QuestObjects.Contains(obj))
154 | {
155 | pointOfInterest.Add(new PointOfInterest
156 | {
157 | Label = obj.ToString(),
158 | Position = points[0],
159 | RenderingSettings = Settings.Rendering.Quest
160 | });
161 | }
162 | // Chests
163 | else if (GoodChests.Contains(obj))
164 | {
165 | foreach (Point point in points)
166 | {
167 | pointOfInterest.Add(new PointOfInterest
168 | {
169 | Label = obj.ToString(),
170 | Position = point,
171 | RenderingSettings = Settings.Rendering.SuperChest
172 | });
173 | }
174 | }
175 | switch (areaData.Area)
176 | {
177 | case Area.HallsOfVaught:
178 | if (obj == GameObject.NihlathakWildernessStartPosition)
179 | {
180 | pointOfInterest.Add(new PointOfInterest
181 | {
182 | Label = obj.ToString(),
183 | Position = points[0],
184 | RenderingSettings = Settings.Rendering.Quest
185 | });
186 | }
187 | break;
188 | }
189 | }
190 |
191 | return pointOfInterest;
192 | }
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/Helpers/ImageUtils.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Diagnostics;
22 | using System.Drawing.Drawing2D;
23 | using System.Drawing.Imaging;
24 | using System.Drawing;
25 |
26 | namespace MapAssist.Helpers
27 | {
28 | public static class ImageUtils
29 | {
30 | public static Bitmap RotateImage(Image inputImage, float angleDegrees, bool upsizeOk, bool clipOk,
31 | Color backgroundColor)
32 | {
33 | // Test for zero rotation and return a clone of the input image
34 | if (angleDegrees == 0f)
35 | return (Bitmap)inputImage.Clone();
36 |
37 | // Set up old and new image dimensions, assuming upsizing not wanted and clipping OK
38 | int oldWidth = inputImage.Width;
39 | int oldHeight = inputImage.Height;
40 | int newWidth = oldWidth;
41 | int newHeight = oldHeight;
42 | var scaleFactor = 1f;
43 |
44 | // If upsizing wanted or clipping not OK calculate the size of the resulting bitmap
45 | if (upsizeOk || !clipOk)
46 | {
47 | double angleRadians = angleDegrees * Math.PI / 180d;
48 |
49 | double cos = Math.Abs(Math.Cos(angleRadians));
50 | double sin = Math.Abs(Math.Sin(angleRadians));
51 | newWidth = (int)Math.Round(oldWidth * cos + oldHeight * sin);
52 | newHeight = (int)Math.Round(oldWidth * sin + oldHeight * cos);
53 | }
54 |
55 | // If upsizing not wanted and clipping not OK need a scaling factor
56 | if (!upsizeOk && !clipOk)
57 | {
58 | scaleFactor = Math.Min((float)oldWidth / newWidth, (float)oldHeight / newHeight);
59 | newWidth = oldWidth;
60 | newHeight = oldHeight;
61 | }
62 |
63 | // Create the new bitmap object. If background color is transparent it must be 32-bit,
64 | // otherwise 24-bit is good enough.
65 | var newBitmap = new Bitmap(newWidth, newHeight,
66 | backgroundColor == Color.Transparent ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb);
67 | newBitmap.SetResolution(inputImage.HorizontalResolution, inputImage.VerticalResolution);
68 |
69 | // Create the Graphics object that does the work
70 | using (Graphics graphicsObject = Graphics.FromImage(newBitmap))
71 | {
72 | graphicsObject.InterpolationMode = InterpolationMode.HighQualityBicubic;
73 | graphicsObject.PixelOffsetMode = PixelOffsetMode.HighQuality;
74 | graphicsObject.SmoothingMode = SmoothingMode.HighQuality;
75 |
76 | // Fill in the specified background color if necessary
77 | if (backgroundColor != Color.Transparent)
78 | graphicsObject.Clear(backgroundColor);
79 |
80 | // Set up the built-in transformation matrix to do the rotation and maybe scaling
81 | graphicsObject.TranslateTransform(newWidth / 2f, newHeight / 2f);
82 |
83 | if (scaleFactor != 1f)
84 | graphicsObject.ScaleTransform(scaleFactor, scaleFactor);
85 |
86 | graphicsObject.RotateTransform(angleDegrees);
87 | graphicsObject.TranslateTransform(-oldWidth / 2f, -oldHeight / 2f);
88 |
89 | // Draw the result
90 | graphicsObject.DrawImage(inputImage, 0, 0);
91 | }
92 |
93 | return newBitmap;
94 | }
95 |
96 | public static (Bitmap, Point) CropBitmap(Bitmap originalBitmap)
97 | {
98 | // Find the min/max non-white/transparent pixels
99 | var min = new Point(int.MaxValue, int.MaxValue);
100 | var max = new Point(int.MinValue, int.MinValue);
101 |
102 | unsafe
103 | {
104 | var bData = originalBitmap.LockBits(new Rectangle(0, 0, originalBitmap.Width, originalBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
105 | byte bitsPerPixel = 32;
106 | byte* scan0 = (byte*)bData.Scan0.ToPointer();
107 |
108 | for (int y = 0; y < bData.Height; ++y)
109 | {
110 | for (int x = 0; x < bData.Width; ++x)
111 | {
112 | byte* data = scan0 + y * bData.Stride + x * bitsPerPixel / 8;
113 | // data[0 = blue, 1 = green, 2 = red, 3 = alpha]
114 | if (data[3] == byte.MaxValue)
115 | {
116 | if (x < min.X) min.X = x;
117 | if (y < min.Y) min.Y = y;
118 |
119 | if (x > max.X) max.X = x;
120 | if (y > max.Y) max.Y = y;
121 | }
122 | }
123 | }
124 | originalBitmap.UnlockBits(bData);
125 | }
126 |
127 | // Create a new bitmap from the crop rectangle
128 | var cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X, max.Y - min.Y);
129 | var newBitmap = new Bitmap(cropRectangle.Width, cropRectangle.Height);
130 | using (Graphics g = Graphics.FromImage(newBitmap))
131 | {
132 | g.DrawImage(originalBitmap, 0, 0, cropRectangle, GraphicsUnit.Pixel);
133 | }
134 |
135 | return (newBitmap, min);
136 | }
137 |
138 | ///
139 | /// Resize the image to the specified width and height.
140 | ///
141 | /// The image to resize.
142 | /// The width to resize to.
143 | /// The height to resize to.
144 | /// The resized image.
145 | public static Bitmap ResizeImage(Image image, int width, int height)
146 | {
147 | var destRect = new Rectangle(0, 0, width, height);
148 | var destImage = new Bitmap(width, height);
149 |
150 | destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
151 |
152 | using (Graphics graphics = Graphics.FromImage(destImage))
153 | {
154 | graphics.CompositingMode = CompositingMode.SourceCopy;
155 | graphics.CompositingQuality = CompositingQuality.HighQuality;
156 | graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
157 | graphics.SmoothingMode = SmoothingMode.HighQuality;
158 | graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
159 |
160 | using (var wrapMode = new ImageAttributes())
161 | {
162 | wrapMode.SetWrapMode(WrapMode.TileFlipXY);
163 | graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
164 | }
165 | }
166 |
167 | return destImage;
168 | }
169 |
170 | public static Bitmap CreateFilledRectangle(Color color, int width, int height)
171 | {
172 | var rectangle = new Bitmap(width, height, PixelFormat.Format32bppArgb);
173 | Graphics graphics = Graphics.FromImage(rectangle);
174 | graphics.SmoothingMode = SmoothingMode.AntiAlias;
175 | graphics.FillRectangle(new SolidBrush(color), 0, 0, width, height);
176 | graphics.Dispose();
177 | return rectangle;
178 | }
179 |
180 | public static Bitmap CreateFilledEllipse(Color color, int width, int height)
181 | {
182 | var ellipse = new Bitmap(width, height, PixelFormat.Format32bppArgb);
183 | Graphics graphics = Graphics.FromImage(ellipse);
184 | graphics.SmoothingMode = SmoothingMode.AntiAlias;
185 | graphics.FillEllipse(new SolidBrush(color), 0, 0, width, height);
186 | graphics.Dispose();
187 | return ellipse;
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Remove the line below if you want to inherit .editorconfig settings from higher directories
2 | root = true
3 |
4 | # C# files
5 | [*.cs]
6 |
7 | #### Core EditorConfig Options ####
8 |
9 | # Indentation and spacing
10 | indent_size = 4
11 | indent_style = space
12 | tab_width = 4
13 |
14 | # New line preferences
15 | end_of_line = crlf
16 | insert_final_newline = true
17 |
18 | #### .NET Coding Conventions ####
19 |
20 | # Organize usings
21 | dotnet_separate_import_directive_groups = false
22 | dotnet_sort_system_directives_first = false
23 | file_header_template = unset
24 |
25 | # this. and Me. preferences
26 | dotnet_style_qualification_for_event = false:error
27 | dotnet_style_qualification_for_field = false:error
28 | dotnet_style_qualification_for_method = false:error
29 | dotnet_style_qualification_for_property = false:error
30 |
31 | # Language keywords vs BCL types preferences
32 | dotnet_style_predefined_type_for_locals_parameters_members = true:error
33 | dotnet_style_predefined_type_for_member_access = true:error
34 |
35 | # Parentheses preferences
36 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
37 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
38 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary
39 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
40 |
41 | # Modifier preferences
42 | dotnet_style_require_accessibility_modifiers = for_non_interface_members
43 |
44 | # Expression-level preferences
45 | dotnet_style_coalesce_expression = true
46 | dotnet_style_collection_initializer = true
47 | dotnet_style_explicit_tuple_names = true
48 | dotnet_style_null_propagation = true
49 | dotnet_style_object_initializer = true
50 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
51 | dotnet_style_prefer_auto_properties = true
52 | dotnet_style_prefer_compound_assignment = true
53 | dotnet_style_prefer_conditional_expression_over_assignment = true
54 | dotnet_style_prefer_conditional_expression_over_return = true
55 | dotnet_style_prefer_inferred_anonymous_type_member_names = true
56 | dotnet_style_prefer_inferred_tuple_names = true
57 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true
58 | dotnet_style_prefer_simplified_boolean_expressions = true
59 | dotnet_style_prefer_simplified_interpolation = true
60 |
61 | # Field preferences
62 | dotnet_style_readonly_field = true
63 |
64 | # Parameter preferences
65 | dotnet_code_quality_unused_parameters = all
66 |
67 | # Suppression preferences
68 | dotnet_remove_unnecessary_suppression_exclusions = none
69 |
70 | #### C# Coding Conventions ####
71 |
72 | # var preferences
73 | csharp_style_var_elsewhere = false
74 | csharp_style_var_for_built_in_types = true:error
75 | csharp_style_var_when_type_is_apparent = true:error
76 |
77 | # Expression-bodied members
78 | csharp_style_expression_bodied_accessors = true
79 | csharp_style_expression_bodied_constructors = false
80 | csharp_style_expression_bodied_indexers = true
81 | csharp_style_expression_bodied_lambdas = true
82 | csharp_style_expression_bodied_local_functions = false
83 | csharp_style_expression_bodied_methods = false
84 | csharp_style_expression_bodied_operators = false
85 | csharp_style_expression_bodied_properties = true
86 |
87 | # Pattern matching preferences
88 | csharp_style_pattern_matching_over_as_with_null_check = true
89 | csharp_style_pattern_matching_over_is_with_cast_check = true
90 | csharp_style_prefer_not_pattern = true
91 | csharp_style_prefer_pattern_matching = true
92 | csharp_style_prefer_switch_expression = true
93 |
94 | # Null-checking preferences
95 | csharp_style_conditional_delegate_call = true
96 |
97 | # Modifier preferences
98 | csharp_prefer_static_local_function = true
99 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
100 |
101 | # Code-block preferences
102 | csharp_prefer_braces = true
103 | csharp_prefer_simple_using_statement = true
104 |
105 | # Expression-level preferences
106 | csharp_prefer_simple_default_expression = true
107 | csharp_style_deconstructed_variable_declaration = true
108 | csharp_style_implicit_object_creation_when_type_is_apparent = true
109 | csharp_style_inlined_variable_declaration = true
110 | csharp_style_pattern_local_over_anonymous_function = true
111 | csharp_style_prefer_index_operator = true
112 | csharp_style_prefer_range_operator = true
113 | csharp_style_throw_expression = true
114 | csharp_style_unused_value_assignment_preference = discard_variable
115 | csharp_style_unused_value_expression_statement_preference = discard_variable
116 |
117 | # 'using' directive preferences
118 | csharp_using_directive_placement = outside_namespace
119 |
120 | #### C# Formatting Rules ####
121 |
122 | # New line preferences
123 | csharp_new_line_before_catch = true
124 | csharp_new_line_before_else = true
125 | csharp_new_line_before_finally = true
126 | csharp_new_line_before_members_in_anonymous_types = true
127 | csharp_new_line_before_members_in_object_initializers = true
128 | csharp_new_line_before_open_brace = all
129 | csharp_new_line_between_query_expression_clauses = true
130 |
131 | # Indentation preferences
132 | csharp_indent_block_contents = true
133 | csharp_indent_braces = false
134 | csharp_indent_case_contents = true
135 | csharp_indent_case_contents_when_block = true
136 | csharp_indent_labels = one_less_than_current
137 | csharp_indent_switch_labels = true
138 |
139 | # Space preferences
140 | csharp_space_after_cast = false
141 | csharp_space_after_colon_in_inheritance_clause = true
142 | csharp_space_after_comma = true
143 | csharp_space_after_dot = false
144 | csharp_space_after_keywords_in_control_flow_statements = true
145 | csharp_space_after_semicolon_in_for_statement = true
146 | csharp_space_around_binary_operators = before_and_after
147 | csharp_space_around_declaration_statements = false
148 | csharp_space_before_colon_in_inheritance_clause = true
149 | csharp_space_before_comma = false
150 | csharp_space_before_dot = false
151 | csharp_space_before_open_square_brackets = false
152 | csharp_space_before_semicolon_in_for_statement = false
153 | csharp_space_between_empty_square_brackets = false
154 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
155 | csharp_space_between_method_call_name_and_opening_parenthesis = false
156 | csharp_space_between_method_call_parameter_list_parentheses = false
157 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
158 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
159 | csharp_space_between_method_declaration_parameter_list_parentheses = false
160 | csharp_space_between_parentheses = false
161 | csharp_space_between_square_brackets = false
162 |
163 | # Wrapping preferences
164 | csharp_preserve_single_line_blocks = true
165 | csharp_preserve_single_line_statements = true
166 |
167 | #### Naming styles ####
168 |
169 | # Naming rules
170 |
171 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
172 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
173 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
174 |
175 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
176 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
177 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
178 |
179 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
180 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
181 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
182 |
183 | # Symbol specifications
184 |
185 | dotnet_naming_symbols.interface.applicable_kinds = interface
186 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
187 | dotnet_naming_symbols.interface.required_modifiers =
188 |
189 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
190 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
191 | dotnet_naming_symbols.types.required_modifiers =
192 |
193 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
194 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
195 | dotnet_naming_symbols.non_field_members.required_modifiers =
196 |
197 | # Naming styles
198 |
199 | dotnet_naming_style.pascal_case.required_prefix =
200 | dotnet_naming_style.pascal_case.required_suffix =
201 | dotnet_naming_style.pascal_case.word_separator =
202 | dotnet_naming_style.pascal_case.capitalization = pascal_case
203 |
204 | dotnet_naming_style.begins_with_i.required_prefix = I
205 | dotnet_naming_style.begins_with_i.required_suffix =
206 | dotnet_naming_style.begins_with_i.word_separator =
207 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
208 |
--------------------------------------------------------------------------------
/Helpers/Compositor.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Collections.Generic;
22 | using System.Drawing;
23 | using System.Drawing.Drawing2D;
24 | using System.Drawing.Imaging;
25 | using MapAssist.Types;
26 | using MapAssist.Settings;
27 |
28 | namespace MapAssist.Helpers
29 | {
30 | public class Compositor
31 | {
32 | private readonly AreaData _areaData;
33 | private readonly Bitmap _background;
34 | public readonly Point CropOffset;
35 | private readonly IReadOnlyList _pointsOfInterest;
36 | private readonly Dictionary<(string, int), Font> _fontCache = new Dictionary<(string, int), Font>();
37 |
38 | private readonly Dictionary<(Shape, int, Color), Bitmap> _iconCache =
39 | new Dictionary<(Shape, int, Color), Bitmap>();
40 |
41 | public Compositor(AreaData areaData, IReadOnlyList pointOfInterest)
42 | {
43 | _areaData = areaData;
44 | _pointsOfInterest = pointOfInterest;
45 | (_background, CropOffset) = DrawBackground(areaData, pointOfInterest);
46 | }
47 |
48 | public Bitmap Compose(GameData gameData, bool scale = true)
49 | {
50 | if (gameData.Area != _areaData.Area)
51 | {
52 | throw new ApplicationException("Asked to compose an image for a different area." +
53 | $"Compositor area: {_areaData.Area}, Game data: {gameData.Area}");
54 | }
55 |
56 | var image = (Bitmap)_background.Clone();
57 |
58 | using (Graphics imageGraphics = Graphics.FromImage(image))
59 | {
60 | imageGraphics.CompositingQuality = CompositingQuality.HighQuality;
61 | imageGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
62 | imageGraphics.SmoothingMode = SmoothingMode.HighQuality;
63 | imageGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
64 |
65 | Point localPlayerPosition = gameData.PlayerPosition
66 | .OffsetFrom(_areaData.Origin)
67 | .OffsetFrom(CropOffset)
68 | .OffsetFrom(new Point(Settings.Rendering.Player.IconSize, Settings.Rendering.Player.IconSize));
69 |
70 | if (Settings.Rendering.Player.CanDrawIcon())
71 | {
72 | Bitmap playerIcon = GetIcon(Settings.Rendering.Player);
73 | imageGraphics.DrawImage(playerIcon, localPlayerPosition);
74 | }
75 |
76 | // The lines are dynamic, and follow the player, so have to be drawn here.
77 | // The rest can be done in DrawBackground.
78 | foreach (PointOfInterest poi in _pointsOfInterest)
79 | {
80 | if (poi.RenderingSettings.CanDrawLine())
81 | {
82 | var pen = new Pen(poi.RenderingSettings.LineColor, poi.RenderingSettings.LineThickness);
83 | if (poi.RenderingSettings.CanDrawArrowHead())
84 | {
85 | pen.CustomEndCap = new AdjustableArrowCap(poi.RenderingSettings.ArrowHeadSize,
86 | poi.RenderingSettings.ArrowHeadSize);
87 | }
88 |
89 | imageGraphics.DrawLine(pen, localPlayerPosition,
90 | poi.Position.OffsetFrom(_areaData.Origin).OffsetFrom(CropOffset));
91 | }
92 | }
93 | MobRendering render = Utils.GetMobRendering();
94 | foreach (var monster in GameMemory.Monsters)
95 | {
96 | var clr = monster.UniqueFlag == 0 ? render.NormalColor : render.UniqueColor;
97 | var pen = new Pen(clr, 1);
98 | var sz = new Size(5, 5);
99 | var sz2 = new Size(2, 2);
100 | var midPoint = monster.Position.OffsetFrom(_areaData.Origin).OffsetFrom(CropOffset);
101 | var rect = new Rectangle(midPoint, sz);
102 | imageGraphics.DrawRectangle(pen, rect);
103 | var i = 0;
104 | foreach(var immunity in monster.Immunities)
105 | {
106 | var brush = new SolidBrush(ResistColors.ResistColor[immunity]);
107 | var iPoint = new Point((i * -2) + (1 * (monster.Immunities.Count - 1)) - 1, 3);
108 | var pen2 = new Pen(ResistColors.ResistColor[immunity], 1);
109 | var rect2 = new Rectangle(midPoint.OffsetFrom(iPoint), sz2);
110 | imageGraphics.FillRectangle(brush, rect2);
111 | i++;
112 | }
113 | }
114 | }
115 |
116 | double multiplier = 1;
117 |
118 | if (scale)
119 | {
120 | double biggestDimension = Math.Max(image.Width, image.Height);
121 |
122 | multiplier = Settings.Map.Size / biggestDimension;
123 |
124 | if (multiplier == 0)
125 | {
126 | multiplier = 1;
127 | }
128 | }
129 |
130 | // ReSharper disable once CompareOfFloatsByEqualityOperator
131 | if (multiplier != 1)
132 | {
133 | image = ImageUtils.ResizeImage(image, (int)(image.Width * multiplier),
134 | (int)(image.Height * multiplier));
135 | }
136 |
137 | // ReSharper disable once ConditionIsAlwaysTrueOrFalse
138 | if (scale && Settings.Map.Rotate)
139 | {
140 | image = ImageUtils.RotateImage(image, 53, true, false, Color.Transparent);
141 | }
142 |
143 | return image;
144 | }
145 |
146 | private (Bitmap, Point) DrawBackground(AreaData areaData, IReadOnlyList pointOfInterest)
147 | {
148 | var background = new Bitmap(areaData.CollisionGrid[0].Length, areaData.CollisionGrid.Length,
149 | PixelFormat.Format32bppArgb);
150 | using (Graphics backgroundGraphics = Graphics.FromImage(background))
151 | {
152 | backgroundGraphics.FillRectangle(new SolidBrush(Color.Transparent), 0, 0,
153 | areaData.CollisionGrid[0].Length,
154 | areaData.CollisionGrid.Length);
155 | backgroundGraphics.CompositingQuality = CompositingQuality.HighQuality;
156 | backgroundGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
157 | backgroundGraphics.SmoothingMode = SmoothingMode.HighQuality;
158 | backgroundGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
159 |
160 | for (var y = 0; y < areaData.CollisionGrid.Length; y++)
161 | {
162 | for (var x = 0; x < areaData.CollisionGrid[y].Length; x++)
163 | {
164 | int type = areaData.CollisionGrid[y][x];
165 | Color? typeColor = Settings.Map.MapColors[type];
166 | if (typeColor != null)
167 | {
168 | background.SetPixel(x, y, (Color)typeColor);
169 | }
170 | }
171 | }
172 |
173 | foreach (PointOfInterest poi in pointOfInterest)
174 | {
175 | if (poi.RenderingSettings.CanDrawIcon())
176 | {
177 | Bitmap icon = GetIcon(poi.RenderingSettings);
178 | backgroundGraphics.DrawImage(icon, poi.Position.OffsetFrom(areaData.Origin));
179 | }
180 |
181 | if (!string.IsNullOrWhiteSpace(poi.Label) && poi.RenderingSettings.CanDrawLabel())
182 | {
183 | Font font = GetFont(poi.RenderingSettings);
184 | backgroundGraphics.DrawString(poi.Label, font,
185 | new SolidBrush(poi.RenderingSettings.LabelColor),
186 | poi.Position.OffsetFrom(areaData.Origin));
187 | }
188 | }
189 |
190 | return ImageUtils.CropBitmap(background);
191 | }
192 | }
193 |
194 | public Font GetFont(string fontStr, int fontSize)
195 | {
196 | (string LabelFont, int LabelFontSize) cacheKey = (fontStr, fontSize);
197 | if (!_fontCache.ContainsKey(cacheKey))
198 | {
199 | var font = new Font(fontStr,
200 | fontSize);
201 | _fontCache[cacheKey] = font;
202 | }
203 |
204 | return _fontCache[cacheKey];
205 | }
206 | private Font GetFont(PointOfInterestRendering poiSettings)
207 | {
208 | (string LabelFont, int LabelFontSize) cacheKey = (poiSettings.LabelFont, poiSettings.LabelFontSize);
209 | if (!_fontCache.ContainsKey(cacheKey))
210 | {
211 | var font = new Font(poiSettings.LabelFont,
212 | poiSettings.LabelFontSize);
213 | _fontCache[cacheKey] = font;
214 | }
215 |
216 | return _fontCache[cacheKey];
217 | }
218 |
219 | private Bitmap GetIcon(PointOfInterestRendering poiSettings)
220 | {
221 | (Shape IconShape, int IconSize, Color Color) cacheKey = (poiSettings.IconShape, poiSettings.IconSize, Color: poiSettings.IconColor);
222 | if (!_iconCache.ContainsKey(cacheKey))
223 | {
224 | var bitmap = new Bitmap(poiSettings.IconSize, poiSettings.IconSize, PixelFormat.Format32bppArgb);
225 | using (Graphics g = Graphics.FromImage(bitmap))
226 | {
227 | g.SmoothingMode = SmoothingMode.AntiAlias;
228 | switch (poiSettings.IconShape)
229 | {
230 | case Shape.Ellipse:
231 | g.FillEllipse(new SolidBrush(poiSettings.IconColor), 0, 0, poiSettings.IconSize,
232 | poiSettings.IconSize);
233 | break;
234 | case Shape.Rectangle:
235 | g.FillRectangle(new SolidBrush(poiSettings.IconColor), 0, 0, poiSettings.IconSize,
236 | poiSettings.IconSize);
237 | break;
238 | }
239 | }
240 |
241 | _iconCache[cacheKey] = bitmap;
242 | }
243 |
244 | return _iconCache[cacheKey];
245 | }
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/Types/Area.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System.Collections.Generic;
21 |
22 | namespace MapAssist.Types
23 | {
24 | public enum Area : uint
25 | {
26 | Abaddon = 125,
27 | AncientTunnels = 65,
28 | ArcaneSanctuary = 74,
29 | ArreatPlateau = 112,
30 | ArreatSummit = 120,
31 | Barracks = 28,
32 | BlackMarsh = 6,
33 | BloodMoor = 2,
34 | BloodyFoothills = 110,
35 | BurialGrounds = 17,
36 | CanyonOfTheMagi = 46,
37 | CatacombsLevel1 = 34,
38 | CatacombsLevel2 = 35,
39 | CatacombsLevel3 = 36,
40 | CatacombsLevel4 = 37,
41 | Cathedral = 33,
42 | CaveLevel1 = 9,
43 | CaveLevel2 = 13,
44 | ChaosSanctuary = 108,
45 | CityOfTheDamned = 106,
46 | ClawViperTempleLevel1 = 58,
47 | ClawViperTempleLevel2 = 61,
48 | ColdPlains = 3,
49 | Crypt = 18,
50 | CrystallinePassage = 113,
51 | DarkWood = 5,
52 | DenOfEvil = 8,
53 | DisusedFane = 95,
54 | DisusedReliquary = 99,
55 | DrifterCavern = 116,
56 | DryHills = 42,
57 | DuranceOfHateLevel1 = 100,
58 | DuranceOfHateLevel2 = 101,
59 | DuranceOfHateLevel3 = 102,
60 | DurielsLair = 73,
61 | FarOasis = 43,
62 | FlayerDungeonLevel1 = 88,
63 | FlayerDungeonLevel2 = 89,
64 | FlayerDungeonLevel3 = 91,
65 | FlayerJungle = 78,
66 | ForgottenReliquary = 96,
67 | ForgottenSands = 134,
68 | ForgottenTemple = 97,
69 | ForgottenTower = 20,
70 | FrigidHighlands = 111,
71 | FrozenRiver = 114,
72 | FrozenTundra = 117,
73 | FurnaceOfPain = 135,
74 | GlacialTrail = 115,
75 | GreatMarsh = 77,
76 | HallsOfAnguish = 122,
77 | HallsOfPain = 123,
78 | HallsOfTheDeadLevel1 = 56,
79 | HallsOfTheDeadLevel2 = 57,
80 | HallsOfTheDeadLevel3 = 60,
81 | HallsOfVaught = 124,
82 | HaremLevel1 = 50,
83 | HaremLevel2 = 51,
84 | Harrogath = 109,
85 | HoleLevel1 = 11,
86 | HoleLevel2 = 15,
87 | IcyCellar = 119,
88 | InfernalPit = 127,
89 | InnerCloister = 32,
90 | JailLevel1 = 29,
91 | JailLevel2 = 30,
92 | JailLevel3 = 31,
93 | KurastBazaar = 80,
94 | KurastCauseway = 82,
95 | KurastDocks = 75,
96 | LostCity = 44,
97 | LowerKurast = 79,
98 | LutGholein = 40,
99 | MaggotLairLevel1 = 62,
100 | MaggotLairLevel2 = 63,
101 | MaggotLairLevel3 = 64,
102 | MatronsDen = 133,
103 | Mausoleum = 19,
104 | MonasteryGate = 26,
105 | MooMooFarm = 39,
106 | NihlathaksTemple = 121,
107 | None = 0,
108 | OuterCloister = 27,
109 | OuterSteppes = 104,
110 | PalaceCellarLevel1 = 52,
111 | PalaceCellarLevel2 = 53,
112 | PalaceCellarLevel3 = 54,
113 | PitLevel1 = 12,
114 | PitLevel2 = 16,
115 | PitOfAcheron = 126,
116 | PlainsOfDespair = 105,
117 | RiverOfFlame = 107,
118 | RockyWaste = 41,
119 | RogueEncampment = 1,
120 | RuinedFane = 98,
121 | RuinedTemple = 94,
122 | SewersLevel1Act2 = 47,
123 | SewersLevel1Act3 = 92,
124 | SewersLevel2Act2 = 48,
125 | SewersLevel2Act3 = 93,
126 | SewersLevel3Act2 = 49,
127 | SpiderCave = 84,
128 | SpiderCavern = 85,
129 | SpiderForest = 76,
130 | StonyField = 4,
131 | StonyTombLevel1 = 55,
132 | StonyTombLevel2 = 59,
133 | SwampyPitLevel1 = 86,
134 | SwampyPitLevel2 = 87,
135 | SwampyPitLevel3 = 90,
136 | TalRashasTomb1 = 66,
137 | TalRashasTomb2 = 67,
138 | TalRashasTomb3 = 68,
139 | TalRashasTomb4 = 69,
140 | TalRashasTomb5 = 70,
141 | TalRashasTomb6 = 71,
142 | TalRashasTomb7 = 72,
143 | TamoeHighland = 7,
144 | TheAncientsWay = 118,
145 | ThePandemoniumFortress = 103,
146 | TheWorldstoneChamber = 132,
147 | TheWorldStoneKeepLevel1 = 128,
148 | TheWorldStoneKeepLevel2 = 129,
149 | TheWorldStoneKeepLevel3 = 130,
150 | ThroneOfDestruction = 131,
151 | TowerCellarLevel1 = 21,
152 | TowerCellarLevel2 = 22,
153 | TowerCellarLevel3 = 23,
154 | TowerCellarLevel4 = 24,
155 | TowerCellarLevel5 = 25,
156 | Travincal = 83,
157 | Tristram = 38,
158 | UberTristram = 136,
159 | UndergroundPassageLevel1 = 10,
160 | UndergroundPassageLevel2 = 14,
161 | UpperKurast = 81,
162 | ValleyOfSnakes = 45,
163 | MapsAncientTemple = 137,
164 | MapsDesecratedTemple = 138,
165 | MapsFrigidPlateau = 139,
166 | MapsInfernalTrial = 140,
167 | MapsRuinedCitadel = 141,
168 | }
169 |
170 | public static class AreaExtensions
171 | {
172 | private readonly static Dictionary _areaNames = new Dictionary()
173 | {
174 | { 0, "None" },
175 | { 1, "Rogue Encampment" },
176 | { 2, "Blood Moor" },
177 | { 3, "Cold Plains" },
178 | { 4, "Stony Field" },
179 | { 5, "Dark Wood" },
180 | { 6, "Black Marsh" },
181 | { 7, "Tamoe Highland" },
182 | { 8, "Den Of Evil" },
183 | { 9, "Cave Level 1" },
184 | { 10, "Underground Passage Level 1" },
185 | { 11, "Hole Level 1" },
186 | { 12, "Pit Level 1" },
187 | { 13, "Cave Level 2" },
188 | { 14, "Underground Passage Level 2" },
189 | { 15, "Hole Level 2" },
190 | { 16, "Pit Level 2" },
191 | { 17, "Burial Grounds" },
192 | { 18, "Crypt" },
193 | { 19, "Mausoleum" },
194 | { 20, "Forgotten Tower" },
195 | { 21, "Tower Cellar Level 1" },
196 | { 22, "Tower Cellar Level 2" },
197 | { 23, "Tower Cellar Level 3" },
198 | { 24, "Tower Cellar Level 4" },
199 | { 25, "Tower Cellar Level 5" },
200 | { 26, "Monastery Gate" },
201 | { 27, "Outer Cloister" },
202 | { 28, "Barracks" },
203 | { 29, "Jail Level 1" },
204 | { 30, "Jail Level 2" },
205 | { 31, "Jail Level 3" },
206 | { 32, "Inner Cloister" },
207 | { 33, "Cathedral" },
208 | { 34, "Catacombs Level 1" },
209 | { 35, "Catacombs Level 2" },
210 | { 36, "Catacombs Level 3" },
211 | { 37, "Catacombs Level 4" },
212 | { 38, "Tristram" },
213 | { 39, "Moo Moo Farm" },
214 | { 40, "Lut Gholein" },
215 | { 41, "Rocky Waste" },
216 | { 42, "Dry Hills" },
217 | { 43, "Far Oasis" },
218 | { 44, "Lost City" },
219 | { 45, "Valley Of Snakes" },
220 | { 46, "Canyon Of The Magi" },
221 | { 47, "A2 Sewers Level 1" },
222 | { 48, "A2 Sewers Level 2" },
223 | { 49, "A2 Sewers Level 3" },
224 | { 50, "Harem Level 1" },
225 | { 51, "Harem Level 2" },
226 | { 52, "Palace Cellar Level 1" },
227 | { 53, "Palace Cellar Level 2" },
228 | { 54, "Palace Cellar Level 3" },
229 | { 55, "Stony Tomb Level 1" },
230 | { 56, "Halls Of The Dead Level 1" },
231 | { 57, "Halls Of The Dead Level 2" },
232 | { 58, "Claw Viper Temple Level 1" },
233 | { 59, "Stony Tomb Level 2" },
234 | { 60, "Halls Of The Dead Level 3" },
235 | { 61, "Claw Viper Temple Level 2" },
236 | { 62, "Maggot Lair Level 1" },
237 | { 63, "Maggot Lair Level 2" },
238 | { 64, "Maggot Lair Level 3" },
239 | { 65, "Ancient Tunnels" },
240 | { 66, "Tal Rashas Tomb #1" },
241 | { 67, "Tal Rashas Tomb #2" },
242 | { 68, "Tal Rashas Tomb #3" },
243 | { 69, "Tal Rashas Tomb #4" },
244 | { 70, "Tal Rashas Tomb #5" },
245 | { 71, "Tal Rashas Tomb #6" },
246 | { 72, "Tal Rashas Tomb #7" },
247 | { 73, "Duriels Lair" },
248 | { 74, "Arcane Sanctuary" },
249 | { 75, "Kurast Docktown" },
250 | { 76, "Spider Forest" },
251 | { 77, "Great Marsh" },
252 | { 78, "Flayer Jungle" },
253 | { 79, "Lower Kurast" },
254 | { 80, "Kurast Bazaar" },
255 | { 81, "Upper Kurast" },
256 | { 82, "Kurast Causeway" },
257 | { 83, "Travincal" },
258 | { 84, "Spider Cave" },
259 | { 85, "Spider Cavern" },
260 | { 86, "Swampy Pit Level 1" },
261 | { 87, "Swampy Pit Level 2" },
262 | { 88, "Flayer Dungeon Level 1" },
263 | { 89, "Flayer Dungeon Level 2" },
264 | { 90, "Swampy Pit Level 3" },
265 | { 91, "Flayer Dungeon Level 3" },
266 | { 92, "A3 Sewers Level 1" },
267 | { 93, "A3 Sewers Level 2" },
268 | { 94, "Ruined Temple" },
269 | { 95, "Disused Fane" },
270 | { 96, "Forgotten Reliquary" },
271 | { 97, "Forgotten Temple" },
272 | { 98, "Ruined Fane" },
273 | { 99, "Disused Reliquary" },
274 | { 100, "Durance Of Hate Level 1" },
275 | { 101, "Durance Of Hate Level 2" },
276 | { 102, "Durance Of Hate Level 3" },
277 | { 103, "The Pandemonium Fortress" },
278 | { 104, "Outer Steppes" },
279 | { 105, "Plains Of Despair" },
280 | { 106, "City Of The Damned" },
281 | { 107, "River Of Flame" },
282 | { 108, "Chaos Sanctuary" },
283 | { 109, "Harrogath" },
284 | { 110, "Bloody Foothills" },
285 | { 111, "Frigid Highlands" },
286 | { 112, "Arreat Plateau" },
287 | { 113, "Crystalline Passage" },
288 | { 114, "Frozen River" },
289 | { 115, "Glacial Trail" },
290 | { 116, "Drifter Cavern" },
291 | { 117, "Frozen Tundra" },
292 | { 118, "Ancient\'s Way" },
293 | { 119, "Icy Cellar" },
294 | { 120, "Arreat Summit" },
295 | { 121, "Nihlathaks Temple" },
296 | { 122, "Halls Of Anguish" },
297 | { 123, "Halls Of Pain" },
298 | { 124, "Halls Of Vaught" },
299 | { 125, "Abaddon" },
300 | { 126, "Pit Of Acheron" },
301 | { 127, "Infernal Pit" },
302 | { 128, "The Worldstone Keep Level 1" },
303 | { 129, "The Worldstone Keep Level 2" },
304 | { 130, "The Worldstone Keep Level 3" },
305 | { 131, "Throne Of Destruction" },
306 | { 132, "The Worldstone Chamber" },
307 | { 133, "Matron\'s Den" },
308 | { 134, "Fogotten Sands" },
309 | { 135, "Furnace of Pain" },
310 | { 136, "Tristram" }
311 | };
312 |
313 | public static string Name(this Area area)
314 | {
315 | return _areaNames.TryGetValue((int)area, out var areaName) ? areaName : area.ToString();
316 | }
317 |
318 | public static bool IsValid(this Area area)
319 | {
320 | return (uint)area >= 1 && (uint)area <= 136;
321 | }
322 | }
323 | }
324 |
--------------------------------------------------------------------------------
/Overlay.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Collections.Generic;
22 | using System.Drawing;
23 | using System.Windows.Forms;
24 | using MapAssist.Types;
25 | using MapAssist.Helpers;
26 | using MapAssist.Settings;
27 | using Gma.System.MouseKeyHook;
28 | using System.Numerics;
29 | using System.Configuration;
30 | using System.Diagnostics;
31 |
32 | namespace MapAssist
33 | {
34 | public partial class Overlay : Form
35 | {
36 | // Move to windows external
37 | private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
38 | private const uint SWP_NOSIZE = 0x0001;
39 | private const uint SWP_NOMOVE = 0x0002;
40 | private const uint TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
41 | private readonly Timer _timer = new Timer();
42 | private GameData _currentGameData;
43 | private Compositor _compositor;
44 | private AreaData _areaData;
45 | private MapApi _mapApi;
46 | private bool _show = true;
47 | private Screen _screen;
48 |
49 | public Overlay(IKeyboardMouseEvents keyboardMouseEvents)
50 | {
51 | InitializeComponent();
52 | keyboardMouseEvents.KeyPress += (_, args) =>
53 | {
54 | if (InGame())
55 | {
56 | if (args.KeyChar == Map.ToggleKey)
57 | {
58 | _show = !_show;
59 | }
60 | if (args.KeyChar == Map.ZoomInKey)
61 | {
62 | if (Map.ZoomLevel > 0.25f)
63 | {
64 | Map.ZoomLevel -= 0.25f;
65 | Map.Size = (int)(Map.Size * 1.15f);
66 | }
67 | }
68 | if (args.KeyChar == Map.ZoomOutKey)
69 | {
70 | if (Map.ZoomLevel < 4f)
71 | {
72 | Map.ZoomLevel += 0.25f;
73 | Map.Size = (int)(Map.Size * .85f);
74 | }
75 | }
76 | }
77 | };
78 | }
79 |
80 | private void Overlay_Load(object sender, EventArgs e)
81 | {
82 | Map.InitMapColors();
83 | Rectangle screen = Screen.PrimaryScreen.WorkingArea;
84 | var width = Width >= screen.Width ? screen.Width : (screen.Width + Width) / 2;
85 | var height = Height >= screen.Height ? screen.Height : (screen.Height + Height) / 2;
86 | Location = new Point((screen.Width - width) / 2, (screen.Height - height) / 2);
87 | Size = new Size(width, height);
88 | Opacity = Map.Opacity;
89 |
90 | _timer.Interval = Map.UpdateTime;
91 | _timer.Tick += MapUpdateTimer_Tick;
92 | _timer.Start();
93 |
94 | if (Map.AlwaysOnTop) SetTopMost();
95 |
96 | mapOverlay.Location = new Point(0, 0);
97 | mapOverlay.Width = Width;
98 | mapOverlay.Height = Height;
99 | mapOverlay.BackColor = Color.Transparent;
100 | }
101 |
102 | private void Overlay_FormClosing(object sender, EventArgs e)
103 | {
104 | _mapApi?.Dispose();
105 | }
106 |
107 | private void MapUpdateTimer_Tick(object sender, EventArgs e)
108 | {
109 | _timer.Stop();
110 |
111 | GameData gameData = GameMemory.GetGameData();
112 | if (gameData != null)
113 | {
114 | if (gameData.HasGameChanged(_currentGameData))
115 | {
116 | Console.WriteLine($"Game changed: {gameData}");
117 | _mapApi?.Dispose();
118 | _mapApi = new MapApi(MapApi.Client, gameData.Difficulty, gameData.MapSeed);
119 | }
120 |
121 | if (gameData.HasMapChanged(_currentGameData))
122 | {
123 | Debug.WriteLine($"Area changed: {gameData.Area}");
124 | if (gameData.Area != Area.None)
125 | {
126 | _areaData = _mapApi.GetMapData(gameData.Area);
127 | List pointsOfInterest = PointOfInterestHandler.Get(_mapApi, _areaData);
128 | _compositor = new Compositor(_areaData, pointsOfInterest);
129 | }
130 | else
131 | {
132 | _compositor = null;
133 | }
134 | }
135 | }
136 |
137 | _currentGameData = gameData;
138 |
139 | if (ShouldHideMap())
140 | {
141 | mapOverlay.Hide();
142 | }
143 | else
144 | {
145 | if (!mapOverlay.Visible)
146 | {
147 | mapOverlay.Show();
148 | if (Map.AlwaysOnTop) SetTopMost();
149 | }
150 | mapOverlay.Refresh();
151 | }
152 |
153 | _timer.Start();
154 | }
155 |
156 | private void SetTopMost()
157 | {
158 | var initialStyle = (uint)WindowsExternal.GetWindowLongPtr(Handle, -20);
159 | WindowsExternal.SetWindowLong(Handle, -20, initialStyle | 0x80000 | 0x20);
160 | WindowsExternal.SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
161 | }
162 |
163 | private bool ShouldHideMap()
164 | {
165 | if (!_show) return true;
166 | if (!InGame()) return true;
167 | if (_currentGameData.Area == Area.None) return true;
168 | if (Array.Exists(Map.HiddenAreas, element => element == _currentGameData.Area)) return true;
169 | if (Map.ToggleViaInGameMap && !_currentGameData.MapShown) return true;
170 | return false;
171 | }
172 |
173 | private bool InGame()
174 | {
175 | return _currentGameData != null && _currentGameData.MainWindowHandle != IntPtr.Zero &&
176 | WindowsExternal.GetForegroundWindow() == _currentGameData.MainWindowHandle;
177 | }
178 |
179 | private void MapOverlay_Paint(object sender, PaintEventArgs e)
180 | {
181 | if (_compositor == null)
182 | {
183 | return;
184 | }
185 |
186 | UpdateLocation();
187 |
188 | Bitmap gameMap = _compositor.Compose(_currentGameData, !Map.OverlayMode);
189 |
190 | var msgCount = 0;
191 | foreach (var warning in GameMemory.WarningMessages)
192 | {
193 | var fontSize = Map.WarnImmuneNPCFontSize;
194 | Font font = _compositor.GetFont(Map.WarnImmuneNPCFont, fontSize);
195 | var stringFormat = new StringFormat();
196 | stringFormat.Alignment = Map.WarnNPCHorizontalAlign;
197 | stringFormat.LineAlignment = Map.WarnNPCVerticalAlign;
198 | e.Graphics.DrawString(warning, font,
199 | new SolidBrush(Map.WarnNPCFontColor),
200 | new Point(Screen.PrimaryScreen.WorkingArea.Width / 2, 10 + (msgCount * (fontSize + fontSize / 2))), stringFormat);
201 | msgCount++;
202 | }
203 | if (Map.OverlayMode)
204 | {
205 | float w = 0;
206 | float h = 0;
207 | var scale = 0.0F;
208 | var center = new Vector2();
209 |
210 | if (ConfigurationManager.AppSettings["ZoomLevelDefault"] == null) { Map.ZoomLevel = 1; }
211 |
212 | switch (Map.Position)
213 | {
214 | case MapPosition.Center:
215 | w = _screen.WorkingArea.Width;
216 | h = _screen.WorkingArea.Height;
217 | scale = (1024.0F / h * w * 3f / 4f / 2.3F) * Map.ZoomLevel;
218 | center = new Vector2(w / 2, h / 2 + 20);
219 |
220 | e.Graphics.SetClip(new RectangleF(0, 0, w, h));
221 | break;
222 | case MapPosition.TopLeft:
223 | w = 640;
224 | h = 360;
225 | scale = (1024.0F / h * w * 3f / 4f / 3.35F) * Map.ZoomLevel;
226 | center = new Vector2(w / 2, (h / 2) + 48);
227 |
228 | e.Graphics.SetClip(new RectangleF(0, 50, w, h));
229 | break;
230 | case MapPosition.TopRight:
231 | w = 640;
232 | h = 360;
233 | scale = (1024.0F / h * w * 3f / 4f / 3.35F) * Map.ZoomLevel;
234 | center = new Vector2(w / 2, (h / 2) + 40);
235 |
236 | e.Graphics.TranslateTransform(_screen.WorkingArea.Width - w, -8);
237 | e.Graphics.SetClip(new RectangleF(0, 50, w, h));
238 | break;
239 | }
240 |
241 | Point playerPosInArea = _currentGameData.PlayerPosition.OffsetFrom(_areaData.Origin).OffsetFrom(_compositor.CropOffset);
242 |
243 | var playerPos = new Vector2(playerPosInArea.X, playerPosInArea.Y);
244 | Vector2 Transform(Vector2 p) =>
245 | center +
246 | DeltaInWorldToMinimapDelta(
247 | p - playerPos,
248 | (float)Math.Sqrt(w * w + h * h),
249 | scale,
250 | 0);
251 |
252 | var p1 = Transform(new Vector2(0, 0));
253 | var p2 = Transform(new Vector2(gameMap.Width, 0));
254 | var p4 = Transform(new Vector2(0, gameMap.Height));
255 |
256 | PointF[] destinationPoints = {
257 | new PointF(p1.X, p1.Y),
258 | new PointF(p2.X, p2.Y),
259 | new PointF(p4.X, p4.Y)
260 | };
261 |
262 | e.Graphics.DrawImage(gameMap, destinationPoints);
263 | }
264 | else
265 | {
266 | var anchor = new Point(0, 0);
267 | switch (Map.Position)
268 | {
269 | case MapPosition.Center:
270 | anchor = new Point(_screen.WorkingArea.Width / 2, _screen.WorkingArea.Height / 2);
271 | break;
272 | case MapPosition.TopRight:
273 | anchor = new Point(_screen.WorkingArea.Width - gameMap.Width, 0);
274 | break;
275 | case MapPosition.TopLeft:
276 | anchor = new Point(0, 0);
277 | break;
278 | }
279 |
280 | e.Graphics.DrawImage(gameMap, anchor);
281 | }
282 | }
283 |
284 | public Vector2 DeltaInWorldToMinimapDelta(Vector2 delta, double diag, float scale, float deltaZ = 0)
285 | {
286 | var CAMERA_ANGLE = -26F * 3.14159274F / 180;
287 |
288 | var cos = (float)(diag * Math.Cos(CAMERA_ANGLE) / scale);
289 | var sin = (float)(diag * Math.Sin(CAMERA_ANGLE) /
290 | scale);
291 |
292 | return new Vector2((delta.X - delta.Y) * cos, deltaZ - (delta.X + delta.Y) * sin);
293 | }
294 |
295 | ///
296 | /// Update the location and size of the form relative to the window location.
297 | ///
298 | private void UpdateLocation()
299 | {
300 | _screen = Screen.FromHandle(_currentGameData.MainWindowHandle);
301 | Location = new Point(_screen.WorkingArea.X, _screen.WorkingArea.Y);
302 | Size = new Size(_screen.WorkingArea.Width, _screen.WorkingArea.Height);
303 | mapOverlay.Size = Size;
304 | }
305 | }
306 | }
307 |
--------------------------------------------------------------------------------
/Types/Stats.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 | using System.Collections.Generic;
20 | using System.Drawing;
21 |
22 | namespace MapAssist.Types
23 | {
24 | public static class ResistColors
25 | {
26 | public static Dictionary ResistColor = new Dictionary
27 | {
28 | { Resist.PHYSICAL, Color.Peru },
29 | { Resist.MAGIC, Color.OrangeRed },
30 | { Resist.FIRE, Color.Red },
31 | { Resist.LIGHTNING, Color.Yellow },
32 | { Resist.COLD, Color.CornflowerBlue },
33 | { Resist.POISON, Color.LimeGreen },
34 |
35 | };
36 | }
37 | public enum Resist
38 | {
39 | PHYSICAL = 0,
40 | MAGIC = 1,
41 | FIRE = 2,
42 | LIGHTNING = 3,
43 | COLD = 4,
44 | POISON = 5
45 | }
46 | public enum Stat : short
47 | {
48 | STAT_INVALID = -1,
49 | STAT_STRENGTH = 0, // 000
50 | STAT_ENERGY, // 001
51 | STAT_DEXTERITY, // 002
52 | STAT_VITALITY, // 003
53 | STAT_STATPTS, // 004
54 | STAT_SKILLPTS, // 005
55 | STAT_HITPOINTS, // 006
56 | STAT_MAXHP, // 007
57 | STAT_MANA, // 008
58 | STAT_MAXMANA, // 009
59 | STAT_STAMINA, // 00A
60 | STAT_MAXSTAMINA, // 00B
61 | STAT_LEVEL, // 00C
62 | STAT_EXPERIENCE, // 00D
63 | STAT_GOLD, // 00E
64 | STAT_GOLDBANK, // 00F
65 | STAT_ITEM_ARMOR_PERCENT, // 010
66 | STAT_ITEM_MAXDAMAGE_PERCENT, // 011
67 | STAT_ITEM_MINDAMAGE_PERCENT, // 012
68 | STAT_TOHIT,
69 | STAT_TOBLOCK,
70 | STAT_MINDAMAGE,
71 | STAT_MAXDAMAGE,
72 | STAT_SECONDARY_MINDAMAGE,
73 | STAT_SECONDARY_MAXDAMAGE,
74 | STAT_DAMAGEPERCENT,
75 | STAT_MANARECOVERY,
76 | STAT_MANARECOVERYBONUS,
77 | STAT_STAMINARECOVERYBONUS,
78 | STAT_LASTEXP,
79 | STAT_NEXTEXP,
80 | STAT_ARMORCLASS,
81 | STAT_ARMORCLASS_VS_MISSILE,
82 | STAT_ARMORCLASS_VS_HTH,
83 | STAT_NORMAL_DAMAGE_REDUCTION,
84 | STAT_MAGIC_DAMAGE_REDUCTION,
85 | STAT_DAMAGERESIST,
86 | STAT_MAGICRESIST,
87 | STAT_MAXMAGICRESIST,
88 | STAT_FIRERESIST,
89 | STAT_MAXFIRERESIST,
90 | STAT_LIGHTRESIST,
91 | STAT_MAXLIGHTRESIST,
92 | STAT_COLDRESIST,
93 | STAT_MAXCOLDRESIST,
94 | STAT_POISONRESIST,
95 | STAT_MAXPOISONRESIST,
96 | STAT_DAMAGEAURA,
97 | STAT_FIREMINDAM,
98 | STAT_FIREMAXDAM,
99 | STAT_LIGHTMINDAM,
100 | STAT_LIGHTMAXDAM,
101 | STAT_MAGICMINDAM,
102 | STAT_MAGICMAXDAM,
103 | STAT_COLDMINDAM,
104 | STAT_COLDMAXDAM,
105 | STAT_COLDLENGTH,
106 | STAT_POISONMINDAM,
107 | STAT_POISONMAXDAM,
108 | STAT_POISONLENGTH,
109 | STAT_LIFEDRAINMINDAM,
110 | STAT_LIFEDRAINMAXDAM,
111 | STAT_MANADRAINMINDAM,
112 | STAT_MANADRAINMAXDAM,
113 | STAT_STAMDRAINMINDAM,
114 | STAT_STAMDRAINMAXDAM,
115 | STAT_STUNLENGTH,
116 | STAT_VELOCITYPERCENT,
117 | STAT_ATTACKRATE,
118 | STAT_OTHER_ANIMRATE,
119 | STAT_QUANTITY,
120 | STAT_VALUE,
121 | STAT_DURABILITY,
122 | STAT_MAXDURABILITY,
123 | STAT_HPREGEN,
124 | STAT_ITEM_MAXDURABILITY_PERCENT,
125 | STAT_ITEM_MAXHP_PERCENT,
126 | STAT_ITEM_MAXMANA_PERCENT,
127 | STAT_ITEM_ATTACKERTAKESDAMAGE,
128 | STAT_ITEM_GOLDBONUS,
129 | STAT_ITEM_MAGICBONUS,
130 | STAT_ITEM_KNOCKBACK,
131 | STAT_ITEM_TIMEDURATION,
132 | STAT_ITEM_ADDCLASSSKILLS,
133 | STAT_UNSENTPARAM1,
134 | STAT_ITEM_ADDEXPERIENCE,
135 | STAT_ITEM_HEALAFTERKILL,
136 | STAT_ITEM_REDUCEDPRICES,
137 | STAT_ITEM_DOUBLEHERBDURATION,
138 | STAT_ITEM_LIGHTRADIUS,
139 | STAT_ITEM_LIGHTCOLOR,
140 | STAT_ITEM_REQ_PERCENT,
141 | STAT_ITEM_LEVELREQ,
142 | STAT_ITEM_FASTERATTACKRATE,
143 | STAT_ITEM_LEVELREQPCT,
144 | STAT_LASTBLOCKFRAME,
145 | STAT_ITEM_FASTERMOVEVELOCITY,
146 | STAT_ITEM_NONCLASSSKILL,
147 | STAT_STATE,
148 | STAT_ITEM_FASTERGETHITRATE,
149 | STAT_MONSTER_PLAYERCOUNT,
150 | STAT_SKILL_POISON_OVERRIDE_LENGTH,
151 | STAT_ITEM_FASTERBLOCKRATE,
152 | STAT_SKILL_BYPASS_UNDEAD,
153 | STAT_SKILL_BYPASS_DEMONS,
154 | STAT_ITEM_FASTERCASTRATE,
155 | STAT_SKILL_BYPASS_BEASTS,
156 | STAT_ITEM_SINGLESKILL,
157 | STAT_ITEM_RESTINPEACE,
158 | STAT_CURSE_RESISTANCE,
159 | STAT_ITEM_POISONLENGTHRESIST,
160 | STAT_ITEM_NORMALDAMAGE,
161 | STAT_ITEM_HOWL,
162 | STAT_ITEM_STUPIDITY,
163 | STAT_ITEM_DAMAGETOMANA,
164 | STAT_ITEM_IGNORETARGETAC,
165 | STAT_ITEM_FRACTIONALTARGETAC,
166 | STAT_ITEM_PREVENTHEAL,
167 | STAT_ITEM_HALFFREEZEDURATION,
168 | STAT_ITEM_TOHIT_PERCENT,
169 | STAT_ITEM_DAMAGETARGETAC,
170 | STAT_ITEM_DEMONDAMAGE_PERCENT,
171 | STAT_ITEM_UNDEADDAMAGE_PERCENT,
172 | STAT_ITEM_DEMON_TOHIT,
173 | STAT_ITEM_UNDEAD_TOHIT,
174 | STAT_ITEM_THROWABLE,
175 | STAT_ITEM_ELEMSKILL,
176 | STAT_ITEM_ALLSKILLS,
177 | STAT_ITEM_ATTACKERTAKESLIGHTDAMAGE,
178 | STAT_IRONMAIDEN_LEVEL,
179 | STAT_LIFETAP_LEVEL,
180 | STAT_THORNS_PERCENT,
181 | STAT_BONEARMOR,
182 | STAT_BONEARMORMAX,
183 | STAT_ITEM_FREEZE,
184 | STAT_ITEM_OPENWOUNDS,
185 | STAT_ITEM_CRUSHINGBLOW,
186 | STAT_ITEM_KICKDAMAGE,
187 | STAT_ITEM_MANAAFTERKILL,
188 | STAT_ITEM_HEALAFTERDEMONKILL,
189 | STAT_ITEM_EXTRABLOOD,
190 | STAT_ITEM_DEADLYSTRIKE,
191 | STAT_ITEM_ABSORBFIRE_PERCENT,
192 | STAT_ITEM_ABSORBFIRE,
193 | STAT_ITEM_ABSORBLIGHT_PERCENT,
194 | STAT_ITEM_ABSORBLIGHT,
195 | STAT_ITEM_ABSORBMAGIC_PERCENT,
196 | STAT_ITEM_ABSORBMAGIC,
197 | STAT_ITEM_ABSORBCOLD_PERCENT,
198 | STAT_ITEM_ABSORBCOLD,
199 | STAT_ITEM_SLOW,
200 | STAT_ITEM_AURA,
201 | STAT_ITEM_INDESCTRUCTIBLE,
202 | STAT_ITEM_CANNOTBEFROZEN,
203 | STAT_ITEM_STAMINADRAINPCT,
204 | STAT_ITEM_REANIMATE,
205 | STAT_ITEM_PIERCE,
206 | STAT_ITEM_MAGICARROW,
207 | STAT_ITEM_EXPLOSIVEARROW,
208 | STAT_ITEM_THROW_MINDAMAGE,
209 | STAT_ITEM_THROW_MAXDAMAGE,
210 | STAT_SKILL_HANDOFATHENA,
211 | STAT_SKILL_STAMINAPERCENT,
212 | STAT_SKILL_PASSIVE_STAMINAPERCENT,
213 | STAT_SKILL_CONCENTRATION,
214 | STAT_SKILL_ENCHANT,
215 | STAT_SKILL_PIERCE,
216 | STAT_SKILL_CONVICTION,
217 | STAT_SKILL_CHILLINGARMOR,
218 | STAT_SKILL_FRENZY,
219 | STAT_SKILL_DECREPIFY,
220 | STAT_SKILL_ARMOR_PERCENT,
221 | STAT_ALIGNMENT,
222 | STAT_TARGET0,
223 | STAT_TARGET1,
224 | STAT_GOLDLOST,
225 | STAT_CONVERSION_LEVEL,
226 | STAT_CONVERSION_MAXHP,
227 | STAT_UNIT_DOOVERLAY,
228 | STAT_ATTACK_VS_MONTYPE,
229 | STAT_DAMAGE_VS_MONTYPE,
230 | STAT_FADE,
231 | STAT_ARMOR_OVERRIDE_PERCENT,
232 | STAT_UNUSED183,
233 | STAT_UNUSED184,
234 | STAT_UNUSED185,
235 | STAT_UNUSED186,
236 | STAT_UNUSED187,
237 | STAT_ITEM_ADDSKILL_TAB,
238 | STAT_UNUSED189,
239 | STAT_UNUSED190,
240 | STAT_UNUSED191,
241 | STAT_UNUSED192,
242 | STAT_UNUSED193,
243 | STAT_ITEM_NUMSOCKETS,
244 | STAT_ITEM_SKILLONATTACK,
245 | STAT_ITEM_SKILLONKILL,
246 | STAT_ITEM_SKILLONDEATH,
247 | STAT_ITEM_SKILLONHIT,
248 | STAT_ITEM_SKILLONLEVELUP,
249 | STAT_UNUSED200,
250 | STAT_ITEM_SKILLONGETHIT,
251 | STAT_UNUSED202,
252 | STAT_UNUSED203,
253 | STAT_ITEM_CHARGED_SKILL,
254 | STAT_UNUSED204,
255 | STAT_UNUSED205,
256 | STAT_UNUSED206,
257 | STAT_UNUSED207,
258 | STAT_UNUSED208,
259 | STAT_UNUSED209,
260 | STAT_UNUSED210,
261 | STAT_UNUSED211,
262 | STAT_UNUSED212,
263 | STAT_ITEM_ARMOR_PERLEVEL,
264 | STAT_ITEM_ARMORPERCENT_PERLEVEL,
265 | STAT_ITEM_HP_PERLEVEL,
266 | STAT_ITEM_MANA_PERLEVEL,
267 | STAT_ITEM_MAXDAMAGE_PERLEVEL,
268 | STAT_ITEM_MAXDAMAGE_PERCENT_PERLEVEL,
269 | STAT_ITEM_STRENGTH_PERLEVEL,
270 | STAT_ITEM_DEXTERITY_PERLEVEL,
271 | STAT_ITEM_ENERGY_PERLEVEL,
272 | STAT_ITEM_VITALITY_PERLEVEL,
273 | STAT_ITEM_TOHIT_PERLEVEL,
274 | STAT_ITEM_TOHITPERCENT_PERLEVEL,
275 | STAT_ITEM_COLD_DAMAGEMAX_PERLEVEL,
276 | STAT_ITEM_FIRE_DAMAGEMAX_PERLEVEL,
277 | STAT_ITEM_LTNG_DAMAGEMAX_PERLEVEL,
278 | STAT_ITEM_POIS_DAMAGEMAX_PERLEVEL,
279 | STAT_ITEM_RESIST_COLD_PERLEVEL,
280 | STAT_ITEM_RESIST_FIRE_PERLEVEL,
281 | STAT_ITEM_RESIST_LTNG_PERLEVEL,
282 | STAT_ITEM_RESIST_POIS_PERLEVEL,
283 | STAT_ITEM_ABSORB_COLD_PERLEVEL,
284 | STAT_ITEM_ABSORB_FIRE_PERLEVEL,
285 | STAT_ITEM_ABSORB_LTNG_PERLEVEL,
286 | STAT_ITEM_ABSORB_POIS_PERLEVEL,
287 | STAT_ITEM_THORNS_PERLEVEL,
288 | STAT_ITEM_FIND_GOLD_PERLEVEL,
289 | STAT_ITEM_FIND_MAGIC_PERLEVEL,
290 | STAT_ITEM_REGENSTAMINA_PERLEVEL,
291 | STAT_ITEM_STAMINA_PERLEVEL,
292 | STAT_ITEM_DAMAGE_DEMON_PERLEVEL,
293 | STAT_ITEM_DAMAGE_UNDEAD_PERLEVEL,
294 | STAT_ITEM_TOHIT_DEMON_PERLEVEL,
295 | STAT_ITEM_TOHIT_UNDEAD_PERLEVEL,
296 | STAT_ITEM_CRUSHINGBLOW_PERLEVEL,
297 | STAT_ITEM_OPENWOUNDS_PERLEVEL,
298 | STAT_ITEM_KICK_DAMAGE_PERLEVEL,
299 | STAT_ITEM_DEADLYSTRIKE_PERLEVEL,
300 | STAT_ITEM_FIND_GEMS_PERLEVEL,
301 | STAT_ITEM_REPLENISH_DURABILITY,
302 | STAT_ITEM_REPLENISH_QUANTITY,
303 | STAT_ITEM_EXTRA_STACK,
304 | STAT_ITEM_FIND_ITEM,
305 | STAT_ITEM_SLASH_DAMAGE,
306 | STAT_ITEM_SLASH_DAMAGE_PERCENT,
307 | STAT_ITEM_CRUSH_DAMAGE,
308 | STAT_ITEM_CRUSH_DAMAGE_PERCENT,
309 | STAT_ITEM_THRUST_DAMAGE,
310 | STAT_ITEM_THRUST_DAMAGE_PERCENT,
311 | STAT_ITEM_ABSORB_SLASH,
312 | STAT_ITEM_ABSORB_CRUSH,
313 | STAT_ITEM_ABSORB_THRUST,
314 | STAT_ITEM_ABSORB_SLASH_PERCENT,
315 | STAT_ITEM_ABSORB_CRUSH_PERCENT,
316 | STAT_ITEM_ABSORB_THRUST_PERCENT,
317 | STAT_ITEM_ARMOR_BYTIME,
318 | STAT_ITEM_ARMORPERCENT_BYTIME,
319 | STAT_ITEM_HP_BYTIME,
320 | STAT_ITEM_MANA_BYTIME,
321 | STAT_ITEM_MAXDAMAGE_BYTIME,
322 | STAT_ITEM_MAXDAMAGE_PERCENT_BYTIME,
323 | STAT_ITEM_STRENGTH_BYTIME,
324 | STAT_ITEM_DEXTERITY_BYTIME,
325 | STAT_ITEM_ENERGY_BYTIME,
326 | STAT_ITEM_VITALITY_BYTIME,
327 | STAT_ITEM_TOHIT_BYTIME,
328 | STAT_ITEM_TOHITPERCENT_BYTIME,
329 | STAT_ITEM_COLD_DAMAGEMAX_BYTIME,
330 | STAT_ITEM_FIRE_DAMAGEMAX_BYTIME,
331 | STAT_ITEM_LTNG_DAMAGEMAX_BYTIME,
332 | STAT_ITEM_POIS_DAMAGEMAX_BYTIME,
333 | STAT_ITEM_RESIST_COLD_BYTIME,
334 | STAT_ITEM_RESIST_FIRE_BYTIME,
335 | STAT_ITEM_RESIST_LTNG_BYTIME,
336 | STAT_ITEM_RESIST_POIS_BYTIME,
337 | STAT_ITEM_ABSORB_COLD_BYTIME,
338 | STAT_ITEM_ABSORB_FIRE_BYTIME,
339 | STAT_ITEM_ABSORB_LTNG_BYTIME,
340 | STAT_ITEM_ABSORB_POIS_BYTIME,
341 | STAT_ITEM_FIND_GOLD_BYTIME,
342 | STAT_ITEM_FIND_MAGIC_BYTIME,
343 | STAT_ITEM_REGENSTAMINA_BYTIME,
344 | STAT_ITEM_STAMINA_BYTIME,
345 | STAT_ITEM_DAMAGE_DEMON_BYTIME,
346 | STAT_ITEM_DAMAGE_UNDEAD_BYTIME,
347 | STAT_ITEM_TOHIT_DEMON_BYTIME,
348 | STAT_ITEM_TOHIT_UNDEAD_BYTIME,
349 | STAT_ITEM_CRUSHINGBLOW_BYTIME,
350 | STAT_ITEM_OPENWOUNDS_BYTIME,
351 | STAT_ITEM_KICK_DAMAGE_BYTIME,
352 | STAT_ITEM_DEADLYSTRIKE_BYTIME,
353 | STAT_ITEM_FIND_GEMS_BYTIME,
354 | STAT_ITEM_PIERCE_COLD,
355 | STAT_ITEM_PIERCE_FIRE,
356 | STAT_ITEM_PIERCE_LTNG,
357 | STAT_ITEM_PIERCE_POIS,
358 | STAT_ITEM_DAMAGE_VS_MONSTER,
359 | STAT_ITEM_DAMAGE_PERCENT_VS_MONSTER,
360 | STAT_ITEM_TOHIT_VS_MONSTER,
361 | STAT_ITEM_TOHIT_PERCENT_VS_MONSTER,
362 | STAT_ITEM_AC_VS_MONSTER,
363 | STAT_ITEM_AC_PERCENT_VS_MONSTER,
364 | STAT_FIRELENGTH,
365 | STAT_BURNINGMIN,
366 | STAT_BURNINGMAX,
367 | STAT_PROGRESSIVE_DAMAGE,
368 | STAT_PROGRESSIVE_STEAL,
369 | STAT_PROGRESSIVE_OTHER,
370 | STAT_PROGRESSIVE_FIRE,
371 | STAT_PROGRESSIVE_COLD,
372 | STAT_PROGRESSIVE_LIGHTNING,
373 | STAT_ITEM_EXTRA_CHARGES,
374 | STAT_PROGRESSIVE_TOHIT,
375 | STAT_POISON_COUNT,
376 | STAT_DAMAGE_FRAMERATE,
377 | STAT_PIERCE_IDX,
378 | STAT_PASSIVE_FIRE_MASTERY,
379 | STAT_PASSIVE_LTNG_MASTERY,
380 | STAT_PASSIVE_COLD_MASTERY,
381 | STAT_PASSIVE_POIS_MASTERY,
382 | STAT_PASSIVE_FIRE_PIERCE,
383 | STAT_PASSIVE_LTNG_PIERCE,
384 | STAT_PASSIVE_COLD_PIERCE,
385 | STAT_PASSIVE_POIS_PIERCE,
386 | STAT_PASSIVE_CRITICAL_STRIKE,
387 | STAT_PASSIVE_DODGE,
388 | STAT_PASSIVE_AVOID,
389 | STAT_PASSIVE_EVADE,
390 | STAT_PASSIVE_WARMTH,
391 | STAT_PASSIVE_MASTERY_MELEE_TH,
392 | STAT_PASSIVE_MASTERY_MELEE_DMG,
393 | STAT_PASSIVE_MASTERY_MELEE_CRIT,
394 | STAT_PASSIVE_MASTERY_THROW_TH,
395 | STAT_PASSIVE_MASTERY_THROW_DMG,
396 | STAT_PASSIVE_MASTERY_THROW_CRIT,
397 | STAT_PASSIVE_WEAPONBLOCK,
398 | STAT_PASSIVE_SUMMON_RESIST,
399 | STAT_MODIFIERLIST_SKILL,
400 | STAT_MODIFIERLIST_LEVEL,
401 | STAT_LAST_SENT_HP_PCT,
402 | STAT_SOURCE_UNIT_TYPE,
403 | STAT_SOURCE_UNIT_ID,
404 | STAT_SHORTPARAM1,
405 | STAT_QUESTITEMDIFFICULTY,
406 | STAT_PASSIVE_MAG_MASTERY,
407 | STAT_PASSIVE_MAG_PIERCE,
408 | };
409 | }
410 |
--------------------------------------------------------------------------------
/Helpers/GameMemory.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | using System;
21 | using System.Diagnostics;
22 | using System.Drawing;
23 | using System.Linq;
24 | using System.Runtime.InteropServices;
25 | using System.Text;
26 | using System.Collections.Generic;
27 |
28 | using MapAssist.Structs;
29 | using MapAssist.Types;
30 | using MapAssist.Settings;
31 |
32 | namespace MapAssist.Helpers
33 | {
34 | class GameMemory
35 | {
36 | private static readonly string ProcessName = Encoding.UTF8.GetString(new byte[] { 68, 50, 82 });
37 | private static IntPtr PlayerUnitPtr;
38 | private static UnitAny PlayerUnit = default;
39 | private static int _lastProcessId = 0;
40 | public static List Monsters = new List();
41 | public static List WarningMessages = new List();
42 | private static Difficulty currentDifficulty = Difficulty.None;
43 | private static uint currentMapSeed = 0;
44 |
45 | unsafe public static GameData GetGameData()
46 | {
47 | IntPtr processHandle = IntPtr.Zero;
48 |
49 | try
50 | {
51 | Process[] process = Process.GetProcessesByName(ProcessName);
52 |
53 | Process gameProcess = null;
54 |
55 | IntPtr windowInFocus = WindowsExternal.GetForegroundWindow();
56 | if (windowInFocus == IntPtr.Zero)
57 | {
58 | gameProcess = process.FirstOrDefault();
59 | }
60 | else
61 | {
62 | gameProcess = process.FirstOrDefault(p => p.MainWindowHandle == windowInFocus);
63 | }
64 |
65 | if (gameProcess == null)
66 | {
67 | throw new Exception("Game process not found.");
68 | }
69 |
70 | // If changing processes we need to re-find the player
71 | if (gameProcess.Id != _lastProcessId)
72 | {
73 | ResetPlayerUnit();
74 | }
75 |
76 | _lastProcessId = gameProcess.Id;
77 |
78 | processHandle =
79 | WindowsExternal.OpenProcess((uint)WindowsExternal.ProcessAccessFlags.VirtualMemoryRead, false, gameProcess.Id);
80 | IntPtr processAddress = gameProcess.MainModule.BaseAddress;
81 | if (PlayerUnitPtr == IntPtr.Zero)
82 | {
83 | var expansionCharacter = Read(processHandle, IntPtr.Add(processAddress, Offsets.ExpansionCheck)) == 1;
84 | var userBaseOffset = 0x30;
85 | var checkUser1 = 1;
86 | if (expansionCharacter)
87 | {
88 | userBaseOffset = 0x70;
89 | checkUser1 = 0;
90 | }
91 | var unitHashTable = Read(processHandle, IntPtr.Add(processAddress, Offsets.UnitHashTable));
92 | foreach (var pUnitAny in unitHashTable.UnitTable)
93 | {
94 | var pListNext = pUnitAny;
95 |
96 | while (pListNext != IntPtr.Zero)
97 | {
98 | var unitAny = Read(processHandle, pListNext);
99 | if (unitAny.Inventory != IntPtr.Zero)
100 | {
101 | var UserBaseCheck = Read(processHandle, IntPtr.Add(unitAny.Inventory, userBaseOffset));
102 | if (UserBaseCheck != checkUser1)
103 | {
104 | PlayerUnitPtr = pUnitAny;
105 | PlayerUnit = unitAny;
106 | break;
107 | }
108 | }
109 | pListNext = (IntPtr)unitAny.pListNext;
110 | }
111 |
112 | if (PlayerUnitPtr != IntPtr.Zero)
113 | {
114 | break;
115 | }
116 | }
117 | }
118 |
119 | if (PlayerUnitPtr == IntPtr.Zero)
120 | {
121 | currentDifficulty = Difficulty.None;
122 | currentMapSeed = 0;
123 | throw new Exception("Player pointer is zero.");
124 | }
125 |
126 | /*IntPtr aPlayerUnit = Read(processHandle, PlayerUnitPtr);
127 |
128 | if (aPlayerUnit == IntPtr.Zero)
129 | {
130 | throw new Exception("Player address is zero.");
131 | }*/
132 |
133 | var playerName = Encoding.ASCII.GetString(Read(processHandle, PlayerUnit.UnitData, 16)).TrimEnd((char)0);
134 | var act = Read(processHandle, (IntPtr)PlayerUnit.pAct);
135 | var mapSeed = (uint)0;
136 | if (currentMapSeed == 0)
137 | {
138 | currentMapSeed = act.MapSeed;
139 | }
140 | mapSeed = currentMapSeed;
141 |
142 | if (mapSeed <= 0 || mapSeed > 0xFFFFFFFF)
143 | {
144 | throw new Exception("Map seed is out of bounds.");
145 | }
146 |
147 | var actId = act.ActId;
148 | var actMisc = Read(processHandle, (IntPtr)act.ActMisc);
149 | var gameDifficulty = Difficulty.None;
150 | if(currentDifficulty == Difficulty.None)
151 | {
152 | currentDifficulty = actMisc.GameDifficulty;
153 | }
154 | gameDifficulty = currentDifficulty;
155 |
156 | if (!gameDifficulty.IsValid())
157 | {
158 | throw new Exception("Game difficulty out of bounds.");
159 | }
160 |
161 | var path = Read(processHandle, (IntPtr)PlayerUnit.pPath);
162 | var positionX = path.DynamicX;
163 | var positionY = path.DynamicY;
164 | var room = Read(processHandle, (IntPtr)path.pRoom);
165 | var roomEx = Read(processHandle, (IntPtr)room.pRoomEx);
166 | var level = Read(processHandle, (IntPtr)roomEx.pLevel);
167 | var levelId = level.LevelId;
168 |
169 | if (!levelId.IsValid())
170 | {
171 | throw new Exception("Level id out of bounds.");
172 | }
173 |
174 | var mapShownByte = Read(processHandle, IntPtr.Add(processAddress, Offsets.UiSettings)).MapShown;
175 | var mapShown = mapShownByte == 1;
176 |
177 | WarningMessages.Clear();
178 | Monsters = GetMobs(processHandle, IntPtr.Add(processAddress, Offsets.UnitHashTable + (128 * 8)));
179 |
180 | return new GameData
181 | {
182 | PlayerPosition = new Point(positionX, positionY),
183 | MapSeed = mapSeed,
184 | Area = levelId,
185 | Difficulty = gameDifficulty,
186 | MapShown = mapShown,
187 | MainWindowHandle = gameProcess.MainWindowHandle,
188 | PlayerName = playerName
189 | };
190 | }
191 | catch (Exception exception)
192 | {
193 | Console.WriteLine(exception.Message);
194 | ResetPlayerUnit();
195 | return null;
196 | }
197 | finally
198 | {
199 | if (processHandle != IntPtr.Zero)
200 | {
201 | WindowsExternal.CloseHandle(processHandle);
202 | }
203 | }
204 | }
205 | unsafe public static List GetMobs(IntPtr processHandle, IntPtr startAddress)
206 | {
207 | var monList = new List();
208 |
209 | var unitHashTable = Read(processHandle, startAddress);
210 | foreach (var pUnitAny in unitHashTable.UnitTable)
211 | {
212 | var pListNext = pUnitAny;
213 |
214 | while (pListNext != IntPtr.Zero)
215 | {
216 | var unitAny = Read(processHandle, pListNext);
217 | //why would we ever comment any of our code with anything useful? :D
218 | if (unitAny.Mode != 0 && unitAny.Mode != 12 && !NPCs.Dummies.TryGetValue(unitAny.TxtFileNo, out var _))
219 | {
220 |
221 | var monData = Read(processHandle, unitAny.UnitData);
222 | var monStats = Read(processHandle, monData.pMonStats);
223 | var monNameBytes = new byte[monStats.Name.Length - 2];
224 | Array.Copy(monStats.Name, 2, monNameBytes, 0, monNameBytes.Length);
225 | var monName = Encoding.ASCII.GetString(monNameBytes).TrimEnd((char)0);
226 | var monPath = Read(processHandle, (IntPtr)unitAny.pPath);
227 | var flag = Read(processHandle, IntPtr.Add(unitAny.UnitData, 24));
228 | var newMon = new Monster()
229 | {
230 | Position = new Point(monPath.DynamicX, monPath.DynamicY),
231 | UniqueFlag = flag,
232 | Immunities = GetImmunes(processHandle, unitAny)
233 | };
234 | var NPC = Enum.GetName(typeof(Npc), unitAny.TxtFileNo);
235 |
236 | var SuperUnique = false;
237 | var NameInWarnList = Array.Exists(Map.WarnImmuneNPC, element => (element == Enum.GetName(typeof(Npc), unitAny.TxtFileNo)));
238 | var NameInWarnList2 = false;
239 | if ((monData.MonsterType & MonsterTypeFlags.SuperUnique) == MonsterTypeFlags.SuperUnique)
240 | {
241 | NPCs.SuperUnique.TryGetValue(monName, out var SuperUniqueName);
242 | SuperUnique = NPCs.SuperUniqueName(monName) == SuperUniqueName;
243 | NameInWarnList2 = Array.Exists(Map.WarnImmuneNPC, element => (element == SuperUniqueName));
244 | if (SuperUnique)
245 | {
246 | NPC = SuperUniqueName;
247 | }
248 | }
249 | if (NameInWarnList || (SuperUnique && NameInWarnList2))
250 | {
251 | var immunestr = "";
252 | foreach(Resist immunity in newMon.Immunities)
253 | {
254 | immunestr += immunity + ", ";
255 | }
256 | if (immunestr.Length > 2)
257 | {
258 | immunestr = immunestr.Remove(immunestr.Length - 2);
259 | WarningMessages.Add(NPC + " is immune to " + immunestr);
260 | }
261 | }
262 | monList.Add(newMon);
263 | }
264 | pListNext = (IntPtr)unitAny.pListNext;
265 | }
266 | }
267 | return monList;
268 | }
269 |
270 | public static Dictionary GetStats(IntPtr processHandle, UnitAny unit)
271 | {
272 | var _statListStruct = Read(processHandle, unit.StatsListEx);
273 | return Read(processHandle, _statListStruct.Stats.FirstStatPtr, Convert.ToInt32(_statListStruct.Stats.Size)).ToDictionary(s => s.Stat, s => s.Value);
274 | }
275 | public static List GetResists(IntPtr processHandle, UnitAny unit)
276 | {
277 | var stats = GetStats(processHandle, unit);
278 |
279 | stats.TryGetValue(Stat.STAT_DAMAGERESIST, out var dmgres);
280 | stats.TryGetValue(Stat.STAT_MAGICRESIST, out var magicres);
281 | stats.TryGetValue(Stat.STAT_FIRERESIST, out var fireres);
282 | stats.TryGetValue(Stat.STAT_LIGHTRESIST, out var lightres);
283 | stats.TryGetValue(Stat.STAT_COLDRESIST, out var coldres);
284 | stats.TryGetValue(Stat.STAT_POISONRESIST, out var poires);
285 |
286 | var _resists = new List { dmgres, magicres, fireres, lightres, coldres, poires };
287 |
288 | return _resists;
289 | }
290 | public static List GetImmunes(IntPtr processHandle, UnitAny unit)
291 | {
292 | var resists = GetResists(processHandle, unit);
293 | var immunities = new List();
294 | for (var i = 0; i < 6; i++)
295 | {
296 | if (resists[i] >= 100)
297 | {
298 | immunities.Add((Resist)i);
299 | }
300 | }
301 | var _immunes = immunities;
302 | return _immunes;
303 | }
304 | private static void ResetPlayerUnit()
305 | {
306 | PlayerUnit = default;
307 | PlayerUnitPtr = IntPtr.Zero;
308 | }
309 |
310 | public static T[] Read(IntPtr processHandle, IntPtr address, int count) where T : struct
311 | {
312 | var sz = Marshal.SizeOf();
313 | var buf = new byte[sz * count];
314 | WindowsExternal.ReadProcessMemory(processHandle, address, buf, buf.Length, out _);
315 |
316 | var handle = GCHandle.Alloc(buf, GCHandleType.Pinned);
317 | try
318 | {
319 | var result = new T[count];
320 | for (var i = 0; i < count; i++)
321 | {
322 | result[i] = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject() + (i * sz), typeof(T));
323 | }
324 |
325 | return result;
326 | }
327 | finally
328 | {
329 | handle.Free();
330 | }
331 | }
332 |
333 | public static T Read(IntPtr processHandle, IntPtr address) where T : struct
334 | {
335 | return Read(processHandle, address, 1)[0];
336 | }
337 | }
338 | }
339 |
--------------------------------------------------------------------------------
/Types/GameObject.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2021 okaygo
3 | *
4 | * https://github.com/misterokaygo/MapAssist/
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | **/
19 |
20 | namespace MapAssist.Types
21 | {
22 | public enum GameObject
23 | {
24 | NotApplicable = -1,
25 | TestData1 = 0,
26 | Casket5 = 1,
27 | Shrine = 2,
28 | Casket6 = 3,
29 | LargeUrn1 = 4,
30 | LargeChestRight = 5,
31 | LargeChestLeft = 6,
32 | Barrel = 7,
33 | TowerTome = 8,
34 | Urn2 = 9,
35 | Bench = 10,
36 | BarrelExploding = 11,
37 | RogueFountain = 12,
38 | DoorGateLeft = 13,
39 | DoorGateRight = 14,
40 | DoorWoodenLeft = 15,
41 | DoorWoodenRight = 16,
42 | CairnStoneAlpha = 17,
43 | CairnStoneBeta = 18,
44 | CairnStoneGamma = 19,
45 | CairnStoneDelta = 20,
46 | CairnStoneLambda = 21,
47 | CairnStoneTheta = 22,
48 | DoorCourtyardLeft = 23,
49 | DoorCourtyardRight = 24,
50 | DoorCathedralDouble = 25,
51 | CainGibbet = 26,
52 | DoorMonasteryDoubleRight = 27,
53 | HoleAnim = 28,
54 | Brazier = 29,
55 | InifussTree = 30,
56 | Fountain = 31,
57 | Crucifix = 32,
58 | Candles1 = 33,
59 | Candles2 = 34,
60 | Standard1 = 35,
61 | Standard2 = 36,
62 | Torch1Tiki = 37,
63 | Torch2Wall = 38,
64 | RogueBonfire = 39,
65 | River1 = 40,
66 | River2 = 41,
67 | River3 = 42,
68 | River4 = 43,
69 | River5 = 44,
70 | AmbientSoundGenerator = 45,
71 | Crate = 46,
72 | AndarielDoor = 47,
73 | RogueTorch1 = 48,
74 | RogueTorch2 = 49,
75 | CasketR = 50,
76 | CasketL = 51,
77 | Urn3 = 52,
78 | Casket = 53,
79 | RogueCorpse1 = 54,
80 | RogueCorpse2 = 55,
81 | RogueCorpseRolling = 56,
82 | CorpseOnStick1 = 57,
83 | CorpseOnStick2 = 58,
84 | TownPortal = 59,
85 | PermanentTownPortal = 60,
86 | InvisibleObject = 61,
87 | DoorCathedralLeft = 62,
88 | DoorCathedralRight = 63,
89 | DoorWoodenLeft2 = 64,
90 | InvisibleRiverSound1 = 65,
91 | InvisibleRiverSound2 = 66,
92 | Ripple1 = 67,
93 | Ripple2 = 68,
94 | Ripple3 = 69,
95 | Ripple4 = 70,
96 | ForestNightSound1 = 71,
97 | ForestNightSound2 = 72,
98 | YetiDung = 73,
99 | TrappDoor = 74,
100 | DoorByAct2Dock = 75,
101 | SewerDrip = 76,
102 | HealthOrama = 77,
103 | InvisibleTownSound = 78,
104 | Casket3 = 79,
105 | Obelisk = 80,
106 | ForestAltar = 81,
107 | BubblingPoolOfBlood = 82,
108 | HornShrine = 83,
109 | HealingWell = 84,
110 | BullHealthShrine = 85,
111 | SteleDesertMagicShrine = 86,
112 | TombLargeChestL = 87,
113 | TombLargeChestR = 88,
114 | Sarcophagus = 89,
115 | DesertObelisk = 90,
116 | TombDoorLeft = 91,
117 | TombDoorRight = 92,
118 | InnerHellManaShrine = 93,
119 | LargeUrn4 = 94,
120 | LargeUrn5 = 95,
121 | InnerHellHealthShrine = 96,
122 | InnerHellShrine = 97,
123 | TombDoorLeft2 = 98,
124 | TombDoorRight2 = 99,
125 | DurielsLairPortal = 100,
126 | Brazier3 = 101,
127 | FloorBrazier = 102,
128 | Flies = 103,
129 | ArmorStandRight = 104,
130 | ArmorStandLeft = 105,
131 | WeaponRackRight = 106,
132 | WeaponRackLeft = 107,
133 | Malus = 108,
134 | PalaceHealthShrine = 109,
135 | Drinker = 110,
136 | Fountain1 = 111,
137 | Gesturer = 112,
138 | DesertFountain = 113,
139 | Turner = 114,
140 | Fountain3 = 115,
141 | SnakeWomanShrine = 116,
142 | JungleTorch = 117,
143 | Fountain4 = 118,
144 | WaypointPortal = 119,
145 | DungeonHealthShrine = 120,
146 | JerhynPlaceHolder1 = 121,
147 | JerhynPlaceHolder2 = 122,
148 | InnerHellShrine2 = 123,
149 | InnerHellShrine3 = 124,
150 | InnerHellHiddenStash = 125,
151 | InnerHellSkullPile = 126,
152 | InnerHellHiddenStash2 = 127,
153 | InnerHellHiddenStash3 = 128,
154 | SecretDoor1 = 129,
155 | Act1WildernessWell = 130,
156 | VileDogAfterglow = 131,
157 | CathedralWell = 132,
158 | ArcaneSanctuaryShrine = 133,
159 | DesertShrine2 = 134,
160 | DesertShrine3 = 135,
161 | DesertShrine1 = 136,
162 | DesertWell = 137,
163 | CaveWell = 138,
164 | Act1LargeChestRight = 139,
165 | Act1TallChestRight = 140,
166 | Act1MediumChestRight = 141,
167 | DesertJug1 = 142,
168 | DesertJug2 = 143,
169 | Act1LargeChest1 = 144,
170 | InnerHellWaypoint = 145,
171 | Act2MediumChestRight = 146,
172 | Act2LargeChestRight = 147,
173 | Act2LargeChestLeft = 148,
174 | TaintedSunAltar = 149,
175 | DesertShrine5 = 150,
176 | DesertShrine4 = 151,
177 | HoradricOrifice = 152,
178 | TyraelsDoor = 153,
179 | GuardCorpse = 154,
180 | HiddenStashRock = 155,
181 | Act2Waypoint = 156,
182 | Act1WildernessWaypoint = 157,
183 | SkeletonCorpseIsAnOxymoron = 158,
184 | HiddenStashRockB = 159,
185 | SmallFire = 160,
186 | MediumFire = 161,
187 | LargeFire = 162,
188 | Act1CliffHidingSpot = 163,
189 | ManaWell1 = 164,
190 | ManaWell2 = 165,
191 | ManaWell3 = 166,
192 | ManaWell4 = 167,
193 | ManaWell5 = 168,
194 | HollowLog = 169,
195 | JungleHealWell = 170,
196 | SkeletonCorpseIsStillAnOxymoron = 171,
197 | DesertHealthShrine = 172,
198 | ManaWell7 = 173,
199 | LooseRock = 174,
200 | LooseBoulder = 175,
201 | MediumChestLeft = 176,
202 | LargeChestLeft2 = 177,
203 | GuardCorpseOnAStick = 178,
204 | Bookshelf1 = 179,
205 | Bookshelf2 = 180,
206 | JungleChest = 181,
207 | TombCoffin = 182,
208 | JungleMediumChestLeft = 183,
209 | JungleShrine2 = 184,
210 | JungleStashObject1 = 185,
211 | JungleStashObject2 = 186,
212 | JungleStashObject3 = 187,
213 | JungleStashObject4 = 188,
214 | DummyCainPortal = 189,
215 | JungleShrine3 = 190,
216 | JungleShrine4 = 191,
217 | TeleportationPad1 = 192,
218 | LamEsensTome = 193,
219 | StairsL = 194,
220 | StairsR = 195,
221 | FloorTrap = 196,
222 | JungleShrine5 = 197,
223 | TallChestLeft = 198,
224 | MephistoShrine1 = 199,
225 | MephistoShrine2 = 200,
226 | MephistoShrine3 = 201,
227 | MephistoManaShrine = 202,
228 | MephistoLair = 203,
229 | StashBox = 204,
230 | StashAltar = 205,
231 | MafistoHealthShrine = 206,
232 | Act3WaterRocks = 207,
233 | Basket1 = 208,
234 | Basket2 = 209,
235 | Act3WaterLogs = 210,
236 | Act3WaterRocksGirl = 211,
237 | Act3WaterBubbles = 212,
238 | Act3WaterLogsX = 213,
239 | Act3WaterRocksB = 214,
240 | Act3WaterRocksGirlC = 215,
241 | Act3WaterRocksY = 216,
242 | Act3WaterLogsZ = 217,
243 | WebCoveredTree1 = 218,
244 | WebCoveredTree2 = 219,
245 | WebCoveredTree3 = 220,
246 | WebCoveredTree4 = 221,
247 | Pillar = 222,
248 | Cocoon = 223,
249 | Cocoon2 = 224,
250 | SkullPileH1 = 225,
251 | OuterHellShrine = 226,
252 | Act3WaterRocksGirlW = 227,
253 | Act3BigLog = 228,
254 | SlimeDoor1 = 229,
255 | SlimeDoor2 = 230,
256 | OuterHellShrine2 = 231,
257 | OuterHellShrine3 = 232,
258 | PillarH2 = 233,
259 | Act3BigLogC = 234,
260 | Act3BigLogD = 235,
261 | HellHealthShrine = 236,
262 | Act3TownWaypoint = 237,
263 | WaypointH = 238,
264 | BurningBodyTown = 239,
265 | Gchest1L = 240,
266 | Gchest2R = 241,
267 | Gchest3R = 242,
268 | GLchest3L = 243,
269 | SewersRatNest = 244,
270 | BurningBodyTown2 = 245,
271 | SewersRatNest2 = 246,
272 | Act1BedBed1 = 247,
273 | Act1BedBed2 = 248,
274 | HellManaShrine = 249,
275 | ExplodingCow = 250,
276 | GidbinnAltar = 251,
277 | GidbinnAltarDecoy = 252,
278 | DiabloRightLight = 253,
279 | DiabloLeftLight = 254,
280 | DiabloStartPoint = 255,
281 | Act1CabinStool = 256,
282 | Act1CabinWood = 257,
283 | Act1CabinWood2 = 258,
284 | HellSkeletonSpawnNW = 259,
285 | Act1HolyShrine = 260,
286 | TombsFloorTrapSpikes = 261,
287 | Act1CathedralShrine = 262,
288 | Act1JailShrine1 = 263,
289 | Act1JailShrine2 = 264,
290 | Act1JailShrine3 = 265,
291 | MaggotLairGooPile = 266,
292 | Bank = 267,
293 | WirtCorpse = 268,
294 | GoldPlaceHolder = 269,
295 | GuardCorpse2 = 270,
296 | DeadVillager1 = 271,
297 | DeadVillager2 = 272,
298 | DummyFlameNoDamage = 273,
299 | TinyPixelShapedThingie = 274,
300 | CavesHealthShrine = 275,
301 | CavesManaShrine = 276,
302 | CaveMagicShrine = 277,
303 | Act3DungeonManaShrine = 278,
304 | Act3SewersMagicShrine1 = 279,
305 | Act3SewersHealthWell = 280,
306 | Act3SewersManaWell = 281,
307 | Act3SewersMagicShrine2 = 282,
308 | Act2BrazierCeller = 283,
309 | Act2TombAnubisCoffin = 284,
310 | Act2Brazier = 285,
311 | Act2BrazierTall = 286,
312 | Act2BrazierSmall = 287,
313 | Act2CellerWaypoint = 288,
314 | HarumBedBed = 289,
315 | IronGrateDoorLeft = 290,
316 | IronGrateDoorRight = 291,
317 | WoodenGrateDoorLeft = 292,
318 | WoodenGrateDoorRight = 293,
319 | WoodenDoorLeft = 294,
320 | WoodenDoorRight = 295,
321 | TombsWallTorchLeft = 296,
322 | TombsWallTorchRight = 297,
323 | ArcaneSanctuaryPortal = 298,
324 | Act2HaramMagicShrine1 = 299,
325 | Act2HaramMagicShrine2 = 300,
326 | MaggotHealthWell = 301,
327 | MaggotManaWell = 302,
328 | ArcaneSanctuaryMagicShrine = 303,
329 | TeleportationPad2 = 304,
330 | TeleportationPad3 = 305,
331 | TeleportationPad4 = 306,
332 | DummyArcaneThing1 = 307,
333 | DummyArcaneThing2 = 308,
334 | DummyArcaneThing3 = 309,
335 | DummyArcaneThing4 = 310,
336 | DummyArcaneThing5 = 311,
337 | DummyArcaneThing6 = 312,
338 | DummyArcaneThing7 = 313,
339 | HaremDeadGuard1 = 314,
340 | HaremDeadGuard2 = 315,
341 | HaremDeadGuard3 = 316,
342 | HaremDeadGuard4 = 317,
343 | HaremEunuchBlocker = 318,
344 | ArcaneHealthWell = 319,
345 | ArcaneManaWell = 320,
346 | TestData2 = 321,
347 | Act2TombWell = 322,
348 | Act2SewerWaypoint = 323,
349 | Act3TravincalWaypoint = 324,
350 | Act3SewerMagicShrine = 325,
351 | Act3SewerDeadBody = 326,
352 | Act3SewerTorch = 327,
353 | Act3KurastTorch = 328,
354 | MafistoLargeChestLeft = 329,
355 | MafistoLargeChestRight = 330,
356 | MafistoMediumChestLeft = 331,
357 | MafistoMediumChestRight = 332,
358 | SpiderLairLargeChestLeft = 333,
359 | SpiderLairTallChestLeft = 334,
360 | SpiderLairMediumChestRight = 335,
361 | SpiderLairTallChestRight = 336,
362 | SteegStone = 337,
363 | GuildVault = 338,
364 | TrophyCase = 339,
365 | MessageBoard = 340,
366 | MephistoBridge = 341,
367 | HellGate = 342,
368 | Act3KurastManaWell = 343,
369 | Act3KurastHealthWell = 344,
370 | HellFire1 = 345,
371 | HellFire2 = 346,
372 | HellFire3 = 347,
373 | HellLava1 = 348,
374 | HellLava2 = 349,
375 | HellLava3 = 350,
376 | HellLightSource1 = 351,
377 | HellLightSource2 = 352,
378 | HellLightSource3 = 353,
379 | HoradricCubeChest = 354,
380 | HoradricScrollChest = 355,
381 | StaffOfKingsChest = 356,
382 | YetAnotherTome = 357,
383 | HellBrazier1 = 358,
384 | HellBrazier2 = 359,
385 | DungeonRockPile = 360,
386 | Act3DungeonMagicShrine = 361,
387 | Act3DungeonBasket = 362,
388 | OuterHellHungSkeleton = 363,
389 | GuyForDungeon = 364,
390 | Act3DungeonCasket = 365,
391 | Act3SewerStairs = 366,
392 | Act3SewerStairsToLevel3 = 367,
393 | DarkWandererStartPosition = 368,
394 | TrappedSoulPlaceHolder = 369,
395 | Act3TownTorch = 370,
396 | LargeChestR = 371,
397 | InnerHellBoneChest = 372,
398 | HellSkeletonSpawnNE = 373,
399 | Act3WaterFog = 374,
400 | DummyNotUsed = 375,
401 | HellForge = 376,
402 | GuildPortal = 377,
403 | HratliStartPosition = 378,
404 | HratliEndPosition = 379,
405 | BurningTrappedSoul1 = 380,
406 | BurningTrappedSoul2 = 381,
407 | NatalyaStartPosition = 382,
408 | StuckedTrappedSoul1 = 383,
409 | StuckedTrappedSoul2 = 384,
410 | CainStartPosition = 385,
411 | StairSR = 386,
412 | ArcaneLargeChestLeft = 387,
413 | ArcaneCasket = 388,
414 | ArcaneLargeChestRight = 389,
415 | ArcaneSmallChestLeft = 390,
416 | ArcaneSmallChestRight = 391,
417 | DiabloSeal1 = 392,
418 | DiabloSeal2 = 393,
419 | DiabloSeal3 = 394,
420 | DiabloSeal4 = 395,
421 | DiabloSeal5 = 396,
422 | SparklyChest = 397,
423 | PandamoniumFortressWaypoint = 398,
424 | InnerHellFissure = 399,
425 | HellMesaBrazier = 400,
426 | Smoke = 401,
427 | ValleyWaypoint = 402,
428 | HellBrazier3 = 403,
429 | CompellingOrb = 404,
430 | KhalimChest1 = 405,
431 | KhalimChest2 = 406,
432 | KhalimChest3 = 407,
433 | SiegeMachineControl = 408,
434 | PotOTorch = 409,
435 | PyoxFirePit = 410,
436 | ExpansionChestRight = 413,
437 | ExpansionWildernessShrine1 = 414,
438 | ExpansionWildernessShrine2 = 415,
439 | ExpansionHiddenStash = 416,
440 | ExpansionWildernessFlag = 417,
441 | ExpansionWildernessBarrel = 418,
442 | ExpansionSiegeBarrel = 419,
443 | ExpansionWoodChestLeft = 420,
444 | ExpansionWildernessShrine3 = 421,
445 | ExpansionManaShrine = 422,
446 | ExpansionHealthShrine = 423,
447 | BurialChestLeft = 424,
448 | BurialChestRight = 425,
449 | ExpansionWell = 426,
450 | ExpansionWildernessShrine4 = 427,
451 | ExpansionWildernessShrine5 = 428,
452 | ExpansionWaypoint = 429,
453 | ExpansionChestLeft = 430,
454 | ExpansionWoodChestRight = 431,
455 | ExpansionSmallChestLeft = 432,
456 | ExpansionSmallChestRight = 433,
457 | ExpansionTorch1 = 434,
458 | ExpansionCampFire = 435,
459 | ExpansionTownTorch = 436,
460 | ExpansionTorch2 = 437,
461 | ExpansionBurningBodies = 438,
462 | ExpansionBurningPit = 439,
463 | ExpansionTribalFlag = 440,
464 | ExpansionTownFlag = 441,
465 | ExpansionChandelier = 442,
466 | ExpansionJar1 = 443,
467 | ExpansionJar2 = 444,
468 | ExpansionJar3 = 445,
469 | ExpansionSwingingHeads = 446,
470 | ExpansionWildernessPole = 447,
471 | AnimatedSkullAndRockPile = 448,
472 | ExpansionTownGate = 449,
473 | SkullAndRockPile = 450,
474 | SiegeHellGate = 451,
475 | EnemyCampBanner1 = 452,
476 | EnemyCampBanner2 = 453,
477 | ExpansionExplodingChest = 454,
478 | ExpansionSpecialChest = 455,
479 | ExpansionDeathPole = 456,
480 | ExpansionDeathPoleLeft = 457,
481 | TempleAltar = 458,
482 | DrehyaTownStartPosition = 459,
483 | DrehyaWildernessStartPosition = 460,
484 | NihlathakTownStartPosition = 461,
485 | NihlathakWildernessStartPosition = 462,
486 | IceCaveHiddenStash = 463,
487 | IceCaveHealthShrine = 464,
488 | IceCaveManaShrine = 465,
489 | IceCaveEvilUrn = 466,
490 | IceCaveJar1 = 467,
491 | IceCaveJar2 = 468,
492 | IceCaveJar3 = 469,
493 | IceCaveJar4 = 470,
494 | IceCaveJar5 = 471,
495 | IceCaveMagicShrine = 472,
496 | CagedWussie = 473,
497 | AncientStatue3 = 474,
498 | AncientStatue1 = 475,
499 | AncientStatue2 = 476,
500 | DeadBarbarian = 477,
501 | ClientSmoke = 478,
502 | IceCaveMagicShrine2 = 479,
503 | IceCaveTorch1 = 480,
504 | IceCaveTorch2 = 481,
505 | ExpansionTikiTorch = 482,
506 | WorldstoneManaShrine = 483,
507 | WorldstoneHealthShrine = 484,
508 | WorldstoneTomb1 = 485,
509 | WorldstoneTomb2 = 486,
510 | WorldstoneTomb3 = 487,
511 | WorldstoneMagicShrine = 488,
512 | WorldstoneTorch1 = 489,
513 | WorldstoneTorch2 = 490,
514 | ExpansionSnowyManaShrine1 = 491,
515 | ExpansionSnowyHealthShrine = 492,
516 | ExpansionSnowyWell = 493,
517 | WorldstoneWaypoint = 494,
518 | ExpansionSnowyMagicShrine2 = 495,
519 | ExpansionWildernessWaypoint = 496,
520 | ExpansionSnowyMagicShrine3 = 497,
521 | WorldstoneWell = 498,
522 | WorldstoneMagicShrine2 = 499,
523 | ExpansionSnowyObject1 = 500,
524 | ExpansionSnowyWoodChestLeft = 501,
525 | ExpansionSnowyWoodChestRight = 502,
526 | WorldstoneMagicShrine3 = 503,
527 | ExpansionSnowyWoodChest2Left = 504,
528 | ExpansionSnowyWoodChest2Right = 505,
529 | SnowySwingingHeads = 506,
530 | SnowyDebris = 507,
531 | PenBreakableDoor = 508,
532 | ExpansionTempleMagicShrine1 = 509,
533 | ExpansionSnowyPoleMR = 510,
534 | IceCaveWaypoint = 511,
535 | ExpansionTempleMagicShrine2 = 512,
536 | ExpansionTempleWell = 513,
537 | ExpansionTempleTorch1 = 514,
538 | ExpansionTempleTorch2 = 515,
539 | ExpansionTempleObject1 = 516,
540 | ExpansionTempleObject2 = 517,
541 | WorldstoneMrBox = 518,
542 | IceCaveWell = 519,
543 | ExpansionTempleMagicShrine = 520,
544 | ExpansionTempleHealthShrine = 521,
545 | ExpansionTempleManaShrine = 522,
546 | BlacksmithForge = 523,
547 | WorldstoneTomb1Left = 524,
548 | WorldstoneTomb2Left = 525,
549 | WorldstoneTomb3Left = 526,
550 | IceCaveBubblesU = 527,
551 | IceCaveBubblesS = 528,
552 | RedBaalsLairTomb1 = 529,
553 | RedBaalsLairTomb1Left = 530,
554 | RedBaalsLairTomb2 = 531,
555 | RedBaalsLairTomb2Left = 532,
556 | RedBaalsLairTomb3 = 533,
557 | RedBaalsLairTomb3Left = 534,
558 | RedBaalsLairMrBox = 535,
559 | RedBaalsLairTorch1 = 536,
560 | RedBaalsLairTorch2 = 537,
561 | CandlesTemple = 538,
562 | TempleWaypoint = 539,
563 | ExpansionDeadPerson1 = 540,
564 | TempleGroundTomb = 541,
565 | LarzukGreeting = 542,
566 | LarzukStandard = 543,
567 | TempleGroundTombLeft = 544,
568 | ExpansionDeadPerson2 = 545,
569 | AncientsAltar = 546,
570 | ArreatSummitDoorToWorldstone = 547,
571 | ExpansionWeaponRackRight = 548,
572 | ExpansionWeaponRackLeft = 549,
573 | ExpansionArmorStandRight = 550,
574 | ExpansionArmorStandLeft = 551,
575 | ArreatsSummitTorch2 = 552,
576 | ExpansionFuneralSpire = 553,
577 | ExpansionBurningLogs = 554,
578 | IceCaveSteam = 555,
579 | ExpansionDeadPerson3 = 556,
580 | BaalsLair = 557,
581 | FrozenAnya = 558,
582 | BBQBunny = 559,
583 | BaalTorchBig = 560,
584 | InvisibleAncient = 561,
585 | InvisibleBase = 562,
586 | BaalsPortal = 563,
587 | ArreatSummitDoor = 564,
588 | LastPortal = 565,
589 | LastLastPortal = 566,
590 | ZooTestData = 567,
591 | KeeperTestData = 568,
592 | BaalsPortal2 = 569,
593 | FirePlaceGuy = 570,
594 | DoorBlocker1 = 571,
595 | DoorBlocker2 = 572,
596 | // Added manually
597 | GoodChest = 580,
598 | NotSoGoodChest = 581
599 | };
600 | }
601 |
--------------------------------------------------------------------------------