├── .gitignore
├── BUILD.md
├── COPYING
├── COPYING.LESSER
├── Examples
├── HelloWorld
│ ├── .gitignore
│ ├── HelloWorld.sln
│ ├── HelloWorld
│ │ ├── HelloWorld.vcxproj
│ │ ├── HelloWorld.vcxproj.filters
│ │ ├── HelloWorld.vcxproj.user
│ │ ├── S4ModApi.h
│ │ ├── S4ModApi.lib
│ │ ├── dllmain.cpp
│ │ └── splash.bmp
│ └── README.md
├── LuaExample
│ ├── .gitignore
│ ├── LuaExample.sln
│ ├── LuaExample
│ │ ├── LuaExample.vcxproj
│ │ ├── LuaExample.vcxproj.filters
│ │ ├── LuaExample.vcxproj.user
│ │ ├── Resource.rc
│ │ ├── S4ModApi.h
│ │ ├── S4ModApi.lib
│ │ ├── dllmain.cpp
│ │ ├── resource.h
│ │ ├── rwm-down.bmp
│ │ ├── rwm-hover.bmp
│ │ ├── rwm.bmp
│ │ ├── sm-down.bmp
│ │ ├── sm-hover.bmp
│ │ └── sm.bmp
│ ├── README.md
│ └── luaexample.png
└── SelectionLimitExample
│ ├── .gitignore
│ ├── README.md
│ ├── SelectionLimitExample.sln
│ ├── SelectionLimitExample
│ ├── S4ModApi.h
│ ├── S4ModApi.lib
│ ├── SelectionLimitExample.vcxproj
│ ├── SelectionLimitExample.vcxproj.filters
│ ├── SelectionLimitExample.vcxproj.user
│ └── dllmain.cpp
│ └── units-selected.png
├── README.md
├── S4ModApi.sln
├── S4ModApi
├── .gitignore
├── CBltHook.cpp
├── CBltHook.h
├── CCustomUi.cpp
├── CCustomUi.h
├── CDialog.cpp
├── CDialog.h
├── CEntityHook.cpp
├── CEntityHook.h
├── CFrameHook.cpp
├── CFrameHook.h
├── CGuiBltHook.cpp
├── CGuiBltHook.h
├── CGuiClearHook.cpp
├── CGuiClearHook.h
├── CGuiElementBltHook.cpp
├── CGuiElementBltHook.h
├── CHook.cpp
├── CHook.h
├── CLuaOpenHook.cpp
├── CLuaOpenHook.h
├── CMapInitHook.cpp
├── CMapInitHook.h
├── CMessageBox.cpp
├── CMessageBox.h
├── CMod.cpp
├── CMod.h
├── CMouseHook.cpp
├── CMouseHook.h
├── CS4Build.cpp
├── CS4Casting.cpp
├── CS4CustomUi.cpp
├── CS4Debug.cpp
├── CS4Entity.cpp
├── CS4Error.cpp
├── CS4GarrisonWarriors.cpp
├── CS4GoodDistribution.cpp
├── CS4Landscape.cpp
├── CS4Listeners.cpp
├── CS4MenuEvents.cpp
├── CS4Misc.cpp
├── CS4Recruit.cpp
├── CS4Screen.cpp
├── CS4Scripting.cpp
├── CS4Selection.cpp
├── CS4SendWarriors.cpp
├── CS4Singleton.cpp
├── CS4Trading.cpp
├── CS4Unknown.cpp
├── CSelectionMod.cpp
├── CSelectionMod.h
├── CSettlerSendHook.cpp
├── CSettlerSendHook.h
├── CSettlers4Api.h
├── CTickHook.cpp
├── CTickHook.h
├── CUpdate.cpp
├── CUpdate.h
├── Console.cpp
├── Console.h
├── DebugInfo.cpp
├── DebugProgram.cpp
├── DebugRender.cpp
├── DebugRender.h
├── Log.cpp
├── Log.h
├── S4CreateInterface.cpp
├── S4ModApi.h
├── S4ModApi.rc
├── S4ModApi.vcxproj
├── S4ModApi.vcxproj.filters
├── S4ModApi.vcxproj.user
├── dllmain.cpp
├── globals.cpp
├── globals.h
├── lib
│ ├── .gitignore
│ ├── Debug
│ │ ├── Lua321.lib
│ │ └── Precompiled.lib
│ ├── Debug142
│ │ ├── Lua321.lib
│ │ └── Precompiled.lib
│ ├── Release
│ │ ├── Lua321.lib
│ │ └── Precompiled.lib
│ ├── hlib.cpp
│ ├── hlib.h
│ ├── lauxlib.h
│ ├── lua.h
│ ├── luadebug.h
│ └── lualib.h
├── md5.cpp
├── md5.h
├── module.cpp
├── module.h
├── patterns.cpp
├── patterns.h
├── resource.h
├── s4.cpp
├── s4.h
├── safemem.cpp
└── safemem.h
├── UpdateExamples.bat
└── VERSION.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # gitignore for C++
2 | # Compiled Object files
3 | *.slo
4 | *.lo
5 | *.o
6 |
7 | # Compiled Dynamic libraries
8 | *.so
9 | *.dylib
10 |
11 | # Compiled Static libraries
12 | *.lai
13 | *.la
14 | *.a
15 |
16 | # Visual Studio Files
17 | /Debug
18 | /Release
19 | /Debug142
20 | *.suo
21 | *.csproj.user
22 | *.vbproj.user
23 | ipch
24 | *sdf
25 | .vs
26 | *.aps
27 |
28 | /PackageRelease.bat
29 | /*.zip
30 | *.xcf
31 | deploy.bat
32 |
--------------------------------------------------------------------------------
/BUILD.md:
--------------------------------------------------------------------------------
1 | # S4ModApi Build Instructions
2 |
3 | To build the S4ModApi project, you will need Visual Studio 2019 and the build tools v141_xp and v142 installed.
4 |
5 | It is also sufficient to only have build tools v142 installed if you only want to create debug builds. The release is build using the v141_xp build tools.
6 |
7 |
8 |
9 | ## IDE Setup
10 |
11 | 1. Choose and download a Version of Visual Studio from [here](https://visualstudio.microsoft.com/de/downloads/). If you need help installing it, follow [these instructions](https://docs.microsoft.com/en-us/visualstudio/install/install-visual-studio?view=vs-2019).
12 | 2. Choose the following workloads during installation:
13 | * **Desktop development with C++**
14 | * **C++ Windows XP support for VS 2017**
15 |
16 | This will install the latest MSVC Buildtools for x64/x86 v142 and v141_xp.
17 |
18 |
19 |
20 | ## Build Configurations
21 |
22 | The project can be build using one of the following configurations.
23 |
24 | | Configuration | Description |
25 | | ------------- | ------------------------------------------------------------ |
26 | | Release | Create a release build using the v141_xp build tools. Logging and console is disabled. |
27 | | Debug | Create a debug build using the v141_xp build tools. Logging and console is enabled. |
28 | | Debug142 | Create a debug build using the v142 build tools. Logging and console is enabled. |
29 |
30 | Note: If you only have the build tools v142 installed, make sure to change the configuration to Debug142.
31 |
32 | To build all configurations in one step do the following.
33 |
34 | 1. Open the **S4ModApi.sln** in Visual Studio 2019.
35 | 2. In the top menu select **Build** and click **Batch build**.
36 | 3. Make sure all configurations are selected and click **Build**.
37 |
38 |
39 |
40 | ## Deployment
41 |
42 | You can create a deploy script in the Release, Debug, Debug142 output directories. It will be automatically called when a build finished. You can use it to copy the S4ModApi.dll to your game installation.
43 |
44 | Example of a deploy.bat:
45 |
46 | ```shell
47 | copy %0\..\S4ModApi.dll "G:\Programme\The Settlers History Collection\The Settlers IV\"
48 | exit 0
49 | ```
50 |
51 |
52 |
53 | ## Packaging
54 |
55 | Run the PackageRelease.bat script to create a zip file containing the following files.
56 |
57 | | File | Description |
58 | | ------------ | ------------------------------------------------------------ |
59 | | LICENSE.md | MIT license file for the binary distribution. |
60 | | S4ModApi.dll | The S4ModApi library that players must install. |
61 | | S4ModApi.h | The header that mod developers must install. |
62 | | S4ModApi.lib | An import library that modders can use to link against S4ModApi.dll. |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/.gitignore:
--------------------------------------------------------------------------------
1 | # gitignore for C++
2 | # Compiled Object files
3 | *.slo
4 | *.lo
5 | *.o
6 |
7 | # Compiled Dynamic libraries
8 | *.so
9 | *.dylib
10 |
11 | # Compiled Static libraries
12 | *.lai
13 | *.la
14 | *.a
15 |
16 | # Visual Studio Files
17 | Debug
18 | Release
19 | *.suo
20 | *.csproj.user
21 | *.vbproj.user
22 | ipch
23 | *sdf
24 | .vs
25 | *.aps
26 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/HelloWorld.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30413.136
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloWorld", "HelloWorld\HelloWorld.vcxproj", "{38C5D2B2-2026-42A6-8C31-7BCC5FD25A08}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Release|x86 = Release|x86
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {38C5D2B2-2026-42A6-8C31-7BCC5FD25A08}.Release|x86.ActiveCfg = Release|Win32
14 | {38C5D2B2-2026-42A6-8C31-7BCC5FD25A08}.Release|x86.Build.0 = Release|Win32
15 | EndGlobalSection
16 | GlobalSection(SolutionProperties) = preSolution
17 | HideSolutionNode = FALSE
18 | EndGlobalSection
19 | GlobalSection(ExtensibilityGlobals) = postSolution
20 | SolutionGuid = {AA9D3F68-8F50-4240-8656-FD39F4A0CB74}
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/HelloWorld/HelloWorld.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Release
6 | Win32
7 |
8 |
9 |
10 | 16.0
11 | Win32Proj
12 | {38c5d2b2-2026-42a6-8c31-7bcc5fd25a08}
13 | HelloWorld
14 | 10.0
15 | HelloWorld
16 |
17 |
18 |
19 | DynamicLibrary
20 | false
21 | v142
22 | true
23 | Unicode
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | false
36 | .asi
37 |
38 |
39 |
40 | Level3
41 | true
42 | true
43 | true
44 | WIN32;NDEBUG;HelloWorld_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
45 | true
46 |
47 |
48 | Windows
49 | true
50 | true
51 | true
52 | false
53 |
54 |
55 | if exist "$(OutDir)deploy.bat" (call "$(OutDir)deploy.bat" )
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/HelloWorld/HelloWorld.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Quelldateien
20 |
21 |
22 |
23 |
24 | Headerdateien
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/HelloWorld/HelloWorld.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/HelloWorld/S4ModApi.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/HelloWorld/HelloWorld/S4ModApi.lib
--------------------------------------------------------------------------------
/Examples/HelloWorld/HelloWorld/dllmain.cpp:
--------------------------------------------------------------------------------
1 | #define WIN32_LEAN_AND_MEAN
2 | #include
3 |
4 | #include "S4ModApi.h"
5 | #pragma comment(lib, "S4ModApi")
6 |
7 | static S4API s4; // the interface to the Settlers 4 Mod API
8 | static LPCVOID splashHandle; // the handle to the splash image
9 |
10 | static void CleanUp() {
11 | if (NULL != splashHandle) {
12 | s4->DestroyCustomUiElement(splashHandle);
13 | splashHandle = NULL;
14 | }
15 | if (NULL != s4) {
16 | s4->Release();
17 | s4 = NULL;
18 | }
19 | };
20 |
21 | BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {
22 | switch (ul_reason_for_call) {
23 | case DLL_PROCESS_ATTACH: {
24 | s4 = S4ApiCreate(); // get an interface to the mod api
25 | if (NULL == s4) break;
26 |
27 | WCHAR imgFn[MAX_PATH]; // the filename of the splash image
28 | INT filenameLen = GetModuleFileNameW(hModule, imgFn, _countof(imgFn))
29 | - 4; // subtract 4 to remove the .asi file ending
30 | if (filenameLen <= 0) break;
31 |
32 | // append \splash.bmp to the filename of the module
33 | wcscpy_s(&imgFn[filenameLen], _countof(imgFn) - filenameLen, L"\\splash.bmp");
34 |
35 | S4CustomUiElement cuie = { 0 };
36 | cuie.size = sizeof(cuie);
37 | cuie.szImg = imgFn;
38 | cuie.x = 50;
39 | cuie.y = 50;
40 | cuie.screen = S4_SCREEN_MAINMENU;
41 | cuie.actionHandler = [](LPCVOID lpUiElement, S4_CUSTOM_UI_ENUM newstate) {
42 | if (newstate & S4_CUSTOM_UI_SELECTED) {
43 | CleanUp();
44 | }
45 | return (HRESULT)0;
46 | };
47 |
48 | splashHandle = s4->CreateCustomUiElement(&cuie);
49 | break;
50 | }
51 | case DLL_THREAD_ATTACH:
52 | case DLL_THREAD_DETACH:
53 | break;
54 | case DLL_PROCESS_DETACH:
55 | CleanUp();
56 | break;
57 | }
58 | return TRUE;
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/HelloWorld/splash.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/HelloWorld/HelloWorld/splash.bmp
--------------------------------------------------------------------------------
/Examples/HelloWorld/README.md:
--------------------------------------------------------------------------------
1 | This is a example project for the S4ModApi. The goal of the Hello World Plugin is to display a hello world popup in the main menu of the game. Have a look at the [article](https://github.com/nyfrk/S4ModApi/wiki/HelloWorldPlugin) that goes step by step through this example.
2 |
3 |
4 |
5 | # License
6 |
7 | The HelloWorld example is licensed under the MIT license.
--------------------------------------------------------------------------------
/Examples/LuaExample/.gitignore:
--------------------------------------------------------------------------------
1 | # gitignore for C++
2 | # Compiled Object files
3 | *.slo
4 | *.lo
5 | *.o
6 |
7 | # Compiled Dynamic libraries
8 | *.so
9 | *.dylib
10 |
11 | # Compiled Static libraries
12 | *.lai
13 | *.la
14 | *.a
15 |
16 | # Visual Studio Files
17 | Debug
18 | Release
19 | *.suo
20 | *.csproj.user
21 | *.vbproj.user
22 | ipch
23 | *sdf
24 | .vs
25 | *.aps
26 |
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30413.136
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LuaExample", "LuaExample\LuaExample.vcxproj", "{A33B9263-8378-4E4D-ACC8-68EE8173D199}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x86 = Debug|x86
11 | Release|x86 = Release|x86
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {A33B9263-8378-4E4D-ACC8-68EE8173D199}.Debug|x86.ActiveCfg = Debug|Win32
15 | {A33B9263-8378-4E4D-ACC8-68EE8173D199}.Debug|x86.Build.0 = Debug|Win32
16 | {A33B9263-8378-4E4D-ACC8-68EE8173D199}.Release|x86.ActiveCfg = Release|Win32
17 | {A33B9263-8378-4E4D-ACC8-68EE8173D199}.Release|x86.Build.0 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {3B1BC253-72A6-4B3E-BCBD-D409F8386153}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/LuaExample.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | 16.0
15 | Win32Proj
16 | {a33b9263-8378-4e4d-acc8-68ee8173d199}
17 | LuaExample
18 | 10.0
19 |
20 |
21 |
22 | DynamicLibrary
23 | true
24 | v142
25 |
26 |
27 | DynamicLibrary
28 | false
29 | v142
30 | true
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | true
46 | .asi
47 |
48 |
49 | false
50 | .asi
51 |
52 |
53 |
54 | Level3
55 | true
56 | WIN32;_DEBUG;LUAEXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
57 | true
58 |
59 |
60 | Windows
61 | true
62 | false
63 |
64 |
65 | if exist "$(OutDir)deploy.bat" (call "$(OutDir)deploy.bat" )
66 |
67 |
68 |
69 |
70 | Level3
71 | true
72 | true
73 | true
74 | WIN32;NDEBUG;LUAEXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
75 | true
76 |
77 |
78 | Windows
79 | true
80 | true
81 | true
82 | false
83 |
84 |
85 | if exist "$(OutDir)deploy.bat" (call "$(OutDir)deploy.bat" )
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/LuaExample.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Quelldateien
20 |
21 |
22 |
23 |
24 | Headerdateien
25 |
26 |
27 |
28 |
29 | Ressourcendateien
30 |
31 |
32 |
33 |
34 | Ressourcendateien
35 |
36 |
37 | Ressourcendateien
38 |
39 |
40 | Ressourcendateien
41 |
42 |
43 | Ressourcendateien
44 |
45 |
46 | Ressourcendateien
47 |
48 |
49 | Ressourcendateien
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/LuaExample.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/Resource.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #include "winres.h"
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | #undef APSTUDIO_READONLY_SYMBOLS
14 |
15 | /////////////////////////////////////////////////////////////////////////////
16 | // Deutsch (Deutschland) resources
17 |
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
19 | LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
20 | #pragma code_page(1252)
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Bitmap
51 | //
52 |
53 | IDB_RWM BITMAP "rwm.bmp"
54 |
55 | IDB_RWM_DOWN BITMAP "rwm-down.bmp"
56 |
57 | IDB_RWM_HOVER BITMAP "rwm-hover.bmp"
58 |
59 | IDB_SM BITMAP "sm.bmp"
60 |
61 | IDB_SM_DOWN BITMAP "sm-down.bmp"
62 |
63 | IDB_SM_HOVER BITMAP "sm-hover.bmp"
64 |
65 | #endif // Deutsch (Deutschland) resources
66 | /////////////////////////////////////////////////////////////////////////////
67 |
68 |
69 |
70 | #ifndef APSTUDIO_INVOKED
71 | /////////////////////////////////////////////////////////////////////////////
72 | //
73 | // Generated from the TEXTINCLUDE 3 resource.
74 | //
75 |
76 |
77 | /////////////////////////////////////////////////////////////////////////////
78 | #endif // not APSTUDIO_INVOKED
79 |
80 |
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/S4ModApi.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/LuaExample/LuaExample/S4ModApi.lib
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Von Microsoft Visual C++ generierte Includedatei.
3 | // Verwendet durch Resource.rc
4 | //
5 | #define IDB_RWM 108
6 | #define IDB_RWM_DOWN 109
7 | #define IDB_RWM_HOVER 110
8 | #define IDB_SM 111
9 | #define IDB_SM_DOWN 112
10 | #define IDB_BITMAP6 113
11 | #define IDB_SM_HOVER 113
12 |
13 | // Next default values for new objects
14 | //
15 | #ifdef APSTUDIO_INVOKED
16 | #ifndef APSTUDIO_READONLY_SYMBOLS
17 | #define _APS_NEXT_RESOURCE_VALUE 114
18 | #define _APS_NEXT_COMMAND_VALUE 40001
19 | #define _APS_NEXT_CONTROL_VALUE 1001
20 | #define _APS_NEXT_SYMED_VALUE 101
21 | #endif
22 | #endif
23 |
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/rwm-down.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/LuaExample/LuaExample/rwm-down.bmp
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/rwm-hover.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/LuaExample/LuaExample/rwm-hover.bmp
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/rwm.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/LuaExample/LuaExample/rwm.bmp
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/sm-down.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/LuaExample/LuaExample/sm-down.bmp
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/sm-hover.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/LuaExample/LuaExample/sm-hover.bmp
--------------------------------------------------------------------------------
/Examples/LuaExample/LuaExample/sm.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/LuaExample/LuaExample/sm.bmp
--------------------------------------------------------------------------------
/Examples/LuaExample/README.md:
--------------------------------------------------------------------------------
1 | This is a example project for the S4ModApi. The goal of the Lua Example Plugin is to demonstrate how a plugin can interact with the games lua virtual machine by adding and calling lua functions. The plugin will add two blue buttons to the game.
2 |
3 | 
4 |
5 | When clicking the **Reveal World Map** button the lua example plugin will call the [ISettlers4Api::RevealWorldMap](https://github.com/nyfrk/S4ModApi/wiki/RevealWorldMap) method. This method will call the [Tutorial.RWM](https://s4.muffinmar.io/scripts/?id=Tutorial_RWM#Tutorial_RWM) lua function to reveal the map. Furthermore the plugin displays a text message in the notification box using [ISettlers4Api::ShowTextMessage](https://github.com/nyfrk/S4ModApi/wiki/ShowTextMessage).
6 |
7 | When clicking the **Call Ext.ShowMessage** button the lua example plugin will call the Ext.ShowMessage lua function. The plugin will add this lua function to the games lua virtual machine by using a Lua Open Hook that is provided by the S4ModApi. The Ext.ShowMessage function uses the S4ModApi to display a message using [ISettlers4Api::ShowTextMessage](https://github.com/nyfrk/S4ModApi/wiki/ShowTextMessage) method. This demonstrates how you can add custom lua functions to the games lua virtual machine and how you can call lua functions from a plugin.
8 |
9 | # License
10 |
11 | The Lua Example Plugin is licensed under the MIT license.
--------------------------------------------------------------------------------
/Examples/LuaExample/luaexample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/LuaExample/luaexample.png
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/.gitignore:
--------------------------------------------------------------------------------
1 | # gitignore for C++
2 | # Compiled Object files
3 | *.slo
4 | *.lo
5 | *.o
6 |
7 | # Compiled Dynamic libraries
8 | *.so
9 | *.dylib
10 |
11 | # Compiled Static libraries
12 | *.lai
13 | *.la
14 | *.a
15 |
16 | # Visual Studio Files
17 | Debug
18 | Release
19 | *.suo
20 | *.csproj.user
21 | *.vbproj.user
22 | ipch
23 | *sdf
24 | .vs
25 | *.aps
26 |
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/README.md:
--------------------------------------------------------------------------------
1 | This is a example project for the S4ModApi. The goal of the Selection Limit Example Plugin is to showcase the removal of the unit selection limit.
2 |
3 | See https://github.com/nyfrk/S4ModApi/wiki/SetMaxSelection.
4 |
5 | 
6 |
7 |
8 |
9 | # License
10 |
11 | The Selection Limit Example Plugin is licensed under the MIT license.
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/SelectionLimitExample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30413.136
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SelectionLimitExample", "SelectionLimitExample\SelectionLimitExample.vcxproj", "{38C5D2B2-2026-42A6-8C31-7BCC5FD25A08}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Release|x86 = Release|x86
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {38C5D2B2-2026-42A6-8C31-7BCC5FD25A08}.Release|x86.ActiveCfg = Release|Win32
14 | {38C5D2B2-2026-42A6-8C31-7BCC5FD25A08}.Release|x86.Build.0 = Release|Win32
15 | EndGlobalSection
16 | GlobalSection(SolutionProperties) = preSolution
17 | HideSolutionNode = FALSE
18 | EndGlobalSection
19 | GlobalSection(ExtensibilityGlobals) = postSolution
20 | SolutionGuid = {AA9D3F68-8F50-4240-8656-FD39F4A0CB74}
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/SelectionLimitExample/S4ModApi.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/SelectionLimitExample/SelectionLimitExample/S4ModApi.lib
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/SelectionLimitExample/SelectionLimitExample.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Release
6 | Win32
7 |
8 |
9 |
10 | 16.0
11 | Win32Proj
12 | {38c5d2b2-2026-42a6-8c31-7bcc5fd25a08}
13 | SelectionLimitExample
14 | 10.0
15 | SelectionLimitExample
16 |
17 |
18 |
19 | DynamicLibrary
20 | false
21 | v142
22 | true
23 | Unicode
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | false
36 | .asi
37 |
38 |
39 |
40 | Level3
41 | true
42 | true
43 | true
44 | WIN32;NDEBUG;SelectionLimitExample_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
45 | true
46 |
47 |
48 | Windows
49 | true
50 | true
51 | true
52 | false
53 |
54 |
55 | if exist "$(OutDir)deploy.bat" (call "$(OutDir)deploy.bat" )
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/SelectionLimitExample/SelectionLimitExample.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Quelldateien
20 |
21 |
22 |
23 |
24 | Headerdateien
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/SelectionLimitExample/SelectionLimitExample.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/SelectionLimitExample/dllmain.cpp:
--------------------------------------------------------------------------------
1 | #define WIN32_LEAN_AND_MEAN
2 | #include
3 |
4 | #include "S4ModApi.h"
5 | #pragma comment(lib, "S4ModApi")
6 |
7 | static S4API s4; // the interface to the Settlers 4 Mod API
8 |
9 | BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {
10 | switch (ul_reason_for_call) {
11 | case DLL_PROCESS_ATTACH: {
12 | s4 = S4ApiCreate(); // get an interface to the mod api
13 | if (NULL != s4) {
14 | s4->SetMaxSelection(1000);
15 | }
16 | break;
17 | }
18 | case DLL_THREAD_ATTACH:
19 | case DLL_THREAD_DETACH:
20 | break;
21 | case DLL_PROCESS_DETACH:
22 | // cleanup
23 | if (NULL != s4) {
24 | s4->SetMaxSelection(100);
25 | s4->Release();
26 | s4 = NULL;
27 | }
28 | break;
29 | }
30 | return TRUE;
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/Examples/SelectionLimitExample/units-selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/Examples/SelectionLimitExample/units-selected.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # S4ModApi [](https://github.com/nyfrk/S4ModApi/releases/latest)
2 | A modding library for Bluebyte's The Settlers 4. The goal of this project is to provide a API to mod developers such that they do not have to resort to reverse engineer the game themselves.
3 |
4 |
5 |
6 | ## Features
7 |
8 | * Create custom UI elements that the player can interact with
9 | * Create player events programmatically
10 | * Run code on specific events
11 | * Dispatch access to common hooks fairly to mods thus reducing conflicts between them
12 | * Simplify ASI mod creation by providing common functions for modding
13 | * Manages a backward compatible ABI for the API
14 | * Single header file
15 | * Open Source
16 |
17 |
18 |
19 | ## Installation for Players
20 |
21 | [Download a release](https://github.com/nyfrk/S4ModApi/releases) and unpack the S4ModApi.dll next to your S4_Main.exe.
22 |
23 |
24 |
25 | ## Remarks for Modders
26 |
27 | Note: The ABI is stable and backward compatible only if you link against the latest release. **Do not distribute your mod linking to a prerelease** (labeled with RC) since the ABI is not stable and not backward compatible. Your mod will break with upcoming releases. Read the [versioning guide](VERSION.md) for more information regarding ABI stability.
28 |
29 | See the [hello world sample mod](https://github.com/nyfrk/S4ModApi/wiki/HelloWorldPlugin) on how to configure your project with the S4ModApi.
30 |
31 | [The **reference** of the API is available in the Wiki](https://github.com/nyfrk/S4ModApi/wiki)
32 |
33 | Please consider contributing features that that we currently do not offer back to this project. You can make sure that your mod stays compatible with upcoming and past releases of The Settlers 4, if you link to the S4ModApi.dll instead of directly linking to the S4_Main.exe. Moreover does it reduce the risk of conflicts between plugins and other mods.
34 |
35 |
36 |
37 | ## Contribute
38 |
39 | We are open for pull requests!
40 |
41 | Follow the [build instructions](BUILD.md) if you want to build the S4ModApi.dll and it's import library.
42 |
43 | Some source files are only provided as precompiled obj files. This is due to license issues.
44 |
45 |
46 |
47 | ## Acknowledgments
48 |
49 | Special thanks to the following contributors. Without their work this project would not be as far as it is today.
50 |
51 | - [**MuffinMario**](https://github.com/MuffinMario) for the creation of [s4.muffinmar.io](https://s4.muffinmar.io/scripts/) and the reversal / documentation of the Lua interface including all function names, their parameters and many enumerations.
52 | - [**Viciten**](https://github.com/Viciten) for the support of [alpha blended bitmaps](https://github.com/nyfrk/S4ModApi/commit/134d532b83d201f43f18b699d877021f512411d3).
53 | - [**oberstrike**](https://github.com/oberstrike) for the contribution of [features and bugfixes](https://github.com/oberstrike/S4ModApi)
54 | - [**WizzardMaker**](https://github.com/WizzardMaker) for the contributions of [features and bugfixes](https://github.com/WizzardMaker/S4ModApi).
55 |
56 |
57 |
58 | ## License
59 |
60 | The S4ModApi project is licensed under the GNU Lesser General Public License version 3 (LGPLv3). See [COPYING.LESSER](COPYING.LESSER) file for details.
61 |
62 |
--------------------------------------------------------------------------------
/S4ModApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29503.13
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "S4ModApi", "S4ModApi\S4ModApi.vcxproj", "{80F4B5D7-9AB1-4DA7-B3A9-C13241352964}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x86 = Debug|x86
11 | Debug142|x86 = Debug142|x86
12 | Release|x86 = Release|x86
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {80F4B5D7-9AB1-4DA7-B3A9-C13241352964}.Debug|x86.ActiveCfg = Debug|Win32
16 | {80F4B5D7-9AB1-4DA7-B3A9-C13241352964}.Debug|x86.Build.0 = Debug|Win32
17 | {80F4B5D7-9AB1-4DA7-B3A9-C13241352964}.Debug142|x86.ActiveCfg = Debug142|Win32
18 | {80F4B5D7-9AB1-4DA7-B3A9-C13241352964}.Debug142|x86.Build.0 = Debug142|Win32
19 | {80F4B5D7-9AB1-4DA7-B3A9-C13241352964}.Release|x86.ActiveCfg = Release|Win32
20 | {80F4B5D7-9AB1-4DA7-B3A9-C13241352964}.Release|x86.Build.0 = Release|Win32
21 | EndGlobalSection
22 | GlobalSection(SolutionProperties) = preSolution
23 | HideSolutionNode = FALSE
24 | EndGlobalSection
25 | GlobalSection(ExtensibilityGlobals) = postSolution
26 | SolutionGuid = {779B4EE4-8F36-40ED-9D04-EEE5F670A740}
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/S4ModApi/.gitignore:
--------------------------------------------------------------------------------
1 | /Debug
2 | /Release
3 | /Debug142
4 | /CFrameHook.cpp
5 | /CMouseHook.cpp
6 | /CS4SendWarriors.cpp
--------------------------------------------------------------------------------
/S4ModApi/CBltHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CBltHook : public CHook {
27 | public:
28 | static CBltHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CBltHook();
37 | static BOOL __stdcall CBltHook::OnBlt(DWORD caller, DWORD ecx, DWORD edx, DWORD _0, DWORD _1, DWORD _2, DWORD _3, DWORD _4, DWORD _5, DWORD _6);
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CCustomUi.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "windows.h"
25 | #include
26 | #include
27 | #include
28 | #include "S4ModApi.h"
29 | #include "CDialog.h"
30 |
31 | class CCustomUi;
32 |
33 | class CCustomUi : public CDialog {
34 | public:
35 | CCustomUi(LPCS4CUSTOMUIELEMENT);
36 | S4_CUSTOM_UI_ENUM GetState();
37 | void SetHandler(LPS4UICALLBACK);
38 | ~CCustomUi();
39 |
40 | protected:
41 | virtual BOOL OnDraw(HDC hdc, const POINT* cursor, const RECT* clientRect) override;
42 | virtual BOOL OnMouse(DWORD dwMouseButton, INT iX, INT iY, DWORD dwMsgId, HWND hwnd) override;
43 | virtual BOOL OnShow() override; // do not call Hide() from here (will deadlock)
44 | virtual BOOL OnHide() override; // do not call Show() from here (will deadlock)
45 |
46 | private:
47 | CCustomUi(const CCustomUi&) = delete;
48 | CCustomUi& operator=(CCustomUi const&) = delete;
49 |
50 | S4_GUI_ENUM m_screenFilter;
51 | RECT m_rect, m_hoverRect, m_selectedRect, m_selectedHoverRect;
52 | HBITMAP m_hImg, m_hImgHover, m_hImgSelected, m_hImgSelectedHover;
53 | std::mutex m_bitmap_mtx;
54 | bool m_visible;
55 |
56 | S4_CUSTOM_UI_ENUM m_state;
57 | volatile LPS4UICALLBACK m_handler;
58 | volatile LPS4UIFILTERCALLBACK m_filterFunc;
59 | };
60 |
--------------------------------------------------------------------------------
/S4ModApi/CDialog.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "windows.h"
25 | #include
26 | #include
27 | #include "S4ModApi.h"
28 |
29 | #define DIALOG_RENDER_PRIORITY 100001
30 |
31 | class CDialog {
32 | public:
33 | const enum FeaturesEnum : unsigned { FeatureNone = 0, FeatureOnMouse = 1, FeatureOnDraw = 2, FeatureAll = 3 } DialogFeatures;
34 |
35 | CDialog(INT x, INT y, INT w, INT h, DWORD flags, FeaturesEnum = FeatureAll);
36 | CDialog(DWORD flags = 0, FeaturesEnum = FeatureAll);
37 | BOOL Show();
38 | BOOL Hide();
39 | BOOL IsShown() const;
40 | BOOL HasFeature(const FeaturesEnum &f) const;
41 | const RECT& GetRect() const;
42 |
43 | virtual ~CDialog();
44 |
45 | protected:
46 | virtual BOOL OnDraw(HDC hdc, const POINT *cursor, const RECT* clientRect);
47 | virtual BOOL OnMouse(DWORD dwMouseButton, INT iX, INT iY, DWORD dwMsgId, HWND hwnd);
48 | virtual BOOL OnShow(); // do not call Hide() from here (will deadlock)
49 | virtual BOOL OnHide(); // do not call Show() from here (will deadlock)
50 | VOID UpdatePositionWithOffsetsFlags(const RECT& source, const RECT* clientRect);
51 |
52 | RECT m_position;
53 | DWORD m_flags;
54 | static S4API s4api;
55 |
56 | private:
57 | CDialog(const CDialog&) = delete;
58 | CDialog& operator=(CDialog const&) = delete;
59 |
60 | volatile bool m_isShown;
61 |
62 | static void Cleanup();
63 |
64 | static void MaintainS4Api();
65 | void ModifyFeatureCounts(signed add);
66 |
67 | static std::mutex state_mutex;
68 | static std::condition_variable condIdle;
69 | static std::vector pending_dialogs;
70 | static volatile enum State : unsigned { StateIdle, StateBusy, StateBusyCleanupRequired } state;
71 | static std::vector dialogs; // how many messageboxes are visible
72 | static S4HOOK hFramehook, hMousehook;
73 | static unsigned countFramehook, countMousehook;
74 |
75 | static HRESULT S4HCALL OnFrameProc(LPDIRECTDRAWSURFACE7 lpSurface, INT32 iPillarboxWidth, LPVOID lpReserved);
76 | static HRESULT S4HCALL OnMouseProc(DWORD dwMouseButton, INT iX, INT iY, DWORD dwMsgId, HWND hwnd, LPCS4UIELEMENT lpUiElement);
77 | };
78 |
--------------------------------------------------------------------------------
/S4ModApi/CEntityHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // JmpPatch
24 | #include "patterns.h"
25 |
26 | #include "CEntityHook.h"
27 |
28 | static hlib::CallPatch OnEntityHook;
29 |
30 | BOOL __stdcall CEntityHook::OnEntity() {
31 | return 0;
32 | }
33 |
34 | //static void __declspec(naked) __onEntity() {
35 | // // todo: add entity hook
36 | // __asm {
37 | // ret
38 | // }
39 | //}
40 |
41 | CEntityHook& CEntityHook::GetInstance() {
42 | static CEntityHook inst;
43 | return inst;
44 | }
45 |
46 | bool CEntityHook::Init() {
47 | TRACE;
48 | /*DWORD addr = g_Patterns.xxx;
49 | if (!addr) return false;
50 |
51 | OnEntityHook = hlib::CallPatch(addr, (DWORD)__onEntity);*/
52 |
53 | return true;
54 | }
55 |
56 | void CEntityHook::Patch() {
57 | TRACE;
58 | OnEntityHook.patch();
59 | }
60 |
61 | void CEntityHook::Unpatch() {
62 | TRACE;
63 | OnEntityHook.unpatch();
64 | }
65 |
66 | CEntityHook::CEntityHook() { TRACE; }
67 |
68 |
69 |
--------------------------------------------------------------------------------
/S4ModApi/CEntityHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CEntityHook : public CHook {
27 | public:
28 | static CEntityHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CEntityHook();
37 | static BOOL __stdcall CEntityHook::OnEntity();
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CFrameHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // JmpPatch
24 | #include "s4.h"
25 | #include "patterns.h"
26 |
27 | #include "CSettlers4Api.h"
28 | #include "CFrameHook.h"
29 | #include "Console.h"
30 |
31 | static hlib::JmpPatch OnFrameHook;
32 | static DWORD* pBase = nullptr;
33 |
34 | DWORD __stdcall CFrameHook::OnFrame() {
35 | TRACE;
36 | // cache the IsCurrentlyOnScreen results in this array
37 | BYTE s4_gui_state[S4_GUI_ENUM_MAXVALUE] = { 0 }; // 0 == unknown, 1 == visible, 2 == hidden
38 | if (pBase) {
39 | INT32 pillarboxWidth = 0;
40 | if (S4::GetInstance().PillarboxWidth) pillarboxWidth = *S4::GetInstance().PillarboxWidth;
41 | LPDIRECTDRAWSURFACE7 dst = (LPDIRECTDRAWSURFACE7)(*(DWORD*)(*(DWORD*)(*(DWORD*)(*pBase) + (g_isGE ? 0x3C : 0x5C)) + 0x4));
42 | mutex.lock();
43 | auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
44 | mutex.unlock();
45 | for (auto& observer : observers) {
46 | auto& param = observer.param;
47 | if (param && param < S4_GUI_ENUM_MAXVALUE) {
48 | switch (s4_gui_state[param]) {
49 | case 0: {
50 | auto res = CSettlers4Api::GetInstance().IsCurrentlyOnScreen((S4_GUI_ENUM)param);
51 | s4_gui_state[param] = res ? 1 : 2;
52 | if (res) break; else continue;
53 | }
54 | case 1: break;
55 | default: continue;
56 | }
57 | }
58 | ((LPS4FRAMECALLBACK)observer.callback)(dst, pillarboxWidth, 0);
59 | }
60 | }
61 | return (DWORD)(OnFrameHook.getAddress() + 5);
62 | }
63 |
64 | static void __declspec(naked) __onFrame() {
65 | __asm {
66 | push ecx
67 | push edx
68 | call CFrameHook::OnFrame
69 | pop edx
70 | pop ecx
71 | pop edi
72 | pop esi
73 | cmp g_isGE, 0
74 | jz lbl_HE
75 | pop ebp // gold edition
76 | jmp lbl_end
77 | lbl_HE :
78 | pop ebx // history edition
79 | lbl_end :
80 | push eax
81 | mov al, 01
82 | ret
83 | }
84 | }
85 |
86 | CFrameHook& CFrameHook::GetInstance() {
87 | static CFrameHook inst;
88 | return inst;
89 | }
90 |
91 | bool CFrameHook::Init() {
92 | TRACE;
93 | if (!g_Patterns.OnFrameHook || !g_Patterns.Backbuffer) return false;
94 |
95 | OnFrameHook = hlib::JmpPatch(g_Patterns.OnFrameHook + 12, (DWORD)__onFrame);
96 | pBase = (DWORD*)(g_Patterns.Backbuffer + (g_isGE ? 34 : 22));
97 |
98 | return true;
99 | }
100 |
101 | void CFrameHook::Patch() {
102 | TRACE;
103 | OnFrameHook.patch();
104 | }
105 |
106 | void CFrameHook::Unpatch() {
107 | TRACE;
108 | OnFrameHook.unpatch();
109 | }
110 |
111 | CFrameHook::CFrameHook() { TRACE; }
112 |
--------------------------------------------------------------------------------
/S4ModApi/CFrameHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CFrameHook : public CHook {
27 | public:
28 | static CFrameHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CFrameHook();
37 | static DWORD __stdcall OnFrame();
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CGuiBltHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // JmpPatch
24 | #include "patterns.h"
25 |
26 | #include "CGuiBltHook.h"
27 |
28 | static hlib::CallPatch OnComposeBltHook, OnSettlerIdHook;
29 |
30 | BOOL __stdcall CGuiBltHook::OnBlt(DWORD id, LPVOID dstSurface, LPRECT dstRect, LPVOID srcSurface, LPRECT srcRect, DWORD ddbltFlags, LPVOID ddbltfx) {
31 | //TRACE; // we do not log this as it will be a mayor performance hit
32 | mutex.lock();
33 | auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
34 | mutex.unlock();
35 | BOOL discard = false;
36 | S4GuiBltParams params;
37 |
38 | params.id = id / 4; // id goes from 0x130 (incl) to 0x167 (excl)
39 | params.dstSurface = dstSurface;
40 | params.dstRect = dstRect;
41 | params.srcSurface = srcSurface;
42 | params.srcRect = srcRect;
43 | params.ddbltFlags = ddbltFlags;
44 | params.ddbltfx = ddbltfx;
45 |
46 | for (auto& observer : observers) {
47 | discard |= ((LPS4GUIBLTCALLBACK)observer.callback)(¶ms, discard);
48 | }
49 |
50 | return discard;
51 | }
52 |
53 | static void __declspec(naked) __onBlt() {
54 | __asm {
55 | sub esp, 16
56 | movdqu[esp], xmm0
57 | sub esp, 16
58 | movdqu[esp], xmm1
59 | sub esp, 16
60 | movdqu[esp], xmm2
61 | sub esp, 16
62 | movdqu[esp], xmm3
63 | sub esp, 16
64 | movdqu[esp], xmm4
65 | sub esp, 16
66 | movdqu[esp], xmm5
67 | sub esp, 16
68 | movdqu[esp], xmm6
69 | sub esp, 16
70 | movdqu[esp], xmm7
71 | sub esp, 128
72 | fsave[esp]
73 |
74 | push ecx
75 | push[esp + 256 + 4 + 20]
76 | push[esp + 256 + 4 + 20]
77 | push[esp + 256 + 4 + 20]
78 | push[esp + 256 + 4 + 20]
79 | push[esp + 256 + 4 + 20]
80 | push ecx
81 | push edi
82 | call CGuiBltHook::OnBlt
83 | pop ecx
84 |
85 | frstor[esp]
86 | add esp, 128
87 | movdqu xmm7, [esp]
88 | add esp, 16
89 | movdqu xmm6, [esp]
90 | add esp, 16
91 | movdqu xmm5, [esp]
92 | add esp, 16
93 | movdqu xmm4, [esp]
94 | add esp, 16
95 | movdqu xmm3, [esp]
96 | add esp, 16
97 | movdqu xmm2, [esp]
98 | add esp, 16
99 | movdqu xmm1, [esp]
100 | add esp, 16
101 | movdqu xmm0, [esp]
102 | add esp, 16
103 |
104 | test al, al
105 | pushf
106 | xor eax, eax
107 | popf
108 | jnz lbl_skip_original
109 | push[esp + 20]
110 | push[esp + 20]
111 | push[esp + 20]
112 | push[esp + 20]
113 | push[esp + 20]
114 | call [esi + 0x18]
115 |
116 | lbl_skip_original:
117 |
118 | pop esi // ret addr
119 | add esp, 20 // clean the stack
120 |
121 | push esi
122 | test eax, eax
123 | ret
124 | }
125 | }
126 |
127 | CGuiBltHook& CGuiBltHook::GetInstance() {
128 | static CGuiBltHook inst;
129 | return inst;
130 | }
131 |
132 | bool CGuiBltHook::Init() {
133 | TRACE;
134 | /*
135 | S4_Main.exe+2647C6 - 8B 45 FC - mov eax,[ebp-04]
136 | S4_Main.exe+2647C9 - 8B 15 08875401 - mov edx,[S4_Main.exe+1058708] { (04860720) }
137 | S4_Main.exe+2647CF - 8D 80 D8456E01 - lea eax,[eax+S4_Main.exe+11F45D8]
138 | S4_Main.exe+2647D5 - 8B 4A 5C - mov ecx,[edx+5C]
139 | S4_Main.exe+2647D8 - 50 - push eax
140 | S4_Main.exe+2647D9 - 8B 45 FC - mov eax,[ebp-04]
141 | S4_Main.exe+2647DC - FF 34 17 - push [edi+edx]
142 | S4_Main.exe+2647DF - 8B 31 - mov esi,[ecx]
143 | S4_Main.exe+2647E1 - 8D 80 B8466E01 - lea eax,[eax+S4_Main.exe+11F46B8]
144 | S4_Main.exe+2647E7 - 50 - push eax
145 | S4_Main.exe+2647E8 - FF 56 18 - call dword ptr [esi+18] <--- we hook here, 5 arguments + ecx
146 | S4_Main.exe+2647EB - 85 C0 - test eax,eax
147 |
148 | */
149 |
150 |
151 | DWORD addr = S4_Main != 0 ? S4_Main + 0x2647E8 : 0;
152 | if (!addr) return false;
153 |
154 | OnComposeBltHook = hlib::CallPatch(addr, (DWORD)__onBlt);
155 |
156 | return true;
157 | }
158 |
159 | void CGuiBltHook::Patch() {
160 | TRACE;
161 | OnComposeBltHook.patch();
162 | }
163 |
164 | void CGuiBltHook::Unpatch() {
165 | TRACE;
166 | OnComposeBltHook.unpatch();
167 | }
168 |
169 | CGuiBltHook::CGuiBltHook() { TRACE; }
170 |
--------------------------------------------------------------------------------
/S4ModApi/CGuiBltHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CGuiBltHook : public CHook {
27 | public:
28 | static CGuiBltHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CGuiBltHook();
37 | static BOOL __stdcall OnBlt(DWORD id, LPVOID dstSurface, LPRECT dstRect, LPVOID srcSurface, LPRECT srcRect, DWORD ddbltFlags, LPVOID ddbltfx);
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CGuiClearHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // JmpPatch
24 | #include "patterns.h"
25 | #include "safemem.h"
26 |
27 | #include "CGuiClearHook.h"
28 |
29 | static hlib::JmpPatch OnClearHook;
30 | DWORD Orig; // you store the original function address here. Populate it before you install the call patch.
31 | DWORD backJmp;
32 |
33 | struct GUIContainer {
34 | WORD type;
35 | WORD x;
36 | WORD y;
37 | WORD width;
38 | WORD height;
39 | WORD mainTexture;
40 | WORD transparency;
41 | WORD containerPointer;
42 | //sizeof == 36
43 | };
44 |
45 | #pragma optimize("", off)
46 | void __stdcall CGuiClearHook::OnClear(DWORD *surfaceContainer) {
47 | //TRACE; // we do not log this as it will be a mayor performance hit
48 | mutex.lock();
49 | auto observers = GetInstance().observers; // obtain a copy of all the observers since the callbacks may modify the vector
50 | mutex.unlock();
51 | BOOL discard = false;
52 | S4GuiClearParams params;
53 | GUIContainer *c = (GUIContainer*)surfaceContainer;
54 | params.surfaceWidth = c->width;
55 | params.surfaceHeight = c->height;
56 | params.x = c->x;
57 | params.y = c->y;
58 | params.surfaceId = c->type;
59 |
60 | // iterate observers
61 | for (auto& observer : observers) {
62 | discard |= ((LPS4GUICLEARCALLBACK)observer.callback)(¶ms, discard);
63 | }
64 |
65 | return;
66 | }
67 | #pragma optimize("", on)
68 |
69 | static void __declspec(naked) __onHook() {
70 | __asm {
71 | call Orig
72 |
73 |
74 | push esi
75 | call CGuiClearHook::OnClear // we call your stdcall hook procedure, this is allowed to change eax, ecx and edx as well as the xmm / fpu registers
76 |
77 |
78 | jmp backJmp
79 | }
80 | }
81 |
82 | CGuiClearHook& CGuiClearHook::GetInstance() {
83 | static CGuiClearHook inst;
84 | return inst;
85 | }
86 |
87 | bool CGuiClearHook::Init() {
88 | TRACE;
89 |
90 | const DWORD addr = S4_Main != 0 ? S4_Main + 0x0027227F : 0;
91 | if (!addr) return false;
92 | Orig = S4_Main + 0x25F000;
93 | backJmp = S4_Main + 0x00272284;
94 | OnClearHook = hlib::JmpPatch(addr, (DWORD)__onHook);
95 |
96 | return true;
97 | }
98 |
99 | void CGuiClearHook::Patch() {
100 | TRACE;
101 | OnClearHook.patch();
102 | }
103 |
104 | void CGuiClearHook::Unpatch() {
105 | TRACE;
106 | OnClearHook.unpatch();
107 | }
108 |
109 | CGuiClearHook::CGuiClearHook() { TRACE; }
110 |
--------------------------------------------------------------------------------
/S4ModApi/CGuiClearHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CGuiClearHook : public CHook {
27 | public:
28 | static CGuiClearHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CGuiClearHook();
37 | static void __stdcall OnClear(DWORD *container);
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CGuiElementBltHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CGuiElementBltHook : public CHook {
27 | public:
28 | static CGuiElementBltHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CGuiElementBltHook();
37 | static BOOL __stdcall OnElementBlt(DWORD _0, DWORD _1, DWORD, DWORD _2, DWORD _3, DWORD _4);
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CHook.h"
23 | #include "Console.h"
24 | #include
25 | #include "module.h"
26 |
27 | void CHook::InitAll() {
28 | TRACE;
29 | const std::lock_guard lock(mutex);
30 | for (auto& inst : instances) inst->Setup();
31 | }
32 |
33 | HRESULT CHook::RemoveListener(S4HOOK hook) {
34 | TRACE;
35 | if (hook != 0) {
36 | const std::lock_guard lock(mutex);
37 | for (auto& inst : instances) {
38 | auto& observers = inst->observers;
39 | for (auto it = observers.rbegin(); it != observers.rend(); ++it) {
40 | if (it->id == hook) {
41 | DecreaseModuleRefcount(it->mod);
42 | observers.erase((++it).base());
43 | if (hook < lowestFreeId) lowestFreeId = hook;
44 | if (observers.empty()) {
45 | inst->Uninstall();
46 | }
47 | LOG("remove listener " << dec << hook << " with S_OK");
48 | return S_OK;
49 | }
50 | }
51 | }
52 | }
53 |
54 | LOG("error: remove listener " << dec << hook << " returns with E_HANDLE");
55 | return E_HANDLE;
56 | }
57 |
58 | S4HOOK CHook::FindFreeObserverId() {
59 | TRACE;
60 | std::vector usedS4HookIDsVec; // bit (!) vector that tracks used IDs
61 | // build bit vector
62 | for (auto& inst : instances) {
63 | for (auto& observer : inst->observers) {
64 | if (observer.id >= usedS4HookIDsVec.size())
65 | usedS4HookIDsVec.resize(observer.id);
66 | usedS4HookIDsVec[observer.id - 1] = true;
67 | }
68 | }
69 |
70 | // find first bit that is 0
71 | auto sz = usedS4HookIDsVec.size();
72 | for (UINT32 i = 0; i < sz; i++) {
73 | if (!usedS4HookIDsVec[i])
74 | return i + 1;
75 | }
76 | return sz + 1;
77 | }
78 |
79 | S4HOOK CHook::AddListener(LPCVOID lpCallback, DWORD dwParam, INT iPriority) {
80 | TRACE;
81 | if (lpCallback == NULL) {
82 | LOG("error: lpCallback is NULL");
83 | return 0;
84 | }
85 | auto mod = IncreaseModuleRefcount(lpCallback);
86 | if (!mod) {
87 | LOG("error: cannot lock code of callback in memory");
88 | return 0; // already unloaded?
89 | }
90 | const std::lock_guard lock(mutex);
91 | Install();
92 | auto hookId = FindFreeObserverId();
93 | ObserverEntry entry(lpCallback, hookId, dwParam, iPriority, mod);
94 | // insert listener according to priority (keeps vector sorted by priority)
95 | observers.insert(
96 | std::upper_bound(
97 | observers.begin(),
98 | observers.end(),
99 | entry,
100 | [](const ObserverEntry& a, const ObserverEntry& b) { return a.priority < b.priority; }),
101 | entry);
102 | LOG("inserted callback " << HEXNUM(lpCallback) << dec << " with param " << dec << dwParam << " in module " << HEXNUM(mod) << ". S4HOOK == " << dec << hookId);
103 | return hookId;
104 | }
105 |
106 | CHook::CHook() {
107 | TRACE;
108 | const std::lock_guard lock(mutex);
109 | instances.push_back(this);
110 | }
111 |
112 | CHook::~CHook() {
113 | TRACE;
114 | const std::lock_guard lock(mutex);
115 | auto it = std::find(instances.rbegin(), instances.rend(), this);
116 | if (it != instances.rend()) {
117 | instances.erase((++it).base());
118 | }
119 | }
120 |
121 | void CHook::Setup() {
122 | TRACE;
123 | if (m_bIsInitialized) return;
124 | m_bIsInitialized = Init();
125 | if (!m_bIsInitialized) return;
126 |
127 | if (m_bWantInstalled) Install();
128 | }
129 |
130 | void CHook::Install() {
131 | TRACE;
132 | if (m_bIsInstalled) return;
133 | m_bWantInstalled = true;
134 | if (!m_bIsInitialized) { // not initialized
135 | Setup(); // try initialize
136 | if (!m_bIsInitialized) return; // still not initialized
137 | }
138 | m_bIsInstalled = true;
139 |
140 | Patch();
141 | }
142 |
143 | void CHook::Uninstall() {
144 | TRACE;
145 | if (!m_bIsInstalled) return;
146 | m_bWantInstalled = false;
147 | m_bIsInstalled = false;
148 |
149 | Unpatch();
150 | }
151 |
152 | std::vector CHook::instances;
153 |
154 | std::recursive_mutex CHook::mutex;
155 | S4HOOK CHook::lowestFreeId = 1;
156 |
157 | CHook::ObserverEntry::ObserverEntry(LPCVOID callback, S4HOOK id, DWORD param, INT priority, HMODULE mod) :
158 | callback(callback),id(id),param(param), priority(priority), mod(mod) {
159 | TRACE;
160 | }
161 |
--------------------------------------------------------------------------------
/S4ModApi/CHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 | #include "S4ModApi.h"
24 | #include
25 | #include
26 | #include "Log.h"
27 |
28 | class CHook {
29 | public:
30 | void Setup(); // processes the addresses from the pattern scanner
31 | void Install(); // installs the hook
32 | void Uninstall(); // uninstalls the hook
33 |
34 | S4HOOK AddListener(LPCVOID,DWORD=0,INT=0); // register an observer
35 | static HRESULT RemoveListener(S4HOOK); // remove an observer
36 | static void InitAll(); // initialize all instantiated hooks
37 |
38 | protected:
39 | virtual bool Init() = 0; // computes target addresses based on the patterns
40 | virtual void Patch() = 0; // installs the patches/detours
41 | virtual void Unpatch() = 0; // uninstalls the patches/detours
42 |
43 | CHook();
44 | ~CHook();
45 | CHook(const CHook&) = delete;
46 | CHook& operator=(CHook const&) = delete;
47 |
48 | /** struct used for mapping S4HOOK to callback function **/
49 | struct ObserverEntry {
50 | LPCVOID callback;
51 | S4HOOK id;
52 | DWORD param;
53 | INT priority;
54 | HMODULE mod;
55 |
56 | ObserverEntry() = delete;
57 | ObserverEntry(LPCVOID callback, S4HOOK id, DWORD param, INT priority, HMODULE mod);
58 | };
59 | std::vector observers;
60 | static std::recursive_mutex mutex;
61 |
62 | private:
63 | /** all instances of the hooks **/
64 | static std::vector instances;
65 |
66 | static S4HOOK lowestFreeId;
67 |
68 | static S4HOOK FindFreeObserverId(); // get a free id for an observer
69 |
70 | unsigned char m_bIsInstalled : 1;
71 | unsigned char m_bIsInitialized : 1;
72 | unsigned char m_bWantInstalled : 1;
73 | };
74 |
--------------------------------------------------------------------------------
/S4ModApi/CLuaOpenHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // JmpPatch
24 | #include "patterns.h"
25 | #include "safemem.h"
26 |
27 | #include "CLuaOpenHook.h"
28 |
29 | static hlib::JmpPatch OnLuaOpenHook;
30 | static DWORD backjmp, origjmp;
31 |
32 | DWORD __stdcall CLuaOpenHook::OnLuaOpen() {
33 | TRACE;
34 | mutex.lock();
35 | auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
36 | mutex.unlock();
37 | for (auto& observer : observers) {
38 | ((LPS4LUAOPENCALLBACK)observer.callback)();
39 | }
40 | return 0;
41 | }
42 |
43 | static void __declspec(naked) __onLuaOpenHE() {
44 | __asm {
45 | call origjmp
46 | call CLuaOpenHook::OnLuaOpen
47 | jmp backjmp
48 | }
49 | }
50 |
51 | CLuaOpenHook& CLuaOpenHook::GetInstance() {
52 | static CLuaOpenHook inst;
53 | return inst;
54 | }
55 |
56 | bool CLuaOpenHook::Init() {
57 | TRACE;
58 | if (!g_Patterns.OnLuaOpenHook) return false;
59 |
60 | DWORD addr = g_Patterns.OnLuaOpenHook;
61 | if (!addr) return false;
62 | addr += 30;
63 | DWORD off = READ_AT((LPCVOID)addr, 1);
64 | if (!off) return false;
65 | origjmp = addr + off + 5;
66 | backjmp = addr + 5;
67 | OnLuaOpenHook = hlib::JmpPatch(addr, (DWORD)(__onLuaOpenHE));
68 |
69 | return true;
70 | }
71 |
72 | void CLuaOpenHook::Patch() {
73 | TRACE;
74 | OnLuaOpenHook.patch();
75 | }
76 |
77 | void CLuaOpenHook::Unpatch() {
78 | TRACE;
79 | OnLuaOpenHook.unpatch();
80 | }
81 |
82 | CLuaOpenHook::CLuaOpenHook() { TRACE; }
83 |
--------------------------------------------------------------------------------
/S4ModApi/CLuaOpenHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CLuaOpenHook : public CHook {
27 | public:
28 | static CLuaOpenHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CLuaOpenHook();
37 | static DWORD __stdcall OnLuaOpen();
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CMapInitHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // JmpPatch
24 | #include "patterns.h"
25 |
26 | #include "CMapInitHook.h"
27 |
28 | static hlib::JmpPatch OnMapInitHook;
29 | static DWORD backjmp;
30 |
31 | DWORD __stdcall CMapInitHook::OnMapInit() {
32 | TRACE;
33 | mutex.lock();
34 | auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
35 | mutex.unlock();
36 | for (auto& observer : observers) {
37 | ((LPS4MAPINITCALLBACK)observer.callback)(0, 0);
38 | }
39 | return 0;
40 | }
41 |
42 | static void __declspec(naked) __onMapInitHE() {
43 | __asm {
44 | push ecx
45 | push edx
46 |
47 | call CMapInitHook::OnMapInit
48 |
49 | // the stuff we replaced
50 | lea ecx, [esi + 0x5c]
51 |
52 | mov eax, backjmp
53 | jmp eax
54 | }
55 | }
56 |
57 | static void __declspec(naked) __onMapInitGE() {
58 | __asm {
59 | // the stuff we replaced
60 | not ecx
61 | dec ecx
62 | mov edi, ecx
63 |
64 | call CMapInitHook::OnMapInit
65 |
66 | mov eax, backjmp
67 | jmp backjmp
68 | }
69 | }
70 |
71 | CMapInitHook& CMapInitHook::GetInstance() {
72 | static CMapInitHook inst;
73 | return inst;
74 | }
75 |
76 | bool CMapInitHook::Init() {
77 | TRACE;
78 | if (!g_Patterns.OnMapInitHook) return false;
79 |
80 | DWORD addr = g_Patterns.OnMapInitHook;
81 | OnMapInitHook = hlib::JmpPatch(addr, (DWORD)(g_isGE ? __onMapInitGE : __onMapInitHE));
82 | backjmp = addr + 5;
83 |
84 | return true;
85 | }
86 |
87 | void CMapInitHook::Patch() {
88 | TRACE;
89 | OnMapInitHook.patch();
90 | }
91 |
92 | void CMapInitHook::Unpatch() {
93 | TRACE;
94 | OnMapInitHook.unpatch();
95 | }
96 |
97 | CMapInitHook::CMapInitHook() { TRACE; }
98 |
--------------------------------------------------------------------------------
/S4ModApi/CMapInitHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CMapInitHook : public CHook {
27 | public:
28 | static CMapInitHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CMapInitHook();
37 | static DWORD __stdcall OnMapInit();
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CMessageBox.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "windows.h"
25 | #include
26 | #include
27 | #include
28 | #include "S4ModApi.h"
29 | #include "CDialog.h"
30 |
31 | class CMessageBox;
32 |
33 | typedef HRESULT(FAR S4HCALL* LPMESSAGEBOXHANDLER)(CMessageBox* messagebox, INT reason);
34 |
35 | class CMessageBox : public CDialog {
36 | public:
37 | enum HideReasonEnum : DWORD {
38 | CMessageBox_HideReason_Default, // default state, window is hidden per default
39 | CMessageBox_HideReason_NotHidden, // the window is not hidden (is visible)
40 | CMessageBox_HideReason_Method, // hide() method was called by user
41 | CMessageBox_HideReason_OkButton, // ok button was used
42 | CMessageBox_HideReason_CloseButton, // close button was used
43 | };
44 |
45 | CMessageBox(LPCWSTR title, LPCWSTR message, INT x, INT y, INT w, INT h, DWORD flags = 0);
46 |
47 | HideReasonEnum GetHideReason();
48 | void SetHandler(LPMESSAGEBOXHANDLER);
49 |
50 | protected:
51 | virtual BOOL OnDraw(HDC hdc, const POINT *cursor, const RECT* client) override;
52 | virtual BOOL OnMouse(DWORD dwMouseButton, INT iX, INT iY, DWORD dwMsgId, HWND hwnd) override;
53 | virtual BOOL OnShow() override; // do not call Hide() from here (will deadlock)
54 | virtual BOOL OnHide() override; // do not call Show() from here (will deadlock)
55 |
56 | private:
57 | CMessageBox(const CMessageBox&) = delete;
58 | CMessageBox& operator=(CMessageBox const&) = delete;
59 |
60 | std::wstring m_title, m_message;
61 | RECT m_closeButton, m_okButton, m_windowRect;
62 | HideReasonEnum m_hideReason;
63 | volatile LPMESSAGEBOXHANDLER m_handler;
64 | };
65 |
--------------------------------------------------------------------------------
/S4ModApi/CMod.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CMod.h"
23 | #include "Console.h"
24 | #include
25 | #include "module.h"
26 |
27 | void CMod::InitAll() {
28 | TRACE;
29 | const std::lock_guard lock(mutex);
30 | for (auto& inst : instances) inst->Setup();
31 | }
32 |
33 | CMod::CMod() {
34 | TRACE;
35 | const std::lock_guard lock(mutex);
36 | instances.push_back(this);
37 | }
38 |
39 | CMod::~CMod() {
40 | TRACE;
41 | const std::lock_guard lock(mutex);
42 | auto it = std::find(instances.rbegin(), instances.rend(), this);
43 | if (it != instances.rend()) {
44 | instances.erase((++it).base());
45 | }
46 | }
47 |
48 | void CMod::Setup() {
49 | TRACE;
50 | const std::lock_guard lock(mutex);
51 | if (m_bIsInitialized) return;
52 | m_bIsInitialized = Init();
53 | if (!m_bIsInitialized) return;
54 |
55 | if (m_bWantInstalled) Install();
56 | }
57 |
58 | void CMod::Install() {
59 | TRACE;
60 | const std::lock_guard lock(mutex);
61 | if (m_bIsInstalled) return;
62 | m_bWantInstalled = true;
63 | if (!m_bIsInitialized) { // not initialized
64 | Setup(); // try initialize
65 | if (!m_bIsInitialized) return; // still not initialized
66 | }
67 | m_bIsInstalled = true;
68 |
69 | Patch();
70 | }
71 |
72 | void CMod::Uninstall() {
73 | TRACE;
74 | const std::lock_guard lock(mutex);
75 | if (!m_bIsInstalled) return;
76 | m_bWantInstalled = false;
77 | m_bIsInstalled = false;
78 |
79 | Unpatch();
80 | }
81 |
82 | bool CMod::IsInstalled() {
83 | return m_bIsInstalled;
84 | }
85 |
86 | bool CMod::IsEnabled() {
87 | return m_bWantInstalled || m_bIsInstalled;
88 | }
89 |
90 | std::vector CMod::instances;
91 | std::recursive_mutex CMod::mutex;
92 |
93 |
--------------------------------------------------------------------------------
/S4ModApi/CMod.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 | #include "S4ModApi.h"
24 | #include
25 | #include
26 | #include "Log.h"
27 |
28 | ///
29 | /// Mods are modifications to the game that require patterns or other initialization
30 | /// to be already performed. Mods may be activated but not installed. When initialization
31 | /// is completed all activated mods will be installed.
32 | ///
33 | /// CMod serves as a base class for mods.
34 | ///
35 | class CMod {
36 | public:
37 | void Setup(); // processes the addresses from the pattern scanner
38 | void Install(); // installs the mod
39 | void Uninstall(); // uninstalls the mod
40 |
41 | bool IsInstalled(); // mod is enabled and installed
42 | bool IsEnabled(); // mod is enabled but not yet installed
43 |
44 | static void InitAll(); // initialize all activated mods
45 |
46 | protected:
47 | virtual bool Init() = 0; // computes target addresses based on the patterns
48 | virtual void Patch() = 0; // installs the patches/detours
49 | virtual void Unpatch() = 0; // uninstalls the patches/detours
50 |
51 | CMod();
52 | ~CMod();
53 | CMod(const CMod&) = delete;
54 | CMod& operator=(CMod const&) = delete;
55 |
56 | static std::recursive_mutex mutex;
57 |
58 | private:
59 | /** all instances of the mods that have been constructed **/
60 | static std::vector instances;
61 |
62 | unsigned char m_bIsInstalled : 1;
63 | unsigned char m_bIsInitialized : 1;
64 | unsigned char m_bWantInstalled : 1;
65 | };
66 |
--------------------------------------------------------------------------------
/S4ModApi/CMouseHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // CallPatch
24 | #include // GET_X_LPARAM, GET_Y_LPARAM
25 | #include "s4.h"
26 | #include "patterns.h"
27 | #include "CMouseHook.h"
28 | #include "CSettlers4Api.h"
29 |
30 | static hlib::CallPatch OnMouseButtonHook, OnMouseWheelHookHE;
31 |
32 | bool __stdcall CMouseHook::OnMouse(HWND hwnd, DWORD msg, DWORD wparam, DWORD lparam) {
33 | TRACE;
34 | S4UiElement uiElement;
35 | LPCS4UIELEMENT lpUiElement =
36 | CSettlers4Api::GetInstance().GetHoveringUiElement(&uiElement) == 0 ? &uiElement : NULL;
37 | mutex.lock();
38 | auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
39 | mutex.unlock();
40 | for (auto& observer : observers) {
41 | if (0 != ((LPS4MOUSECALLBACK)observer.callback)(wparam, (INT16)(GET_X_LPARAM(lparam)), (INT16)(GET_Y_LPARAM(lparam)), msg, hwnd, lpUiElement))
42 | return true;
43 | }
44 | return false;
45 | }
46 |
47 | static void __declspec(naked) __onMouseHE() {
48 | __asm {
49 | push eax
50 | push ecx
51 | push edx
52 |
53 | //push edi
54 |
55 | push[ebp - 0x04] // lparam
56 | push[ebp - 0x08] // wparam
57 | push[ebp - 0x0C] // msg
58 | push[ebp + 0x08] // hwnd
59 | call CMouseHook::OnMouse
60 |
61 | pop edx
62 | pop ecx
63 | test al, al
64 | pop eax
65 | jnz cancelEvent
66 |
67 | test eax, 0x08000000
68 | //mov ecx, [ebp - 4] // the opcodes we replaced
69 | //xor ecx, ebp
70 |
71 | ret
72 |
73 | cancelEvent :
74 | //cancel the event
75 | pop eax // remove the return address from stack
76 | pop edi
77 | pop esi
78 | pop ebx
79 | xor eax, eax
80 | mov esp, ebp
81 | pop ebp
82 | ret 16
83 | }
84 | }
85 |
86 | static void __declspec(naked) __onMouseGE() {
87 | __asm {
88 | push eax
89 | push edx
90 |
91 | push[esp + 0x2C] // lparam
92 | push[esp + 0x1C + 4] // wparam
93 | push[esp + 0x0C + 8] // msg
94 | push[esp + 0x28 + 12] // hwnd
95 | call CMouseHook::OnMouse
96 |
97 | pop edx
98 | test al, al
99 | pop eax
100 | jnz cancelEvent
101 |
102 | test eax, 0x08000000 // the opcode we replaced
103 |
104 | ret
105 |
106 | cancelEvent :
107 | pop eax // pop return address
108 | xor eax, eax
109 | pop edi
110 | pop esi
111 | pop ebp
112 | pop ebx
113 | pop ecx
114 | pop ecx
115 | ret 16
116 | }
117 | }
118 |
119 | CMouseHook& CMouseHook::GetInstance() {
120 | static CMouseHook inst;
121 | return inst;
122 | }
123 |
124 | bool CMouseHook::Init() {
125 | TRACE;
126 | if (!g_Patterns.OnMouseButtonHook) return false;
127 |
128 | DWORD addr = g_Patterns.OnMouseButtonHook + (g_isGE ? 19 : 20);
129 | DWORD addr2 = g_Patterns.OnMouseButtonHook + 68;
130 | OnMouseButtonHook = hlib::CallPatch(addr, (DWORD)(g_isGE ? __onMouseGE : __onMouseHE));
131 | OnMouseWheelHookHE = hlib::CallPatch(addr2, (DWORD)__onMouseHE); // this is not required for the GE as the original hook already catches that too.
132 |
133 | return true;
134 | }
135 |
136 | void CMouseHook::Patch() {
137 | TRACE;
138 | OnMouseButtonHook.patch();
139 | OnMouseWheelHookHE.patch();
140 | }
141 |
142 | void CMouseHook::Unpatch() {
143 | TRACE;
144 | OnMouseButtonHook.unpatch();
145 | OnMouseWheelHookHE.unpatch();
146 | }
147 |
148 | CMouseHook::CMouseHook() { TRACE; }
149 |
--------------------------------------------------------------------------------
/S4ModApi/CMouseHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CMouseHook : public CHook {
27 | public:
28 | static CMouseHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CMouseHook();
37 | static bool __stdcall OnMouse(HWND hwnd, DWORD msg, DWORD wparam, DWORD lparam);
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Casting.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "patterns.h"
24 | #include "globals.h"
25 | #include "safemem.h"
26 | #include "s4.h"
27 |
28 | BOOL CSettlers4Api::CastSpell(DWORD priest, DWORD spell, INT x, INT y, DWORD player) {
29 | TRACE;
30 |
31 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
32 | if (!vtbl) return FALSE;
33 |
34 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
35 | if (!localPlayer) return FALSE;
36 |
37 | #pragma pack(push, 1)
38 | static union {
39 | struct EventStruct_t {
40 | /*00*/DWORD CEvn_Logic_vtbl; // vtable
41 | /*04*/DWORD eventId; // 0x13B8
42 | /*08*/WORD spell;
43 | /*0A*/WORD priest;
44 | /*0C*/WORD x;
45 | /*0E*/WORD y;
46 | /*10*/DWORD tick; //
47 | /*14*/BYTE flags; // always 0 ?
48 | /*16*/BYTE __pad[3]; // ignored
49 | /*18*/DWORD settlersArray; // must be 0
50 | /*1C*/WORD sizeofArray; // always 0
51 | /*1E*/BYTE player; //
52 | } eventStruct;
53 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
54 | } u1;
55 | #pragma pack(pop)
56 |
57 | ZeroMemory(&u1, sizeof(u1));
58 |
59 | u1.eventStruct.CEvn_Logic_vtbl = vtbl;
60 | u1.eventStruct.eventId = 0x13B8;
61 | u1.eventStruct.spell = (WORD)spell;
62 | u1.eventStruct.priest = (WORD)priest;
63 | u1.eventStruct.x = (WORD)x;
64 | u1.eventStruct.y = (WORD)y;
65 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
66 | u1.eventStruct.player = (BYTE)localPlayer;
67 |
68 | return S4::GetInstance().SendNetEvent(&u1);
69 | }
70 |
--------------------------------------------------------------------------------
/S4ModApi/CS4CustomUi.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "CMessageBox.h"
24 | #include "CCustomUi.h"
25 |
26 | static HRESULT S4HCALL OnMessageBoxHide(CMessageBox* messagebox, INT reason) {
27 | UNREFERENCED_PARAMETER(reason);
28 | delete messagebox;
29 | return 0;
30 | }
31 |
32 | S4CUSTOMUI CSettlers4Api::ShowMessageBox(LPCWSTR title, LPCWSTR message, INT x, INT y, INT w, INT h, DWORD flags) {
33 | TRACE;
34 | auto mb = new CMessageBox(title,message,x,y,w,h,flags);
35 | mb->SetHandler(OnMessageBoxHide);
36 | mb->Show();
37 | return mb;
38 | }
39 |
40 | S4CUSTOMUI CSettlers4Api::CreateCustomUiElement(LPCS4CUSTOMUIELEMENT arg) {
41 | TRACE;
42 | if (arg && arg->size == sizeof(*arg)) {
43 | auto cui = new CCustomUi(arg);
44 | cui->Show();
45 | return cui;
46 | }
47 | return NULL;
48 | }
49 |
50 | BOOL CSettlers4Api::DestroyCustomUiElement(S4CUSTOMUI arg) {
51 | TRACE;
52 | return HideCustomUiElement(arg); // TODO: calling delete may be harmful when calling from a S4UiCallbackProc
53 | //if (arg) {
54 | // delete arg;
55 | //}
56 | return NULL;
57 | }
58 |
59 | BOOL CSettlers4Api::HideCustomUiElement(S4CUSTOMUI arg) {
60 | TRACE;
61 | if (arg) {
62 | auto diag = (CDialog*)arg;
63 | diag->Hide();
64 | return TRUE;
65 | } else {
66 | return FALSE;
67 | }
68 | }
69 |
70 | BOOL CSettlers4Api::ShowCustomUiElement(S4CUSTOMUI arg) {
71 | TRACE;
72 | if (arg) {
73 | auto diag = (CDialog*)arg;
74 | diag->Show();
75 | return TRUE;
76 | } else {
77 | return FALSE;
78 | }
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Debug.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 |
24 | LPVOID CSettlers4Api::GetDebugData(LPVOID reserved0, LPVOID reserved1) {
25 | TRACE;
26 | UNREFERENCED_PARAMETER(reserved0);
27 | UNREFERENCED_PARAMETER(reserved1);
28 |
29 | return (LPVOID)m_refs;
30 | }
31 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Error.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 |
24 | DWORD CSettlers4Api::GetLastError() {
25 | TRACE;
26 | return 0;
27 | }
28 |
--------------------------------------------------------------------------------
/S4ModApi/CS4GarrisonWarriors.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "patterns.h"
24 | #include "globals.h"
25 | #include "safemem.h"
26 | #include "s4.h"
27 | #include "hlib.h"
28 |
29 | BOOL CSettlers4Api::GarrisonWarriors(DWORD building, DWORD player) {
30 | TRACE;
31 |
32 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
33 | if (!vtbl) return FALSE;
34 |
35 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
36 | if (!localPlayer) return FALSE;
37 |
38 | #pragma pack(push, 1)
39 | static union {
40 | struct EventStruct_t {
41 | /*00*/DWORD CEvn_Logic_vtbl; // [2C] vtable
42 | /*04*/DWORD eventId; // [28] 0x13A7
43 | /*08*/DWORD buildingIndex; // [24]
44 | /*0C*/INT32 amount; // [20] Must be -1. Other values have no effect?
45 | /*10*/DWORD tick; // [1C]
46 | /*14*/BYTE flags; // [18] always 0x00 ?
47 | /*16*/BYTE __pad[3]; // [17] ignored
48 | /*18*/DWORD settlersArray; // [14] must be 0
49 | /*1C*/WORD sizeofArray; // [10] always 0
50 | /*1E*/BYTE player; // [E]
51 | } eventStruct;
52 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
53 | } u1;
54 | #pragma pack(pop)
55 |
56 | ZeroMemory(&u1, sizeof(u1));
57 | u1.eventStruct.CEvn_Logic_vtbl = vtbl;
58 | u1.eventStruct.eventId = 0x13A7; // garrison event
59 | u1.eventStruct.buildingIndex = building;
60 | u1.eventStruct.amount = -1;
61 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
62 | u1.eventStruct.player = (BYTE)localPlayer;
63 |
64 | return S4::GetInstance().SendNetEvent(&u1);
65 | }
66 |
67 | BOOL CSettlers4Api::UnGarrisonWarriors(DWORD building, INT column, BOOL bowman, DWORD player) {
68 | TRACE;
69 |
70 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
71 | if (!vtbl) return FALSE;
72 |
73 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
74 | if (!localPlayer) return FALSE;
75 |
76 | #pragma pack(push, 1)
77 | static union {
78 | struct EventStruct_t {
79 | /*00*/DWORD CEvn_Logic_vtbl; // [2C] vtable
80 | /*04*/DWORD eventId; // [28] 0x13A8
81 | /*08*/WORD type;// 0==swordmen, 1==bowmen
82 | /*0A*/WORD buildingIndex; //
83 | /*0C*/INT32 unit; // index of the unit in the building to remove. Is in range 0..5. Use -1 to remove em all.
84 | /*10*/DWORD tick; // [1C]
85 | /*14*/BYTE flags; // [18] always 0x0f00 ?
86 | /*16*/BYTE __pad[3]; // [17] ignored
87 | /*18*/DWORD settlersArray; // [14] must be 0
88 | /*1C*/WORD sizeofArray; // [10] always 0
89 | /*1E*/BYTE player; // [E]
90 | } eventStruct;
91 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
92 | } u1;
93 | #pragma pack(pop)
94 |
95 | ZeroMemory(&u1, sizeof(u1));
96 | u1.eventStruct.CEvn_Logic_vtbl = vtbl;
97 | u1.eventStruct.eventId = 0x13A8; // ungarrison event
98 | u1.eventStruct.type = (WORD)bowman;
99 | u1.eventStruct.buildingIndex = (WORD)building;
100 | u1.eventStruct.unit = column;
101 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
102 | u1.eventStruct.player = (BYTE)localPlayer;
103 |
104 | return S4::GetInstance().SendNetEvent(&u1);
105 | }
106 |
107 |
108 |
--------------------------------------------------------------------------------
/S4ModApi/CS4GoodDistribution.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "patterns.h"
24 | #include "globals.h"
25 | #include "safemem.h"
26 | #include "s4.h"
27 |
28 | BOOL CSettlers4Api::ChangeGoodDistribution(S4_GOOD_ENUM good, S4_BUILDING_ENUM building, INT percent, DWORD ecosector, DWORD player) {
29 | TRACE;
30 |
31 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
32 | if (!vtbl) return FALSE;
33 |
34 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
35 | if (!localPlayer) return FALSE;
36 |
37 | #pragma pack(push, 1)
38 | static union {
39 | struct EventStruct_t {
40 | /*00*/DWORD CEvn_Logic_vtbl; // vtable
41 | /*04*/DWORD eventId;
42 | /*08*/WORD building;
43 | /*0A*/WORD good;
44 | /*0C*/INT16 change;
45 | /*0E*/WORD ecosector;
46 | /*10*/DWORD tick; //
47 | /*14*/BYTE flags; // always 0 ?
48 | /*16*/BYTE __pad[3]; // ignored
49 | /*18*/DWORD settlersArray; // must be 0
50 | /*1C*/WORD sizeofArray; // always 0
51 | /*1E*/BYTE player; //
52 | } eventStruct;
53 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
54 | } u1;
55 | #pragma pack(pop)
56 |
57 | ZeroMemory(&u1, sizeof(u1));
58 |
59 | u1.eventStruct.CEvn_Logic_vtbl = vtbl; // 00E4BA08
60 | u1.eventStruct.eventId = 0x13A4;
61 | u1.eventStruct.good = (WORD)(good);
62 | u1.eventStruct.building = (WORD)(building);
63 | u1.eventStruct.change = (INT16)percent;
64 | u1.eventStruct.ecosector = (WORD)ecosector;
65 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
66 | u1.eventStruct.player = (BYTE)localPlayer;
67 |
68 | return S4::GetInstance().SendNetEvent(&u1);
69 | }
70 |
71 | // positive offset means lower priority, negative offset means higher priority
72 | BOOL CSettlers4Api::ChangeGoodPriority(S4_GOOD_ENUM good, INT offset, DWORD ecosector, DWORD player) {
73 | TRACE;
74 |
75 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
76 | if (!vtbl) return FALSE;
77 |
78 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
79 | if (!localPlayer) return FALSE;
80 |
81 | #pragma pack(push, 1)
82 | static union {
83 | struct EventStruct_t {
84 | /*00*/DWORD CEvn_Logic_vtbl; // vtable
85 | /*04*/DWORD eventId;
86 | /*08*/INT16 offset;
87 | /*0A*/WORD good;
88 | /*0C*/DWORD ecosector;
89 | /*10*/DWORD tick; //
90 | /*14*/BYTE flags; // always 0 ?
91 | /*16*/BYTE __pad[3]; // ignored
92 | /*18*/DWORD settlersArray; // must be 0
93 | /*1C*/WORD sizeofArray; // always 0
94 | /*1E*/BYTE player; //
95 | } eventStruct;
96 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
97 | } u1;
98 | #pragma pack(pop)
99 |
100 | ZeroMemory(&u1, sizeof(u1));
101 |
102 | u1.eventStruct.CEvn_Logic_vtbl = vtbl; // 00E4BA08
103 | u1.eventStruct.eventId = 0x13A5;
104 | u1.eventStruct.good = (WORD)(good);
105 | u1.eventStruct.offset = (INT16)offset;
106 | u1.eventStruct.ecosector = ecosector;
107 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
108 | u1.eventStruct.player = (BYTE)localPlayer;
109 |
110 | return S4::GetInstance().SendNetEvent(&u1);
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Landscape.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "patterns.h"
24 | #include "s4.h"
25 | #include "safemem.h"
26 | #include "globals.h"
27 |
28 | DWORD CSettlers4Api::LandscapeGetHeight(INT x, INT y) {
29 | TRACE;
30 | auto landscape = S4::GetInstance().GetLandscapeAt((WORD)x, (WORD)y);
31 | if (landscape) return landscape->GetTerrainHeight();
32 | return 0;
33 | }
34 |
35 | S4_GROUND_ENUM CSettlers4Api::LandscapeGetType(INT x, INT y) {
36 | TRACE;
37 | auto landscape = S4::GetInstance().GetLandscapeAt((WORD)x, (WORD)y);
38 | if (landscape) return landscape->GetTerrainType();
39 | return S4_GROUND_ENUM::WATER8;
40 | }
41 |
42 | BOOL CSettlers4Api::LandscapeIsPond(INT x, INT y) {
43 | TRACE;
44 | auto landscape = S4::GetInstance().GetLandscapeAt((WORD)x, (WORD)y);
45 | if (landscape) return landscape->IsPondBrush();
46 | return FALSE;
47 | }
48 |
49 | BOOL CSettlers4Api::LandscapeIsDarkLand(INT x, INT y) {
50 | TRACE;
51 | auto landscape = S4::GetInstance().GetLandscapeAt((WORD)x, (WORD)y);
52 | if (landscape) return landscape->IsDarkLand();
53 | return FALSE;
54 | }
55 |
56 | BOOL CSettlers4Api::LandscapeIsDarkLandBorder(INT x, INT y) {
57 | TRACE;
58 | auto landscape = S4::GetInstance().GetLandscapeAt((WORD)x, (WORD)y);
59 | if (landscape) return landscape->IsDarkBorder();
60 | return FALSE;
61 | }
62 |
63 | DWORD CSettlers4Api::LandscapeGetFogOfWar(INT x, INT y) {
64 | TRACE;
65 | auto landscape = S4::GetInstance().GetLandscapeAt((WORD)x, (WORD)y);
66 | if (landscape) return landscape->GetFogOfWarLevel();
67 | return (DWORD)-1;
68 | }
69 |
70 | BOOL CSettlers4Api::LandscapeIsFoundingStone(INT x, INT y) {
71 | TRACE;
72 | auto landscape = S4::GetInstance().GetLandscapeAt((WORD)x, (WORD)y);
73 | if (landscape) return landscape->IsFoundingStone();
74 | return FALSE;
75 | }
76 |
77 | S4_RESOURCE_ENUM CSettlers4Api::LandscapeGetResource(INT x, INT y) {
78 | TRACE;
79 | return S4::GetInstance().GetResourceAt((WORD)x, (WORD)y);
80 | }
81 |
82 | BOOL CSettlers4Api::LandscapeSetResource(INT x, INT y, S4_RESOURCE_ENUM res) {
83 | TRACE;
84 | return S4::GetInstance().SetResourceAt((WORD)x, (WORD)y, res);
85 | }
86 |
87 | DWORD CSettlers4Api::LandscapeGetObject(INT x, INT y) {
88 | TRACE;
89 | return S4::GetInstance().GetEntityIdAt((WORD)x, (WORD)y);
90 | }
91 |
92 | DWORD CSettlers4Api::LandscapeGetOwner(INT x, INT y) {
93 | TRACE;
94 | return S4::GetInstance().GetOwnerAt((WORD)x, (WORD)y);
95 | }
96 |
97 | DWORD CSettlers4Api::LandscapeGetEcoSector(INT x, INT y) {
98 | TRACE;
99 | return S4::GetInstance().LandscapeGetEcoSector((WORD)x, (WORD)y);
100 | }
101 |
102 | BOOL CSettlers4Api::LandscapeIsOccupied(INT x, INT y) {
103 | TRACE;
104 | return S4::GetInstance().IsOccupied((WORD)x, (WORD)y);
105 | }
--------------------------------------------------------------------------------
/S4ModApi/CS4Listeners.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 |
24 | #include "CFrameHook.h"
25 | #include "CMapInitHook.h"
26 | #include "CMouseHook.h"
27 | #include "CSettlerSendHook.h"
28 | #include "CTickHook.h"
29 | #include "CLuaOpenHook.h"
30 | #include "CBltHook.h"
31 | #include "CEntityHook.h"
32 | #include "CGuiBltHook.h"
33 | #include "CGuiClearHook.h"
34 | #include "CGuiElementBltHook.h"
35 |
36 | extern "C" {
37 |
38 | HRESULT CSettlers4Api::RemoveListener(S4HOOK id) {
39 | TRACE;
40 | return CHook::RemoveListener(id);
41 | }
42 |
43 | S4HOOK CSettlers4Api::AddFrameListener(LPS4FRAMECALLBACK cb) {
44 | TRACE;
45 | return CFrameHook::GetInstance().AddListener(cb);
46 | }
47 |
48 | S4HOOK CSettlers4Api::AddUIFrameListener(LPS4FRAMECALLBACK cb, S4_GUI_ENUM param) {
49 | TRACE;
50 | return CFrameHook::GetInstance().AddListener(cb, param);
51 | }
52 |
53 | S4HOOK CSettlers4Api::AddMapInitListener(LPS4MAPINITCALLBACK cb) {
54 | TRACE;
55 | return CMapInitHook::GetInstance().AddListener(cb);
56 | }
57 |
58 | S4HOOK CSettlers4Api::AddMouseListener(LPS4MOUSECALLBACK cb) {
59 | TRACE;
60 | return CMouseHook::GetInstance().AddListener(cb);
61 | }
62 |
63 | S4HOOK CSettlers4Api::AddSettlerSendListener(LPS4SETTLERSENDCALLBACK cb) {
64 | TRACE;
65 | return CSettlerSendHook::GetInstance().AddListener(cb);
66 | }
67 |
68 | S4HOOK CSettlers4Api::AddTickListener(LPS4TICKCALLBACK cb) {
69 | TRACE;
70 | return CTickHook::GetInstance().AddListener(cb);
71 | }
72 |
73 | S4HOOK CSettlers4Api::AddLuaOpenListener(LPS4LUAOPENCALLBACK cb) {
74 | TRACE;
75 | return CLuaOpenHook::GetInstance().AddListener(cb);
76 | }
77 |
78 | S4HOOK CSettlers4Api::AddBltListener(LPS4BLTCALLBACK cb) {
79 | TRACE;
80 | return CBltHook::GetInstance().AddListener(cb);
81 | }
82 |
83 | S4HOOK CSettlers4Api::AddEntityListener(LPS4ENTITYCALLBACK cb) {
84 | TRACE;
85 | return CEntityHook::GetInstance().AddListener(cb);
86 | }
87 |
88 | S4HOOK CSettlers4Api::AddGuiBltListener(LPS4GUIBLTCALLBACK cb) {
89 | TRACE;
90 | return CGuiBltHook::GetInstance().AddListener(cb);
91 | }
92 |
93 | S4HOOK CSettlers4Api::AddGuiElementBltListener(LPS4GUIDRAWCALLBACK cb) {
94 | TRACE;
95 | return CGuiElementBltHook::GetInstance().AddListener(cb);
96 | }
97 |
98 | S4HOOK CSettlers4Api::AddGuiClearListener(LPS4GUICLEARCALLBACK cb) {
99 | TRACE;
100 | return CGuiClearHook::GetInstance().AddListener(cb);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/S4ModApi/CS4MenuEvents.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "s4.h"
24 |
25 |
26 | BOOL CSettlers4Api::StartBuildingPlacement(S4_BUILDING_ENUM building) {
27 | TRACE;
28 |
29 | Event_t ev(0, 0, 0, building, 0, 0x1B5);
30 | if (!ev.eventId) return FALSE;
31 |
32 | return S4::GetInstance().SendLocalEvent(ev);
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Misc.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "globals.h"
24 | #include "s4.h"
25 | #include "md5.h"
26 | #include "safemem.h"
27 |
28 | HRESULT CSettlers4Api::GetMD5OfModule(HMODULE module, LPSTR out, SIZE_T sz) {
29 | TRACE;
30 | if (!out || !sz) return ERROR_BAD_ARGUMENTS;
31 | MD5 md5;
32 | WCHAR filename[MAX_PATH + 1];
33 | auto len = GetModuleFileNameW(module, filename, MAX_PATH);
34 | if (!len) return GetLastError();
35 | filename[len] = '\0';
36 | auto res = ComputeMD5(filename, &md5);
37 | if (!res) return res;
38 | md5.ToString(out, sz); // covert to string
39 | return ERROR_SUCCESS;
40 | }
41 |
42 | BOOL CSettlers4Api::IsEdition(S4_EDITION_ENUM edition) {
43 | TRACE;
44 | switch (edition) {
45 | case S4_EDITION_GOLD: return g_isGE;
46 | case S4_EDITION_HISTORY: return !g_isGE;
47 | default: return FALSE;
48 | }
49 | }
50 |
51 | HWND CSettlers4Api::GetHwnd() {
52 | TRACE;
53 | auto& pHwnd = S4::GetInstance().Hwnd;
54 | return (HWND)READ_AT(pHwnd);
55 | }
56 |
57 | HRESULT CSettlers4Api::GetHoveringUiElement(LPS4UIELEMENT out) {
58 | TRACE;
59 | if (out) {
60 | auto& ppUi = S4::GetInstance().HoveringUiElement;
61 | UiElement_t* pUi = (UiElement_t*)READ_AT(ppUi);
62 | if (pUi) {
63 | UiElement_t ui;
64 | memget_s(&ui, pUi, sizeof ui);
65 | out->x = ui.x;
66 | out->y = ui.y;
67 | out->w = ui.w;
68 | out->h = ui.h;
69 | out->id = ui.id;
70 | out->sprite = ui.sprite;
71 | return 0;
72 | }
73 | }
74 | return -1;
75 | }
76 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Recruit.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "patterns.h"
24 | #include "globals.h"
25 | #include "safemem.h"
26 | #include "s4.h"
27 |
28 | // for some units (specialists) building is the eco sector number
29 | BOOL CSettlers4Api::RecruitWarriors(DWORD building, S4_SETTLER_ENUM unit, INT amount, DWORD player) {
30 | TRACE;
31 |
32 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
33 | if (!vtbl) return FALSE;
34 |
35 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
36 | if (!localPlayer) return FALSE;
37 |
38 | #pragma pack(push, 1)
39 | union {
40 | struct EventStruct_t {
41 | /*00*/DWORD CEvn_Logic_vtbl; // vtable
42 | /*04*/DWORD eventId; // 0x13B7
43 | /*08*/WORD unit; // 1D == swordman lv1, 1E == lv2 etc
44 | /*10*/WORD buildingIndex; //
45 | /*0C*/INT32 amount; // put 100 for infinite
46 | /*10*/DWORD tick; //
47 | /*14*/BYTE flags; // always 0xf500 ?
48 | /*16*/BYTE __pad[3]; // ignored
49 | /*18*/DWORD settlersArray; // must be 0
50 | /*1C*/WORD sizeofArray; // always 0
51 | /*1E*/BYTE player; //
52 | } eventStruct;
53 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
54 | } u1;
55 | #pragma pack(pop)
56 |
57 | ZeroMemory(&u1, sizeof(u1));
58 |
59 | switch (unit) {
60 | case S4_SETTLER_CARRIER:
61 | case S4_SETTLER_DIGGER:
62 | case S4_SETTLER_BUILDER:
63 | u1.eventStruct.eventId = 0x13A3; // civilian recruitment event
64 | u1.eventStruct.unit = (WORD)(unit);
65 | //building is the eco sector id !!!
66 | break;
67 | case S4_SETTLER_SWORDSMAN_01:
68 | case S4_SETTLER_SWORDSMAN_02:
69 | case S4_SETTLER_SWORDSMAN_03:
70 | case S4_SETTLER_BOWMAN_01:
71 | case S4_SETTLER_BOWMAN_02:
72 | case S4_SETTLER_BOWMAN_03:
73 | case S4_SETTLER_MEDIC_01:
74 | case S4_SETTLER_MEDIC_02:
75 | case S4_SETTLER_MEDIC_03:
76 | case S4_SETTLER_AXEWARRIOR_01:
77 | case S4_SETTLER_AXEWARRIOR_02:
78 | case S4_SETTLER_AXEWARRIOR_03:
79 | case S4_SETTLER_BLOWGUNWARRIOR_01:
80 | case S4_SETTLER_BLOWGUNWARRIOR_02:
81 | case S4_SETTLER_BLOWGUNWARRIOR_03:
82 | case S4_SETTLER_SQUADLEADER:
83 | case S4_SETTLER_BACKPACKCATAPULTIST_01:
84 | case S4_SETTLER_BACKPACKCATAPULTIST_02:
85 | case S4_SETTLER_BACKPACKCATAPULTIST_03:
86 | u1.eventStruct.eventId = 0x13B7; // barracks recruitment event
87 | u1.eventStruct.unit = (WORD)(unit);
88 | break;
89 | case S4_SETTLER_SABOTEUR:
90 | case S4_SETTLER_PIONEER:
91 | case S4_SETTLER_THIEF:
92 | case S4_SETTLER_GEOLOGIST:
93 | case S4_SETTLER_GARDENER:
94 | //case S4_SETTLER_LANDSCAPER:
95 | //case S4_SETTLER_DARKGARDENER:
96 | //case S4_SETTLER_SHAMAN:
97 | u1.eventStruct.eventId = 0x13AF; // specialists recruitment event
98 | u1.eventStruct.unit = (WORD)(unit);
99 | //building is the eco sector id !!!
100 | break;
101 |
102 | default: return FALSE; // currently not supported
103 | }
104 |
105 | u1.eventStruct.CEvn_Logic_vtbl = vtbl; // 00E4BA08
106 | u1.eventStruct.buildingIndex = (WORD)building;
107 | u1.eventStruct.amount = amount;
108 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
109 | u1.eventStruct.player = (BYTE)localPlayer;
110 |
111 | return S4::GetInstance().SendNetEvent(&u1);
112 | }
113 |
114 | BOOL CSettlers4Api::RecruitVehicle(DWORD building, S4_VEHICLE_ENUM unit, INT amount, DWORD player) {
115 | TRACE;
116 |
117 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
118 | if (!vtbl) return FALSE;
119 |
120 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
121 | if (!localPlayer) return FALSE;
122 |
123 | #pragma pack(push, 1)
124 | union {
125 | struct EventStruct_t {
126 | /*00*/DWORD CEvn_Logic_vtbl; // vtable
127 | /*04*/DWORD eventId; // 0x13B7
128 | /*08*/WORD unit; // 1D == swordman lv1, 1E == lv2 etc
129 | /*10*/WORD buildingIndex; //
130 | /*0C*/INT32 amount; // put 100 for infinite
131 | /*10*/DWORD tick; //
132 | /*14*/BYTE flags; // always 0xf500 ?
133 | /*16*/BYTE __pad[3]; // ignored
134 | /*18*/DWORD settlersArray; // must be 0
135 | /*1C*/WORD sizeofArray; // always 0
136 | /*1E*/BYTE player; //
137 | } eventStruct;
138 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
139 | } u1;
140 | #pragma pack(pop)
141 |
142 | ZeroMemory(&u1, sizeof(u1));
143 |
144 | switch (unit) {
145 | case S4_VEHICLE_WARSHIP:
146 | case S4_VEHICLE_FERRY:
147 | case S4_VEHICLE_TRANSPORTSHIP:
148 | case S4_VEHICLE_WARMACHINE:
149 | case S4_VEHICLE_CART:
150 | case S4_VEHICLE_FOUNDATION_CART:
151 | u1.eventStruct.eventId = 0x13B0; // vehicle recruitment event (shipyard, vehicle hall)
152 | u1.eventStruct.unit = (WORD)(unit);
153 | break;
154 |
155 | default: return FALSE; // currently not supported
156 | }
157 |
158 | u1.eventStruct.CEvn_Logic_vtbl = vtbl; // 00E4BA08
159 | u1.eventStruct.buildingIndex = (WORD)building;
160 | u1.eventStruct.amount = amount;
161 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
162 | u1.eventStruct.player = (BYTE)localPlayer;
163 |
164 | return S4::GetInstance().SendNetEvent(&u1);
165 | }
166 |
167 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Selection.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "CSettlers4Api.h"
24 | #include "hlib.h" // JmpPatch
25 | #include "patterns.h"
26 | #include "s4.h"
27 | #include "safemem.h"
28 | #include
29 | #include "CSelectionMod.h"
30 |
31 | BOOL CSettlers4Api::ClearSelection() {
32 | TRACE;
33 | typedef void(__stdcall* ClearSelection_t)();
34 | auto ClearSelection = (ClearSelection_t)g_Patterns.ClearSelection.addr;
35 | if (!ClearSelection) return FALSE;
36 | ClearSelection();
37 | return TRUE;
38 | }
39 |
40 | BOOL CSettlers4Api::GetSelection(PWORD out, SIZE_T outlen, PSIZE_T selectionCount) {
41 | TRACE;
42 | if (!out) return FALSE;
43 | auto& s = S4::GetInstance().Selection;
44 | if (!s) return FALSE;
45 | auto ct = s->count();
46 | auto elementsToCopy = min(ct, outlen);
47 | if (selectionCount) *selectionCount = ct;
48 | LOG("s->BasePtr == " << HEXNUM(s->BasePtr))
49 | if (out && elementsToCopy) memget_s(out, s->BasePtr, elementsToCopy * sizeof(*s->BasePtr));
50 | return TRUE;
51 | }
52 |
53 | BOOL CSettlers4Api::RemoveSelection(PWORD settlers, SIZE_T settlerslen, PSIZE_T removedCount) {
54 | TRACE;
55 | if (!settlers) return FALSE;
56 | if (!settlerslen) {
57 | if (removedCount) *removedCount = 0;
58 | return TRUE;
59 | }
60 | auto& s = S4::GetInstance().Selection;
61 | if (!s) return FALSE;
62 | auto ppool = S4::GetInstance().EntityPool;
63 | if (!ppool) return FALSE;
64 | auto pool = *ppool;
65 |
66 | // build a set for settlers to remove
67 | std::unordered_set removeSet;
68 | for (SIZE_T i = 0; i < settlerslen; i++) {
69 | auto e = settlers[i];
70 | if (e) removeSet.insert(e);
71 | }
72 |
73 | auto end = s->EndPtr;
74 | auto cur = s->BasePtr;
75 | for (auto sp = cur; sp < end; ++sp) {
76 | if (removeSet.find(*sp) != removeSet.end()) {
77 | pool[*sp].clrSelectionVisibility();
78 | continue;
79 | }
80 | *cur = *sp;
81 | ++cur;
82 | }
83 | if (removedCount) *removedCount = end - cur;
84 | if (cur == s->BasePtr) {
85 | // all elements have been removed
86 | //ClearSelection();
87 | }
88 | s->EndPtr = cur;
89 | return TRUE;
90 | }
91 |
92 | DWORD CSettlers4Api::SetMaxSelection(DWORD newLimit) {
93 | TRACE;
94 | return CSelectionMod::GetInstance().SetMaxSelection(newLimit);
95 | }
96 |
97 | DWORD CSettlers4Api::GetMaxSelection() {
98 | TRACE;
99 | return CSelectionMod::GetInstance().GetMaxSelection();
100 | }
101 |
--------------------------------------------------------------------------------
/S4ModApi/CS4SendWarriors.cpp:
--------------------------------------------------------------------------------
1 | #include "CSettlers4Api.h"
2 | #include "patterns.h"
3 | #include "globals.h"
4 | #include "safemem.h"
5 | #include "s4.h"
6 |
7 | BOOL CSettlers4Api::SendWarriors(INT x, INT y, S4_MOVEMENT_ENUM mode, PWORD warriors, SIZE_T countOfWarriors, DWORD player) {
8 | TRACE;
9 |
10 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
11 | if (!localPlayer) return FALSE;
12 |
13 | DWORD pos = ((WORD)y) << 16 | ((WORD)x);
14 |
15 | static DWORD heapAlloc = 0;
16 | static DWORD fillEventArg = 0;
17 | static DWORD one;
18 | static DWORD fillEvent = 0;
19 | static DWORD sendEvent = 0;
20 | one = 1;
21 | if (!heapAlloc) {
22 | DWORD addr = g_Patterns.OnSettlerCommandHook + (g_isGE ? 88 : 99);
23 | DWORD off = READ_AT((LPCVOID)addr, 1);
24 | if (addr && off)
25 | heapAlloc = addr + off + 5;
26 | else
27 | return FALSE;
28 | }
29 | if (!g_isGE && !fillEvent) {
30 | DWORD addr = g_Patterns.OnSettlerCommandHook + 0xB4;
31 | DWORD off = READ_AT((LPCVOID)addr, 1);
32 | if (addr && off)
33 | fillEvent = addr + off + 5;
34 | else
35 | return FALSE;
36 | }
37 | if (!sendEvent) {
38 | DWORD addr = g_Patterns.OnSettlerCommandHook + (g_isGE ? 0xE9 : 0xC3);
39 | DWORD off = READ_AT((LPCVOID)addr, 1);
40 | if (addr && off)
41 | sendEvent = addr + off + 5;
42 | else
43 | return FALSE;
44 | }
45 | //if (!fillEventArg)
46 | // fillEventArg = READ_AT((LPCVOID)(g_Patterns.OnSettlerCommandHook - (g_isGE ? 0x73 : 0x66))); // local player
47 | //if (!fillEventArg)
48 | // fillEventArg = (DWORD)&one;
49 | //DWORD dwFillEventArg = *(DWORD*)fillEventArg;
50 |
51 | auto repetitions = (countOfWarriors+99u) / 100u;
52 | for (auto i = 0u; i < repetitions; i++) {
53 | auto lower = i * 100;
54 | auto count = min(countOfWarriors - lower, 100) * sizeof(WORD);
55 | void* mem = NULL;
56 |
57 | __asm {
58 | // Allocate the mem just like the game would do it.
59 | // The game will free it for us later
60 | push count
61 | //mov eax, S4_Main
62 | //add eax, 0x94FBF7
63 | call heapAlloc
64 | add esp, 04 // cdecl!
65 | mov mem, eax
66 | }
67 |
68 | if (mem) {
69 | memcpy(mem, &warriors[lower], count);
70 |
71 | #pragma pack(push, 1)
72 | union {
73 | struct EventStruct_t {
74 | /*00*/DWORD CEvn_Logic_vtbl; // 0x14 // vtable
75 | /*04*/DWORD movementCommandId; // 0x18 // 0x1396
76 | /*08*/DWORD position; // 0x1C
77 | /*0C*/DWORD commandType; // 0x20
78 | /*10*/DWORD tick; // 0x24
79 | /*14*/DWORD null; // 0x28 // always 0 ?
80 | /*18*/DWORD settlersArray; // 0x2C
81 | /*1C*/WORD sizeofArray; // 0x30
82 | /*1E*/BYTE dl; // 0x32 // local player
83 | } eventStruct;
84 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
85 | } u1;
86 | #pragma pack(pop)
87 |
88 | if (g_isGE) {
89 | // note for the GE we must populate the struct ourselfs as the function is inlined :(
90 | static const DWORD vtblPtr = READ_AT(g_Patterns.OnSettlerCommandHook, 0xC5);
91 | u1.eventStruct.CEvn_Logic_vtbl = *(DWORD*)(vtblPtr);
92 | u1.eventStruct.movementCommandId = 0x1396;
93 | u1.eventStruct.position = pos;
94 | u1.eventStruct.commandType = mode;
95 | DWORD stick = 0;
96 | static const DWORD tickPtr = READ_AT(g_Patterns.OnSettlerCommandHook, 0x87);
97 | if (tickPtr) {
98 | stick = *(DWORD*)(tickPtr);
99 | if (stick) {
100 | stick = *(DWORD*)(stick + 0x18);
101 | if (stick) {
102 | stick = *(DWORD*)(stick);
103 | }
104 | }
105 | }
106 | u1.eventStruct.tick = stick;
107 | u1.eventStruct.null = 0;
108 | u1.eventStruct.settlersArray = (DWORD)mem;
109 | u1.eventStruct.sizeofArray = (WORD)count;
110 | u1.eventStruct.dl = (BYTE)localPlayer;
111 | void* arg = &u1.eventStruct;
112 | static const DWORD* pthisptr = (DWORD*)READ_AT(g_Patterns.OnSettlerCommandHook, 0x7D);
113 | if (pthisptr && *pthisptr) {
114 | DWORD pthis = *pthisptr;
115 | __asm {
116 | // send the event just like the game would do it
117 | mov ecx, pthis
118 | push arg
119 | call sendEvent
120 | }
121 | }
122 | } else {
123 | // we could populate this ourselfs buf its easier to let
124 | // the game do it for us. The game will basically just
125 | // copy the arguments and insert the events tick number
126 | __asm {
127 | // fill the event struct just like the game would do it
128 | push count
129 | lea ecx, u1.eventStructBytes
130 | push mem
131 | push localPlayer
132 | push mode // command type
133 | push pos // target position
134 | push 0x1396 // movement command id
135 | call fillEvent
136 |
137 | // send the event just like the game would do it
138 | lea eax, u1.eventStructBytes
139 | push eax
140 | call sendEvent
141 | }
142 | }
143 |
144 |
145 | } // if (mem)
146 | } // for
147 |
148 | return TRUE;
149 | }
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Singleton.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 |
24 | CSettlers4Api& CSettlers4Api::GetInstance() { static CSettlers4Api instance; return instance; }
25 | CSettlers4Api::CSettlers4Api() : m_refs(0) { TRACE; }
26 | CSettlers4Api::~CSettlers4Api() { TRACE; }
27 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Trading.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "patterns.h"
24 | #include "globals.h"
25 | #include "safemem.h"
26 | #include "s4.h"
27 |
28 | BOOL CSettlers4Api::SetTradingRoute(DWORD sourceBuilding, DWORD destinationBuilding, DWORD player) {
29 | TRACE;
30 |
31 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
32 | if (!vtbl) return FALSE;
33 |
34 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
35 | if (!localPlayer) return FALSE;
36 |
37 | #pragma pack(push, 1)
38 | static union {
39 | struct EventStruct_t {
40 | /*00*/DWORD CEvn_Logic_vtbl; // vtable
41 | /*04*/DWORD eventId; // 0x138D
42 | /*08*/DWORD sourceBuilding;
43 | /*0C*/DWORD destinationBuilding;
44 | /*10*/DWORD tick; //
45 | /*14*/BYTE flags; // always 0 ?
46 | /*16*/BYTE __pad[3]; // ignored
47 | /*18*/DWORD settlersArray; // must be 0
48 | /*1C*/WORD sizeofArray; // always 0
49 | /*1E*/BYTE player; //
50 | } eventStruct;
51 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
52 | } u1;
53 | #pragma pack(pop)
54 |
55 | ZeroMemory(&u1, sizeof(u1));
56 |
57 | u1.eventStruct.CEvn_Logic_vtbl = vtbl; // 00E4BA08
58 | if (!u1.eventStruct.CEvn_Logic_vtbl) return FALSE;
59 | u1.eventStruct.eventId = 0x138D;
60 | u1.eventStruct.sourceBuilding = sourceBuilding;
61 | u1.eventStruct.destinationBuilding = destinationBuilding;
62 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
63 | u1.eventStruct.player = (BYTE)localPlayer;
64 |
65 | return S4::GetInstance().SendNetEvent(&u1);
66 | }
67 |
68 | BOOL CSettlers4Api::TradeGood(DWORD buidling, S4_GOOD_ENUM good, INT amount, DWORD player) {
69 | TRACE;
70 |
71 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
72 | if (!vtbl) return FALSE;
73 |
74 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
75 | if (!localPlayer) return FALSE;
76 |
77 | #pragma pack(push, 1)
78 | static union {
79 | struct EventStruct_t {
80 | /*00*/DWORD CEvn_Logic_vtbl; // vtable
81 | /*04*/DWORD eventId; // 0x13BE
82 | /*08*/WORD good;
83 | /*0A*/WORD buidling;
84 | /*0C*/INT32 amount;
85 | /*10*/DWORD tick; //
86 | /*14*/BYTE flags; // always 0 ?
87 | /*16*/BYTE __pad[3]; // ignored
88 | /*18*/DWORD settlersArray; // must be 0
89 | /*1C*/WORD sizeofArray; // always 0
90 | /*1E*/BYTE player; //
91 | } eventStruct;
92 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
93 | } u1;
94 | #pragma pack(pop)
95 |
96 | ZeroMemory(&u1, sizeof(u1));
97 |
98 | u1.eventStruct.CEvn_Logic_vtbl = vtbl; // 00E4BA08
99 | u1.eventStruct.eventId = 0x138E;
100 | u1.eventStruct.good = (WORD)(good);
101 | u1.eventStruct.buidling = (WORD)buidling;
102 | u1.eventStruct.amount = amount;
103 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
104 | u1.eventStruct.player = (BYTE)localPlayer;
105 |
106 | return S4::GetInstance().SendNetEvent(&u1);
107 | }
108 |
109 | BOOL CSettlers4Api::StoreGood(DWORD buidling, S4_GOOD_ENUM good, BOOL enable, DWORD player) {
110 | TRACE;
111 |
112 | DWORD vtbl = S4::GetInstance().GetNetEventVTbl(); // 00E4BA08
113 | if (!vtbl) return FALSE;
114 |
115 | DWORD localPlayer = player ? player : S4::GetInstance().GetLocalPlayer();
116 | if (!localPlayer) return FALSE;
117 |
118 | #pragma pack(push, 1)
119 | static union {
120 | struct EventStruct_t {
121 | /*00*/DWORD CEvn_Logic_vtbl; // vtable
122 | /*04*/DWORD eventId; // 0x13B4
123 | /*08*/WORD good;
124 | /*0A*/WORD buidling;
125 | /*0C*/INT32 enable;
126 | /*10*/DWORD tick; //
127 | /*14*/BYTE flags; // always 0 ?
128 | /*16*/BYTE __pad[3]; // ignored
129 | /*18*/DWORD settlersArray; // must be 0
130 | /*1C*/WORD sizeofArray; // always 0
131 | /*1E*/BYTE player; //
132 | } eventStruct;
133 | BYTE eventStructBytes[32]; // event struct is at least 32 bytes
134 | } u1;
135 | #pragma pack(pop)
136 |
137 | ZeroMemory(&u1, sizeof(u1));
138 |
139 | u1.eventStruct.CEvn_Logic_vtbl = vtbl; // 00E4BA08
140 | u1.eventStruct.eventId = 0x13B4;
141 | u1.eventStruct.good = (WORD)(good);
142 | u1.eventStruct.buidling = (WORD)buidling;
143 | u1.eventStruct.enable = enable;
144 | u1.eventStruct.tick = S4::GetInstance().GetCurrentTick();
145 | u1.eventStruct.player = (BYTE)localPlayer;
146 |
147 | return S4::GetInstance().SendNetEvent(&u1);
148 | }
149 |
150 |
--------------------------------------------------------------------------------
/S4ModApi/CS4Unknown.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "CSettlers4Api.h"
23 | #include "globals.h"
24 | #include
25 |
26 | HRESULT CSettlers4Api::QueryInterface(REFIID riid, LPVOID* ppvObj) {
27 | TRACE;
28 | if (ppvObj == NULL) {
29 | return E_POINTER;
30 | }
31 |
32 | if (riid == IID_IUnknown) {
33 | *ppvObj = static_cast(this);
34 | }
35 | else if (riid == IID_ISettlers4Api2) {
36 | *ppvObj = static_cast(this);
37 | }
38 | // Template that can be used when adding version 3.x of the interface
39 | //else if (riid == IID_ISettlers4Api3) {
40 | // *ppvObj = static_cast(this);
41 | //}
42 | else {
43 | *ppvObj = NULL;
44 | return E_NOINTERFACE;
45 | }
46 |
47 | (static_cast(*ppvObj))->AddRef();
48 |
49 | return S_OK;
50 | }
51 |
52 | static std::mutex mtx; // ref counter lock
53 |
54 | ULONG CSettlers4Api::AddRef() {
55 | TRACE;
56 | std::lock_guard lock(mtx);
57 | return ++m_refs;
58 | }
59 |
60 | ULONG CSettlers4Api::Release() {
61 | TRACE;
62 | std::lock_guard lock(mtx);
63 | // Decrement the object's internal counter.
64 | auto lRefCount = --m_refs;
65 | if (lRefCount <= 0) {
66 | //delete this;
67 | return 0;
68 | }
69 | return lRefCount;
70 | }
71 |
--------------------------------------------------------------------------------
/S4ModApi/CSelectionMod.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CMod.h"
25 |
26 | ///
27 | /// Selection Mod that allows the player to select and command more than
28 | /// 100 settlers.
29 | ///
30 | class CSelectionMod : public CMod {
31 | public:
32 | static CSelectionMod& GetInstance();
33 |
34 | DWORD SetMaxSelection(DWORD newLimit);
35 | DWORD GetMaxSelection();
36 |
37 | protected:
38 | virtual bool Init();
39 | virtual void Patch();
40 | virtual void Unpatch();
41 |
42 | private:
43 | CSelectionMod();
44 | static HRESULT S4HCALL CSelectionMod::OnSettlersSend(DWORD dwPosition, S4_MOVEMENT_ENUM dwCommand, LPVOID lpReserved);
45 | };
46 |
47 |
--------------------------------------------------------------------------------
/S4ModApi/CSettlerSendHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // CallPatch
24 | #include "patterns.h"
25 | #include "CSettlerSendHook.h"
26 |
27 | static hlib::CallPatch OnSettlerCommandHook;
28 |
29 | bool __stdcall CSettlerSendHook::OnNewCommand(DWORD position, S4_MOVEMENT_ENUM command) {
30 | TRACE;
31 | mutex.lock();
32 | auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
33 | mutex.unlock();
34 | for (auto& observer : observers) {
35 | if (((LPS4SETTLERSENDCALLBACK)observer.callback)(position, command, 0))
36 | return true;
37 | }
38 | return false;
39 | }
40 |
41 | static void __declspec(naked) __newCommand() {
42 | __asm {
43 | push eax
44 | push ecx
45 | push edx
46 | push esi
47 | cmp g_isGE, 0
48 | jz lbl_he
49 | push ebp // this is the position for the GE
50 | jmp lbl_cont
51 | lbl_he :
52 | push ebx // this is the position for the HE
53 | lbl_cont :
54 | call CSettlerSendHook::OnNewCommand
55 | pop edx
56 | pop ecx
57 | test al, al
58 | pop eax
59 | jz lbl_cont2
60 | mov eax, edi // cancel the command
61 | lbl_cont2 :
62 | sub edi, eax
63 | sar edi, 1
64 | test edi, edi
65 | ret
66 | }
67 | }
68 |
69 | CSettlerSendHook& CSettlerSendHook::GetInstance() {
70 | static CSettlerSendHook inst;
71 | return inst;
72 | }
73 |
74 | bool CSettlerSendHook::Init() {
75 | TRACE;
76 | if (!g_Patterns.OnSettlerCommandHook) return false;
77 |
78 | DWORD addr = g_Patterns.OnSettlerCommandHook;
79 | OnSettlerCommandHook = hlib::CallPatch(addr, (DWORD)__newCommand, 1);
80 |
81 | return true;
82 | }
83 |
84 | void CSettlerSendHook::Patch() {
85 | TRACE;
86 | OnSettlerCommandHook.patch();
87 | }
88 |
89 | void CSettlerSendHook::Unpatch() {
90 | TRACE;
91 | OnSettlerCommandHook.unpatch();
92 | }
93 |
94 | CSettlerSendHook::CSettlerSendHook() { TRACE; }
95 |
--------------------------------------------------------------------------------
/S4ModApi/CSettlerSendHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CSettlerSendHook : public CHook {
27 | public:
28 | static CSettlerSendHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CSettlerSendHook();
37 | static bool __stdcall OnNewCommand(DWORD position, S4_MOVEMENT_ENUM command);
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CTickHook.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "globals.h" // g_isGE, hProcess
23 | #include "hlib.h" // CallPatch
24 | #include "patterns.h"
25 | #include "CTickHook.h"
26 |
27 | static hlib::CallPatch OnTickHook;
28 |
29 | bool __stdcall CTickHook::OnTick(DWORD tick, bool hasEvent) {
30 | TRACE;
31 | bool delay = false;
32 |
33 | mutex.lock();
34 | auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
35 | mutex.unlock();
36 | for (auto& observer : observers) {
37 | delay |= (bool)(((LPS4TICKCALLBACK)observer.callback)(tick, hasEvent, delay));
38 | }
39 | return delay;
40 | }
41 |
42 | static void __declspec(naked) __onTick() {
43 | __asm {
44 | cmp g_isGE, 0
45 | jz lbl_he
46 | mov eax, [ecx] // only for ge
47 | lbl_he:
48 | mov eax, [eax + 0x0C]
49 | call eax
50 | push eax
51 | push ecx
52 | push edx
53 | movzx eax, al
54 | push eax
55 | push ebx // tick
56 | call CTickHook::OnTick
57 | pop edx
58 | pop ecx
59 | test al, al
60 | pop eax
61 | jz lbl_processEvent
62 | xor eax, eax
63 | lbl_processEvent :
64 | ret
65 | }
66 | }
67 |
68 | CTickHook& CTickHook::GetInstance() {
69 | static CTickHook inst;
70 | return inst;
71 | }
72 |
73 | bool CTickHook::Init() {
74 | TRACE;
75 | if (!g_Patterns.OnSettlerCommandHook) return false;
76 |
77 | DWORD addr = g_Patterns.OnTickHook + (g_isGE ? 6 : 8);
78 | OnTickHook = hlib::CallPatch(addr, (DWORD)__onTick);
79 |
80 | return true;
81 | }
82 |
83 | void CTickHook::Patch() {
84 | TRACE;
85 | OnTickHook.patch();
86 | }
87 |
88 | void CTickHook::Unpatch() {
89 | TRACE;
90 | OnTickHook.unpatch();
91 | }
92 |
93 | CTickHook::CTickHook() { TRACE; }
94 |
--------------------------------------------------------------------------------
/S4ModApi/CTickHook.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "CHook.h"
25 |
26 | class CTickHook : public CHook {
27 | public:
28 | static CTickHook& GetInstance();
29 |
30 | protected:
31 | virtual bool Init();
32 | virtual void Patch();
33 | virtual void Unpatch();
34 |
35 | private:
36 | CTickHook();
37 | static bool __stdcall OnTick(DWORD tick, bool hasEvent);
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/S4ModApi/CUpdate.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | /**
23 | * This is a quick and dirty auto update script. It will replace the S4ModApi.dll with the latest
24 | * non-prerelease version from the github release.
25 | **/
26 |
27 | #pragma once
28 |
29 | #include "windef.h"
30 | #include
31 |
32 | class CUpdate {
33 | public:
34 | enum EUpdateCheckStatus {
35 | UPDATE_CHECK_UNK,
36 | UPDATE_CHECK_ERROR,
37 | UPDATE_CHECK_AVAILABLE,
38 | UPDATE_CHECK_UPTODATE,
39 | };
40 |
41 | static CUpdate& GetInstance();
42 |
43 | EUpdateCheckStatus check(); // check for updates
44 | DWORD getMillisSinceCheck(); // how many milliseconds elapsed since we polled for the last result
45 |
46 | private:
47 | void InitVersion();
48 | void InstallUpdate(const std::string& url);
49 |
50 | CUpdate& operator=(const CUpdate&) = delete;
51 | CUpdate(const CUpdate&) = delete;
52 | CUpdate() = default;
53 |
54 | bool m_hasChecked = false;
55 | EUpdateCheckStatus m_status = UPDATE_CHECK_UNK;
56 | DWORD m_receivedTick = 0xFFFFFFFF;
57 | WORD m_verMayor = 0, m_verMinor = 0;
58 | };
--------------------------------------------------------------------------------
/S4ModApi/Console.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #if _DEBUG
23 |
24 | #define WIN32_LEAN_AND_MEAN
25 | #include "windows.h"
26 | #include
27 | #include
28 | #include
29 |
30 | static FILE* g_ConsoleFile = NULL;
31 |
32 | void InitConsole() {
33 | AllocConsole();
34 | g_ConsoleFile = NULL;
35 | freopen_s(&g_ConsoleFile, "conout$", "w", stdout);
36 | }
37 |
38 | void DestroyConsole() {
39 | if (g_ConsoleFile != NULL) {
40 | fclose(g_ConsoleFile);
41 | g_ConsoleFile = NULL;
42 | }
43 | FreeConsole();
44 | }
45 |
46 | HWND GetConsoleHwnd() {
47 | // This snipped was taken from https://support.microsoft.com/de-ch/help/124103/how-to-obtain-a-console-window-handle-hwnd
48 |
49 | const unsigned MY_BUFSIZE = 1024; // Buffer size for console window titles.
50 | HWND hwndFound; // This is what is returned to the caller.
51 | char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated WindowTitle
52 | char pszOldWindowTitle[MY_BUFSIZE]; // Contains original WindowTitle
53 | GetConsoleTitleA(pszOldWindowTitle, MY_BUFSIZE); // Fetch current window title.
54 | sprintf_s(pszNewWindowTitle, "%d/%d", // Format a "unique" NewWindowTitle.
55 | GetTickCount(),
56 | GetCurrentProcessId());
57 | SetConsoleTitleA(pszNewWindowTitle); // Change current window title.
58 | Sleep(40); // Ensure window title has been updated.
59 | hwndFound = FindWindowA(NULL, pszNewWindowTitle); // Look for NewWindowTitle.
60 | SetConsoleTitleA(pszOldWindowTitle); // Restore original window title.
61 | return hwndFound;
62 | }
63 |
64 | #endif
--------------------------------------------------------------------------------
/S4ModApi/Console.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #if _DEBUG
25 |
26 | #include
27 | #include // std::setfill, std::setw
28 | #include "windows.h"
29 |
30 | using std::cout;
31 | using std::hex;
32 | using std::dec;
33 | using std::endl;
34 |
35 | #define HEXNUM(a) "0x" << hex << std::setfill('0') << std::setw(8) << ((DWORD)(a))
36 |
37 | void InitConsole();
38 | void DestroyConsole();
39 | HWND GetConsoleHwnd();
40 |
41 | #endif
--------------------------------------------------------------------------------
/S4ModApi/DebugInfo.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/S4ModApi/DebugInfo.cpp
--------------------------------------------------------------------------------
/S4ModApi/DebugProgram.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #if _DEBUG
23 |
24 | #include "windows.h"
25 | #include "Console.h"
26 | #include "S4ModApi.h"
27 | #include
28 | #include "DebugRender.h"
29 | #include "CMessageBox.h"
30 | #include "globals.h"
31 | #include "Log.h"
32 |
33 | #define DEBUG_KEY VK_F5
34 | #define DEBUG_KEY_STR "F5"
35 |
36 | extern "C" HRESULT __declspec(nothrow) S4HCALL S4HooksGetDebugData(UINT32 type, LPSTR buf, SIZE_T bufsize);
37 |
38 | CMessageBox g_GreetingsMessageBox(
39 | L"g_GreetingsMessageBox",
40 | L"It appears that you are running a debug build of the S4ModApi.dll.\n"
41 | "You should update it to a release build if you are not a developer or bug tester. "
42 | "See https://github.com/nyfrk/S4ModApi for proper release.\n\n"
43 | "You can press " DEBUG_KEY_STR " to toggle the console window. ", 100, 100, 450, 250);
44 |
45 | void DebugProgramMain() {
46 | TRACE;
47 |
48 | //std::vector hooks;
49 |
50 | while (1) {
51 | TRACE;
52 |
53 | cout << endl << "** Welcome to the S4ModApi Debug Menu **" << endl << endl;
54 |
55 | {
56 | // print the patterns
57 | char* buf = new char[4096];
58 | cout << "$ S4HooksGetDebugData(0x80000000," << HEXNUM(buf) << "," << dec << 2048 << ")" << endl;
59 | auto ret = S4HooksGetDebugData(0x80000000, buf, 4096);
60 | cout << " " << HEXNUM(ret) << endl;
61 | delete[] buf;
62 | }
63 |
64 | Sleep(1000);
65 |
66 | cout << "$ S4ApiCreate()" << endl;
67 | auto S4API = S4ApiCreate();
68 | if (S4API) {
69 | cout << " success." << endl;
70 | } else {
71 | cout << " failure." << endl;
72 | for (int t = 3; t >= 0; t--) {
73 | cout << " will retry in " << dec << t << " seconds." << endl;
74 | Sleep(1000);
75 | }
76 | continue;
77 | }
78 |
79 | g_GreetingsMessageBox.Show();
80 |
81 | //{ cout << "$ " << HEXNUM(S4API) << "->AddFrameListener(" << HEXNUM(DebugFrameProc) << ")" << endl;
82 | // auto res = S4API->AddFrameListener(DebugFrameProc);
83 | // cout << " " << dec << res << endl;
84 | // hooks.push_back(res);
85 | //}
86 |
87 | while (GetAsyncKeyState(DEBUG_KEY) >= 0) {
88 | Sleep(100);
89 |
90 | if (GetAsyncKeyState(VK_MULTIPLY) < 0) {
91 | CMessageBox test(L"Caption", L"This is a test message", 200, 200, 400, 150);
92 | test.Show();
93 | while (GetAsyncKeyState(VK_MULTIPLY) < 0) { Sleep(10); }
94 | cout << "Hide Reason = " << dec << (DWORD)test.GetHideReason() << endl;
95 | }
96 | }
97 | while (GetAsyncKeyState(DEBUG_KEY) < 0) Sleep(10);
98 |
99 | //for (auto& hook : hooks) {
100 | // cout << "$ " << HEXNUM(S4API) << "->RemoveListener(" << dec << (DWORD)hook << ")" << endl;
101 | // auto res = S4API->RemoveListener(hook);
102 | // cout << " " << dec << res << endl;
103 | //}
104 |
105 | //hooks.clear();
106 |
107 | { cout << "$ " << HEXNUM(S4API) << "->Release()" << endl;
108 | auto res = S4API->Release();
109 | cout << " " << dec << res << endl;
110 | }
111 |
112 | cout << endl << "** goodbye **" << endl << endl;
113 |
114 |
115 | Sleep(2000);
116 |
117 | HWND hwnd = GetConsoleHwnd();
118 | ShowWindow(hwnd, SW_HIDE);
119 |
120 | while (GetAsyncKeyState(DEBUG_KEY) >= 0) Sleep(100);
121 | while (GetAsyncKeyState(DEBUG_KEY) < 0) Sleep(10);
122 |
123 | ShowWindow(hwnd, SW_SHOW);
124 | }
125 |
126 | }
127 |
128 |
129 | #endif
--------------------------------------------------------------------------------
/S4ModApi/DebugRender.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #if _DEBUG
23 |
24 | #include "DebugRender.h"
25 | #include "Console.h"
26 |
27 | HRESULT S4HCALL DebugFrameProc(LPDIRECTDRAWSURFACE7 lpSurface, INT32 iPillarboxWidth, LPVOID lpReserved) {
28 | UNREFERENCED_PARAMETER(lpSurface);
29 | UNREFERENCED_PARAMETER(iPillarboxWidth);
30 | UNREFERENCED_PARAMETER(lpReserved);
31 |
32 | auto S4API = S4ApiCreate();
33 | if (!S4API) return 0;
34 |
35 | POINT p = { 0 };
36 | HWND hwnd = S4API->GetHwnd();
37 | const bool hasCursor = hwnd && GetCursorPos(&p) && ScreenToClient(hwnd, &p);
38 |
39 | //for (DWORD i = 0; i < S4_GUI_ENUM_MAXVALUE; i++) {
40 | // if (S4API->IsCurrentlyOnScreen((S4_GUI_ENUM)i)) {
41 | // cout << " " << dec << i << " is on screen" << endl;
42 | // }
43 | //}
44 |
45 | S4API->Release();
46 | return 0;
47 | }
48 |
49 | #endif
--------------------------------------------------------------------------------
/S4ModApi/DebugRender.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #if _DEBUG
25 |
26 | #include "S4ModApi.h"
27 |
28 | HRESULT S4HCALL DebugFrameProc(LPDIRECTDRAWSURFACE7 lpSurface, INT32 iPillarboxWidth, LPVOID lpReserved);
29 |
30 | #endif
--------------------------------------------------------------------------------
/S4ModApi/Log.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #ifdef _DEBUG
23 |
24 | #include "Log.h"
25 | #include
26 |
27 | std::ofstream g_LogStream;
28 | std::recursive_mutex g_LogStream_Mutex;
29 | volatile int isLogTraceInit = false;
30 | static __declspec(thread) int depth = 0;
31 | static __declspec(thread) std::string g_lastfunc;
32 |
33 | std::string GetLogstreamFilename() {
34 | char fname[MAX_PATH + 1];
35 | auto len = GetModuleFileNameA(NULL, fname, MAX_PATH);
36 | fname[len] = '\0';
37 | char* logfname = fname;
38 | for (int i = len; i >= 0; --i) {
39 | if (fname[i] == '\\' || fname[i] == '/') {
40 | fname[++i] = '\0';
41 | break;
42 | }
43 | }
44 | return std::string(logfname) + "S4ModApi.log";
45 | }
46 |
47 | void DestroyLogstream() {
48 | std::lock_guard lock(g_LogStream_Mutex);
49 | isLogTraceInit = false;
50 | g_LogStream.close();
51 | }
52 |
53 | void InitLogstream() {
54 | std::lock_guard lock(g_LogStream_Mutex);
55 | g_LogStream.open(GetLogstreamFilename(), std::ios_base::out);
56 | g_LogStream << "This is a S4ModApi.log file. It has been produced by S4ModApi.dll." << endl
57 | << "See https://github.com/nyfrk/S4Hooks for more information on this project." << endl
58 | << "You can safely delete this log file. If the log creation annoys you, just switch" << endl
59 | << "to a release build (you are using a debug build)" << endl << endl;
60 | isLogTraceInit = true;
61 | }
62 |
63 | std::string RAIILogTrace::Timestamp(int extended) {
64 | SYSTEMTIME time;
65 | GetSystemTime(&time);
66 | std::stringstream ss;
67 | ss << dec;
68 | if (extended) {
69 | ss <<
70 | std::setfill('0') << std::setw(4) << time.wYear << '-' <<
71 | std::setfill('0') << std::setw(2) << time.wMonth << '-' <<
72 | std::setfill('0') << std::setw(2) << time.wDay << ' ' <<
73 | std::setfill('0') << std::setw(2) << time.wHour << ':' <<
74 | std::setfill('0') << std::setw(2) << time.wMinute << ':' <<
75 | std::setfill('0') << std::setw(2) << time.wSecond << "#" <<
76 | std::setfill('0') << std::setw(4) << time.wMilliseconds;
77 | }
78 | else {
79 | DWORD t = ((DWORD)time.wMilliseconds)
80 | + (1000u * (DWORD)time.wSecond)
81 | + (1000u * 60u * (DWORD)time.wMinute);
82 | t %= 1000000;
83 | ss << std::setfill(' ') << std::setw(6) << t;
84 | }
85 | return ss.str();
86 | }
87 |
88 | std::string RAIILogTrace::Indentation() {
89 | std::stringstream ss;
90 | for (int i = 0; i < depth; i++) {
91 | ss << " ";
92 | }
93 | return ss.str();
94 | }
95 |
96 | RAIILogTrace::RAIILogTrace(std::string file, unsigned line, std::string func, LPCVOID a) {
97 | if (!isLogTraceInit) return;
98 | std::lock_guard lock(g_LogStream_Mutex);
99 | if (!isLogTraceInit) return;
100 | g_LogStream << LOG_PROLOG_LONG << Indentation();
101 | if (g_lastfunc == func) {
102 | g_LogStream << "code at " << file << ":" << dec << line << " // in " << func << std::endl;
103 | nodestructor = true;
104 | }
105 | else {
106 | g_LogStream << func << "("<< HEXNUM(a) <<") { // at " << file << ":" << dec << line << std::endl;
107 | ++depth;
108 | lastfunc = g_lastfunc;
109 | g_lastfunc = func;
110 | nodestructor = false;
111 | }
112 | g_LogStream.flush();
113 | }
114 |
115 | RAIILogTrace::RAIILogTrace(std::string file, unsigned line, std::string func) : func(func) {
116 | if (!isLogTraceInit) return;
117 | std::lock_guard lock(g_LogStream_Mutex);
118 | if (!isLogTraceInit) return;
119 | g_LogStream << LOG_PROLOG_LONG << Indentation();
120 | if (g_lastfunc == func) {
121 | g_LogStream << "code at " << file << ":" << dec << line << " // in " << func << std::endl;
122 | nodestructor = true;
123 | }
124 | else {
125 | g_LogStream << func << " { // at " << file << ":" << dec << line << std::endl;
126 | ++depth;
127 | lastfunc = g_lastfunc;
128 | g_lastfunc = func;
129 | nodestructor = false;
130 | }
131 | g_LogStream.flush();
132 | }
133 |
134 | RAIILogTrace::~RAIILogTrace() {
135 | if (!isLogTraceInit) return;
136 | std::lock_guard lock(g_LogStream_Mutex);
137 | if (!isLogTraceInit) return;
138 | g_lastfunc = lastfunc;
139 | if (!nodestructor) {
140 | --depth;
141 | g_LogStream << LOG_PROLOG_LONG << Indentation() << "} // " << func << std::endl;
142 | g_LogStream.flush();
143 | }
144 | }
145 |
146 | #endif
--------------------------------------------------------------------------------
/S4ModApi/Log.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #ifdef _DEBUG
25 |
26 | #include "Console.h"
27 | #include
28 | #include
29 | #include
30 | #include
31 | extern std::ofstream g_LogStream;
32 |
33 | std::string GetLogstreamFilename();
34 | void InitLogstream();
35 | void DestroyLogstream();
36 |
37 | extern volatile int isLogTraceInit;
38 |
39 | #define LOG(a) {\
40 | if (isLogTraceInit) {\
41 | g_LogStream_Mutex.lock();\
42 | cout << LOG_PROLOG_SHORT << a << endl;\
43 | g_LogStream << LOG_PROLOG_LONG << RAIILogTrace::Indentation() << "| " << a << endl;\
44 | g_LogStream.flush();\
45 | g_LogStream_Mutex.unlock();\
46 | }\
47 | }
48 |
49 | #define TRACE_(...) RAIILogTrace __raii_logtrace__(__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__);
50 | #define TRACE TRACE_()
51 |
52 | #define LOG_PROLOG(a) "[t:" << dec << std::setw(6) << std::setfill(' ') << GetCurrentThreadId() << ','\
53 | << RAIILogTrace::Timestamp(a) << "] "
54 | #define LOG_PROLOG_LONG LOG_PROLOG(1)
55 | #define LOG_PROLOG_SHORT LOG_PROLOG(0)
56 |
57 | extern std::recursive_mutex g_LogStream_Mutex;
58 |
59 | struct RAIILogTrace {
60 | static std::string RAIILogTrace::Indentation();
61 | static std::string RAIILogTrace::Timestamp(int extended);
62 | RAIILogTrace(std::string file, unsigned line, std::string func);
63 | RAIILogTrace(std::string file, unsigned line, std::string func, LPCVOID a);
64 | ~RAIILogTrace();
65 | std::string func;
66 | std::string lastfunc;
67 | bool nodestructor = false;
68 | };
69 |
70 | #else // _DEBUG
71 | #define LOG(x) ;
72 | #define TRACE ;
73 | #define TRACE_(x) ;
74 | #endif // _DEBUG
75 |
--------------------------------------------------------------------------------
/S4ModApi/S4CreateInterface.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 |
23 | #define WIN32_LEAN_AND_MEAN
24 | #include
25 | #include "CSettlers4Api.h"
26 | #include // new(std::nothrow)
27 | #include // sprintf_s
28 |
29 | HRESULT __declspec(nothrow) S4HCALL S4CreateInterface(CONST GUID FAR* lpGUID, S4API FAR* lplpS4H) {
30 | #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__ ",@1") // undecorated
31 | #pragma comment(linker, "/EXPORT:" __FUNCDNAME__ ) // stdcall decorated
32 | TRACE;
33 |
34 | if (!lplpS4H) return E_POINTER;
35 | if (!lpGUID) {
36 | *lplpS4H = NULL;
37 | return E_POINTER;
38 | }
39 |
40 | if (S_OK == CSettlers4Api::GetInstance().QueryInterface(*lpGUID, (LPVOID*)lplpS4H)) return S_OK;
41 |
42 | //if (*lpGUID == IID_ISettlers4Api) {
43 | // return ((*lplpS4H = new(std::nothrow) CSettlers4Api()) == nullptr) ? E_OUTOFMEMORY : S_OK;
44 | //}
45 |
46 | static bool showMessageBox = true;
47 | if (showMessageBox) {
48 | const char fmt[] =
49 | "Error: Missing Interface in S4ModApi.dll (%s)\n\n"
50 | "It appears that you are attempting to run a mod that expects a newer "
51 | "interface. Please go to https://github.com/nyfrk/S4ModApi and download "
52 | "the latest version.\n\n\n"
53 | "Do you want to open the URL in your browser?\n\n"
54 | "Click Yes if you want me to open the Download Page.\n"
55 | "Click No if you want to continue (no more warnings are shown)\n"
56 | "Click Cancel to stop the process.\n";
57 |
58 | char buf[_countof(fmt) + 45*2]; // 45 is length of a uuid in characters
59 | const char* txt = buf;
60 | LPOLESTR uuidStr = NULL;
61 |
62 | if (S_OK != StringFromCLSID(*lpGUID, &uuidStr) || uuidStr == NULL) {
63 | txt = fmt;
64 | } else {
65 | sprintf_s(buf, fmt, uuidStr);
66 | CoTaskMemFree(uuidStr);
67 | }
68 |
69 | auto idc = MessageBoxA(
70 | NULL,
71 | txt,
72 | "S4ModApi.dll",
73 | MB_YESNOCANCEL | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST | MB_ICONERROR);
74 |
75 | switch (idc) {
76 | case IDNO:
77 | break;
78 | case IDYES:
79 | system("start https://github.com/nyfrk/S4ModApi/issues/1");
80 | Sleep(2000);
81 | default: // cancel
82 | ExitProcess(0);
83 | }
84 |
85 | showMessageBox = false;
86 | }
87 |
88 | *lplpS4H = NULL;
89 | return E_NOINTERFACE;
90 | }
--------------------------------------------------------------------------------
/S4ModApi/S4ModApi.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/S4ModApi/S4ModApi.rc
--------------------------------------------------------------------------------
/S4ModApi/S4ModApi.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
7 | WindowsLocalDebugger
8 |
9 |
--------------------------------------------------------------------------------
/S4ModApi/dllmain.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #define WIN32_LEAN_AND_MEAN
23 | #include
24 | #include "globals.h"
25 | #include "Console.h"
26 | #include "Log.h"
27 | #include "module.h" // g_hModule
28 |
29 | BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {
30 | UNREFERENCED_PARAMETER(lpReserved);
31 |
32 | switch (ul_reason_for_call) {
33 | case DLL_PROCESS_ATTACH:
34 | g_hModule = hModule;
35 |
36 | #if _DEBUG
37 | InitConsole();
38 | InitLogstream();
39 | LOG("S4ModApi.dll has been attached at " << HEXNUM(g_hModule) << '.');
40 | #endif
41 |
42 | {
43 | // check file name
44 | WCHAR exeFQFilename[MAX_PATH + 1]; // fully qualified file name of the process executable
45 | auto len = GetModuleFileNameW(NULL, exeFQFilename, MAX_PATH);
46 | exeFQFilename[len] = '\0';
47 | LPCWSTR exeFilename = exeFQFilename; // the filename of the process executable (without path)
48 | for (int i = len; i >= 0; i--) {
49 | auto c = exeFQFilename[i];
50 | if (c == '\\' || c == '/') {
51 | exeFilename = &(exeFQFilename[i + 1]);
52 | break;
53 | }
54 | }
55 | // is filename S4_Main.exe ?
56 | if (0 == wcscmp(L"S4_Main.exe", exeFilename)) {
57 | TRACE;
58 |
59 | // compute the md5 of the target and cache it
60 | ComputeMD5(exeFQFilename, &g_md5);
61 |
62 | #if _DEBUG
63 | char md5str[2 * MD5LEN + 1];
64 | g_md5.ToString(md5str, sizeof(md5str));
65 | LOG("MD5 of " << exeFilename << " is " << md5str << '.');
66 | #endif
67 |
68 | // prevent lib from beeing unloaded when we are not ready with cleanup yet
69 | // use FreeLibraryAndExitThread to unload it.
70 | HMODULE mod = IncreaseModuleRefcount(InitializeGlobals);
71 | if (mod) {
72 | // evade the loader lock (thread gets started as soon as it becomes attached, witch will
73 | // only happen if the loader lock is released - thus everything is loaded
74 | HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)InitializeGlobals, mod, 0, NULL);
75 | if (!hThread) {
76 | DecreaseModuleRefcount(mod);
77 | return FALSE; // unload DLL
78 | } else {
79 | CloseHandle(hThread);
80 | }
81 | }
82 | }
83 | }
84 |
85 | break;
86 | case DLL_THREAD_ATTACH:
87 | LOG("thread attached");
88 | break;
89 | case DLL_THREAD_DETACH:
90 | LOG("thread detached");
91 | break;
92 | case DLL_PROCESS_DETACH:
93 | #ifdef _DEBUG
94 | LOG("S4ModApi.dll has been detached.");
95 | DestroyConsole();
96 | DestroyLogstream();
97 | #endif
98 |
99 | break;
100 | }
101 | return TRUE;
102 | }
103 |
104 |
--------------------------------------------------------------------------------
/S4ModApi/globals.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #define WIN32_LEAN_AND_MEAN
23 | #include "globals.h"
24 | #include "patterns.h"
25 | #include "s4.h"
26 | #include
27 | #include "CHook.h"
28 | #include "CMod.h"
29 | #include "md5.h"
30 | #include "CMessageBox.h"
31 | #include "CUpdate.h"
32 |
33 | bool g_isGE;
34 |
35 | DWORD S4_Main = 0;
36 | DWORD DDRAW = 0;
37 | DWORD EventEngine = 0;
38 | DWORD GuiEngine2 = 0;
39 | DWORD GfxEngine = 0;
40 | MD5 g_md5;
41 | std::atomic_bool g_isInitialized = false;
42 |
43 | #if _DEBUG
44 | void DebugProgramMain();
45 | #endif
46 |
47 | DWORD WINAPI InitializeGlobals(HMODULE mod) {
48 | TRACE;
49 |
50 | // find base addresses of modules of interest
51 | S4_Main = (DWORD)GetModuleHandleA(NULL);
52 | DDRAW = (DWORD)GetModuleHandleA("DDRAW");
53 | EventEngine = (DWORD)GetModuleHandleA("EventEngine"); // GE only
54 | GuiEngine2 = (DWORD)GetModuleHandleA("GuiEngine2"); // GE only
55 | GfxEngine = (DWORD)GetModuleHandleA("GfxEngine"); // GE only
56 |
57 | // set flag if we detect the presence of any dll that is used in the gold edition
58 | g_isGE = EventEngine || GuiEngine2 || GfxEngine;
59 |
60 | // scan for patterns
61 | g_Patterns.Scan();
62 |
63 | // initialize pointers to game structs
64 | S4::GetInstance().Initialize();
65 |
66 | // initialize all instantiated hooks (others will be lazy initialized)
67 | CHook::InitAll();
68 |
69 | // Initialize all mods
70 | CMod::InitAll();
71 |
72 | // Check for updates
73 | CUpdate::GetInstance().check();
74 |
75 | g_isInitialized = true;
76 |
77 | #if _DEBUG
78 | DebugProgramMain();
79 | #endif
80 |
81 | FreeLibraryAndExitThread(mod, 0); // decrements the reference counter
82 | return 0; // never reached
83 | }
84 |
--------------------------------------------------------------------------------
/S4ModApi/globals.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include
25 | #include
26 | #include "md5.h"
27 |
28 | extern bool g_isGE; // true if gold edition, false if history edition.
29 |
30 | extern DWORD S4_Main; // base address of S4_Main.exe
31 | extern DWORD DDRAW; // base address of DDRAW.dll
32 | extern DWORD EventEngine; // base address of EventEngine.dll. This is only present in the gold edition.
33 | extern DWORD GuiEngine2; // base address of GuiEngine2.dll. This is only present in the gold edition.
34 | extern DWORD GfxEngine; // base address of GfxEngine.dll. This is only present in the gold edition.
35 | extern MD5 g_md5; // md5 of the exe
36 | extern std::atomic_bool g_isInitialized; // variable that indicates when s4api has been initialized
37 |
38 |
39 | DWORD WINAPI InitializeGlobals(HMODULE mod);
40 |
--------------------------------------------------------------------------------
/S4ModApi/lib/.gitignore:
--------------------------------------------------------------------------------
1 | /Dummy
2 | *.cpp
3 | *.bat
4 | *.md
--------------------------------------------------------------------------------
/S4ModApi/lib/Debug/Lua321.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/S4ModApi/lib/Debug/Lua321.lib
--------------------------------------------------------------------------------
/S4ModApi/lib/Debug/Precompiled.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/S4ModApi/lib/Debug/Precompiled.lib
--------------------------------------------------------------------------------
/S4ModApi/lib/Debug142/Lua321.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/S4ModApi/lib/Debug142/Lua321.lib
--------------------------------------------------------------------------------
/S4ModApi/lib/Debug142/Precompiled.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/S4ModApi/lib/Debug142/Precompiled.lib
--------------------------------------------------------------------------------
/S4ModApi/lib/Release/Lua321.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/S4ModApi/lib/Release/Lua321.lib
--------------------------------------------------------------------------------
/S4ModApi/lib/Release/Precompiled.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nyfrk/S4ModApi/bb5d40ead1bb2a111ec0f787a6da5c15e130684e/S4ModApi/lib/Release/Precompiled.lib
--------------------------------------------------------------------------------
/S4ModApi/lib/hlib.cpp:
--------------------------------------------------------------------------------
1 | // hlib aggregation placeholder
2 |
--------------------------------------------------------------------------------
/S4ModApi/lib/lauxlib.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lauxlib.h,v 1.12 1999/03/10 14:19:41 roberto Exp $
3 | ** Auxiliary functions for building Lua libraries
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #ifndef auxlib_h
9 | #define auxlib_h
10 |
11 |
12 | #include "lua.h"
13 |
14 |
15 | struct luaL_reg {
16 | char *name;
17 | lua_CFunction func;
18 | };
19 |
20 |
21 | #define luaL_arg_check(cond,numarg,extramsg) if (!(cond)) \
22 | luaL_argerror(numarg,extramsg)
23 |
24 | void luaL_openlib (struct luaL_reg *l, int n);
25 | void luaL_argerror (int numarg, char *extramsg);
26 | #define luaL_check_string(n) (luaL_check_lstr((n), NULL))
27 | char *luaL_check_lstr (int numArg, long *len);
28 | #define luaL_opt_string(n, d) (luaL_opt_lstr((n), (d), NULL))
29 | char *luaL_opt_lstr (int numArg, char *def, long *len);
30 | double luaL_check_number (int numArg);
31 | #define luaL_check_int(n) ((int)luaL_check_number(n))
32 | #define luaL_check_long(n) ((long)luaL_check_number(n))
33 | double luaL_opt_number (int numArg, double def);
34 | #define luaL_opt_int(n,d) ((int)luaL_opt_number(n,d))
35 | #define luaL_opt_long(n,d) ((long)luaL_opt_number(n,d))
36 | lua_Object luaL_functionarg (int arg);
37 | lua_Object luaL_tablearg (int arg);
38 | lua_Object luaL_nonnullarg (int numArg);
39 | void luaL_verror (char *fmt, ...);
40 | char *luaL_openspace (int size);
41 | void luaL_resetbuffer (void);
42 | void luaL_addchar (int c);
43 | int luaL_getsize (void);
44 | void luaL_addsize (int n);
45 | int luaL_newbuffer (int size);
46 | void luaL_oldbuffer (int old);
47 | char *luaL_buffer (void);
48 | int luaL_findstring (char *name, char *list[]);
49 | void luaL_chunkid (char *out, char *source, int len);
50 | void luaL_filesource (char *out, char *filename, int len);
51 |
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/S4ModApi/lib/luadebug.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: luadebug.h,v 1.6 1999/03/04 21:17:26 roberto Exp $
3 | ** Debugging API
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #ifndef luadebug_h
9 | #define luadebug_h
10 |
11 |
12 | #include "lua.h"
13 |
14 | typedef lua_Object lua_Function;
15 |
16 | typedef void (*lua_LHFunction) (int line);
17 | typedef void (*lua_CHFunction) (lua_Function func, char *file, int line);
18 |
19 | lua_Function lua_stackedfunction (int level);
20 | void lua_funcinfo (lua_Object func, char **source, int *linedefined);
21 | int lua_currentline (lua_Function func);
22 | char *lua_getobjname (lua_Object o, char **name);
23 |
24 | lua_Object lua_getlocal (lua_Function func, int local_number, char **name);
25 | int lua_setlocal (lua_Function func, int local_number);
26 |
27 | int lua_nups (lua_Function func);
28 |
29 | lua_LHFunction lua_setlinehook (lua_LHFunction func);
30 | lua_CHFunction lua_setcallhook (lua_CHFunction func);
31 | int lua_setdebug (int debug);
32 |
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/S4ModApi/lib/lualib.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lualib.h,v 1.6 1999/05/05 19:23:11 roberto Exp $
3 | ** Lua standard libraries
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #ifndef lualib_h
9 | #define lualib_h
10 |
11 | #include "lua.h"
12 |
13 | void lua_iolibopen (void);
14 | void lua_strlibopen (void);
15 | void lua_mathlibopen (void);
16 | void lua_dblibopen (void);
17 |
18 |
19 | void lua_userinit (void);
20 |
21 |
22 | /* To keep compatibility with old versions */
23 |
24 | #define iolib_open lua_iolibopen
25 | #define strlib_open lua_strlibopen
26 | #define mathlib_open lua_mathlibopen
27 |
28 |
29 |
30 | /* Auxiliary functions (private) */
31 |
32 | char *luaI_classend (char *p);
33 | int luaI_singlematch (int c, char *p, char *ep);
34 |
35 | #endif
36 |
37 |
--------------------------------------------------------------------------------
/S4ModApi/md5.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #include "md5.h"
23 |
24 | #include
25 | #include
26 | #include "Log.h"
27 |
28 | #define BUFSIZE 1024
29 |
30 | SIZE_T MD5::ToString(LPSTR out, SIZE_T sz) {
31 | TRACE;
32 | CONST CHAR rgbDigits[] = "0123456789ABCDEF";
33 | auto to = min(sz, MD5LEN * 2);
34 | for (size_t i = 0; i < to; i++) {
35 | auto& b = bytes[i / 2]; // byte takes two characters
36 | out[i] = rgbDigits[(i % 2) ? (b & 0xF) : (b >> 4)];
37 | }
38 | if (to < sz) {
39 | out[to] = '\0';
40 | ++to;
41 | }
42 | return to;
43 | }
44 |
45 | #pragma warning(push)
46 | #pragma warning( disable : 4706 )
47 | HRESULT ComputeMD5(LPCWSTR filename, MD5* out) {
48 | TRACE;
49 | // This is basically just the sample from here:
50 | // https://docs.microsoft.com/de-de/windows/win32/seccrypto/example-c-program--creating-an-md-5-hash-from-file-content?redirectedfrom=MSDN
51 | // Note, you may change CALG_MD5 to CALG_SHA1 to get the SHA1 sum.
52 |
53 | DWORD dwStatus = 0;
54 | BOOL bResult = FALSE;
55 | HCRYPTPROV hProv = 0;
56 | HCRYPTHASH hHash = 0;
57 | HANDLE hFile = NULL;
58 | BYTE rgbFile[BUFSIZE];
59 | DWORD cbRead = 0;
60 | auto& rgbHash = out->bytes;
61 | DWORD cbHash = 0;
62 |
63 | hFile = CreateFileW(filename,
64 | GENERIC_READ,
65 | FILE_SHARE_READ,
66 | NULL,
67 | OPEN_EXISTING,
68 | FILE_FLAG_SEQUENTIAL_SCAN,
69 | NULL);
70 |
71 | if (INVALID_HANDLE_VALUE == hFile) {
72 | dwStatus = GetLastError();
73 | return dwStatus;
74 | }
75 |
76 | // Get handle to the crypto provider
77 | if (!CryptAcquireContext(&hProv,
78 | NULL,
79 | NULL,
80 | PROV_RSA_FULL,
81 | CRYPT_VERIFYCONTEXT)) {
82 | dwStatus = GetLastError();
83 | CloseHandle(hFile);
84 | return dwStatus;
85 | }
86 |
87 | if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
88 | dwStatus = GetLastError();
89 | CloseHandle(hFile);
90 | CryptReleaseContext(hProv, 0);
91 | return dwStatus;
92 | }
93 |
94 | while (bResult = ReadFile(hFile, rgbFile, BUFSIZE, &cbRead, NULL)) {
95 | if (0 == cbRead) {
96 | break;
97 | }
98 |
99 | if (!CryptHashData(hHash, rgbFile, cbRead, 0)) {
100 | dwStatus = GetLastError();
101 | CryptReleaseContext(hProv, 0);
102 | CryptDestroyHash(hHash);
103 | CloseHandle(hFile);
104 | return dwStatus;
105 | }
106 | }
107 | #pragma warning(pop)
108 |
109 | if (!bResult) {
110 | dwStatus = GetLastError();
111 | CryptReleaseContext(hProv, 0);
112 | CryptDestroyHash(hHash);
113 | CloseHandle(hFile);
114 | return dwStatus;
115 | }
116 |
117 | cbHash = MD5LEN;
118 | if (!CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) {
119 | dwStatus = GetLastError();
120 | }
121 |
122 | CryptDestroyHash(hHash);
123 | CryptReleaseContext(hProv, 0);
124 | CloseHandle(hFile);
125 |
126 | return dwStatus;
127 | }
--------------------------------------------------------------------------------
/S4ModApi/md5.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #define MD5LEN 16
25 |
26 | #include "Windows.h"
27 |
28 | struct MD5 {
29 | BYTE bytes[MD5LEN] = { 0 };
30 |
31 | SIZE_T ToString(LPSTR out, SIZE_T sz);
32 | };
33 |
34 | HRESULT ComputeMD5(LPCWSTR filename, MD5 *out);
35 |
--------------------------------------------------------------------------------
/S4ModApi/module.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #define WIN32_LEAN_AND_MEAN
23 | #include "windows.h"
24 | #include "Log.h"
25 |
26 | HMODULE g_hModule = NULL;
27 |
28 | HMODULE IncreaseModuleRefcount(LPCVOID target) {
29 | TRACE;
30 | HMODULE out;
31 | if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)target, &out)) {
32 | return out;
33 | }
34 | return NULL;
35 | }
36 |
37 | BOOL DecreaseModuleRefcount(HMODULE mod) {
38 | TRACE;
39 | return FreeLibrary(mod);
40 | }
--------------------------------------------------------------------------------
/S4ModApi/module.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include "windows.h"
25 |
26 | extern HMODULE g_hModule;
27 | HMODULE IncreaseModuleRefcount(LPCVOID target); // NULL on failure
28 | BOOL DecreaseModuleRefcount(HMODULE module); // true if successfull
29 |
--------------------------------------------------------------------------------
/S4ModApi/patterns.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #pragma once
23 |
24 | #include
25 |
26 | struct PatternAddr {
27 | void Scan(LPCSTR name, DWORD base, LPCSTR basename, LPCSTR patternStr);
28 |
29 | DWORD addr;
30 | DWORD base;
31 | LPCSTR name;
32 | LPCSTR basename;
33 |
34 | operator bool() const;
35 | operator DWORD() const;
36 | operator LPCVOID() const;
37 | DWORD operator+(int off);
38 | DWORD operator-(int off);
39 | };
40 |
41 | extern struct Patterns {
42 | // Debug Rendering Patterns
43 | PatternAddr
44 | OnMapInitHook,
45 | PillarboxWidth,
46 | OnFrameHook,
47 | Hwnd,
48 | Backbuffer,
49 | OnSettlerCommandHook,
50 | OnTickHook,
51 | OnMouseButtonHook,
52 | HoveringUiElement,
53 | MenuScreenObj,
54 | CurrentMenuScreen,
55 | GameMenusWndProc,
56 | WndProcChain,
57 | ActiveIngameMenu,
58 | SettlerFilter,
59 | ClearSelection,
60 | NetEventConstuctor,
61 | RecruitmentEventConstructor,
62 | LocalEvent,
63 | Lua,
64 | ShowTextMessage,
65 | OnLuaOpenHook,
66 | OnBltHook,
67 |
68 | BoxSelect,
69 | AltSelect,
70 | UnitsPerRightclick,
71 | SelectionMarkerBufferGetter,
72 | SelectionMarkerBufferSetter,
73 | HealthBubbleBufferGetter,
74 | HealthBubbleBufferSetter
75 | ;
76 |
77 | void Scan();
78 |
79 | Patterns() = default;
80 | private:
81 | Patterns(const Patterns&) = delete;
82 | Patterns& operator=(Patterns const&) = delete;
83 | } g_Patterns;
84 |
85 |
--------------------------------------------------------------------------------
/S4ModApi/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Von Microsoft Visual C++ generierte Includedatei.
3 | // Verwendet durch S4ModApi.rc
4 | //
5 |
6 | // Next default values for new objects
7 | //
8 | #ifdef APSTUDIO_INVOKED
9 | #ifndef APSTUDIO_READONLY_SYMBOLS
10 | #define _APS_NEXT_RESOURCE_VALUE 104
11 | #define _APS_NEXT_COMMAND_VALUE 40001
12 | #define _APS_NEXT_CONTROL_VALUE 1005
13 | #define _APS_NEXT_SYMED_VALUE 101
14 | #endif
15 | #endif
16 |
--------------------------------------------------------------------------------
/S4ModApi/safemem.cpp:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // GNU Lesser General Public License v3 (LGPL v3)
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // This file is part of S4ModApi.
7 | //
8 | // S4ModApi is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // S4ModApi is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with S4ModApi. If not, see .
20 | ///////////////////////////////////////////////////////////////////////////////
21 |
22 | #define WIN32_LEAN_AND_MEAN
23 | #include "Windows.h"
24 | #include "Log.h"
25 |
26 | extern "C" {
27 |
28 | void* __stdcall memget_s(void* dst, const void* src, size_t len) {
29 | #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__ ) // export undecorated
30 | #pragma comment(linker, "/EXPORT:" __FUNCDNAME__ ) // export stdcall decorated
31 | TRACE;
32 | DWORD read = 0;
33 | if (!ReadProcessMemory(GetCurrentProcess(), src, dst, len, &read) || read != len) {
34 | return NULL;
35 | }
36 | return dst;
37 | }
38 |
39 | void* __stdcall memset_s(void* dst, const void* src, size_t len) {
40 | #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__ ) // export undecorated
41 | #pragma comment(linker, "/EXPORT:" __FUNCDNAME__ ) // export stdcall decorated
42 | TRACE;
43 | DWORD writtn = 0;
44 | if (!WriteProcessMemory(GetCurrentProcess(), dst, src, len, &writtn) || writtn != len) {
45 | return NULL;
46 | }
47 | return dst;
48 | }
49 |
50 | DWORD __stdcall READ_AT(const void* src, int offset) {
51 | #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__ ) // export undecorated
52 | #pragma comment(linker, "/EXPORT:" __FUNCDNAME__ ) // export stdcall decorated
53 | TRACE;
54 | DWORD ret;
55 | if (src && ReadProcessMemory(GetCurrentProcess(), (LPCVOID)((DWORD)src + offset), &ret, sizeof(DWORD), NULL)) {
56 | return ret;
57 | }
58 | return 0;
59 | }
60 |
61 | BOOL __stdcall WRITE_AT(void* dst, DWORD val, int offset) {
62 | #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__ ) // export undecorated
63 | #pragma comment(linker, "/EXPORT:" __FUNCDNAME__ ) // export stdcall decorated
64 | TRACE;
65 | return (dst && WriteProcessMemory(GetCurrentProcess(), (LPVOID)((DWORD)dst + offset), &val, sizeof(DWORD), NULL));
66 | }
67 |
68 | }
--------------------------------------------------------------------------------
/S4ModApi/safemem.h:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | // MIT License
3 | //
4 | // Copyright (c) 2022 nyfrk and contributors
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 | ///////////////////////////////////////////////////////////////////////////////
24 |
25 | #pragma once
26 |
27 | #include "windef.h"
28 |
29 | extern "C" {
30 |
31 | /**
32 | * Read memory from source (safe read)
33 | **/
34 | void* __stdcall memget_s(void* dst, const void* src, size_t len);
35 |
36 | /**
37 | * Write memory at destination (safe write)
38 | **/
39 | void* __stdcall memset_s(void* dst, const void* src, size_t len);
40 |
41 | /**
42 | * Read a DWORD from memory or return 0 on failure. (Safe read)
43 | **/
44 | DWORD __stdcall READ_AT(const void* src, int offset = 0);
45 |
46 | /**
47 | * Write a DWORD to memory or return 0 on failure. (Safe write)
48 | **/
49 | BOOL __stdcall WRITE_AT(void* dst, DWORD val, int offset = 0);
50 |
51 | }
--------------------------------------------------------------------------------
/UpdateExamples.bat:
--------------------------------------------------------------------------------
1 | cd %0\..\Examples
2 |
3 | copy ..\Release\S4ModApi.lib HelloWorld\HelloWorld
4 | copy ..\S4ModApi\S4ModApi.h HelloWorld\HelloWorld
5 |
6 | copy ..\Release\S4ModApi.lib LuaExample\LuaExample
7 | copy ..\S4ModApi\S4ModApi.h LuaExample\LuaExample
8 |
9 | copy ..\Release\S4ModApi.lib HotkeysExample\HotkeysExample
10 | copy ..\S4ModApi\S4ModApi.h HotkeysExample\HotkeysExample
11 |
12 | copy ..\Release\S4ModApi.lib SelectionLimitExample\SelectionLimitExample
13 | copy ..\S4ModApi\S4ModApi.h SelectionLimitExample\SelectionLimitExample
14 |
15 |
--------------------------------------------------------------------------------
/VERSION.md:
--------------------------------------------------------------------------------
1 | # S4ModApi Versioning
2 |
3 | Every release gets from now on a fixed Application Binary Interface (ABI), meaning that mods linking against an older version will still be compatible even when a more recent S4ModApi.dll is used. The COM Pattern is used to ensure ABI compatibility. This allows players to update the S4ModApi.dll independently of their plugins. Plugins can be made compatible by updating S4ModApi.dll when new game versions are published - without having to recompile or even touching the source code of a plugin.
4 |
5 |
6 |
7 | ## Semantic Versioning
8 |
9 | S4ModApi now adopts a semantic versioning scheme (mayor.minor.patch). The digits are increased according to the following rules.
10 |
11 | * Mayor digit is increased when a new interface using a fresh UUID is added to the S4ModApi. The new interface may reorder, add, change or remove methods from the interface. Specification of methods may change. Interfaces requested using an older UUID will still get an appropriate interface.
12 |
13 | * Minor digit is increased when specification changes happen that do not break previous versions interfaces and no new UUID is required. That is the case when methods are just appended to the current interface or when all methods still adhere mostly to their previous specification. For example a specification change is acceptable if a previously reserved argument or method is now implemented. This is also the case for bug fixes (changing implementation to comply specification).
14 |
15 | * Patch digit is not used and is always 0. It is ignored by the auto update feature.
16 |
17 | Versions according to these rules may also be increased for changes to older interfaces. Lets say for example the current S4ModApi is in version 3.3. The change to 3.4 may change features that were initially implemented in version 2.0 (e.g. bug fixes). Plugins that were linked to version 2.0 may now enjoy the fixed behavior even though it was linked against the older version. Please note that at some point this will be difficult to maintain and we may thus decide at any point to not fix old bugs. Especially when we notice that plugins rely on these.
18 |
19 | Note: If your plugin was compiled against version 1.x or older you will have to recompile your plugin using a newer S4ModApi Version.
20 |
21 |
22 |
23 | ## ISettlers4Api Interface Versioning
24 |
25 | With every mayor version a new interface is created. These are indicated by the suffix to the interface name. For example ISettlers4Api3 is the interface requested by plugins that were compiled using S4ModApi 3.x.x. When recompiling your plugin using the latest S4ModApi, make sure to replace the old S4ModApi.h header file and the linking library S4ModApi.lib.
26 |
27 |
--------------------------------------------------------------------------------