Skip to content
nyfrk edited this page Aug 29, 2020 · 2 revisions

In this article I will give you step by step instructions on how to create your first plugin for The Settlers 4 using the S4ModApi Library.

The goal of the Hello World Plugin is to display a hello world popup in the main menu of the game. You can also download the project files here.

IDE Setup

  1. Choose and download a Version of Visual Studio from here. If you need help installing it, follow these instructions.

  2. Choose the following Workloads during installation: Desktop development with C++

This will install the latest MSVC Buildtools for x64/x86 development which is v142.

Project Configuration

  1. Open Visual Studio 2019 and create a new project.

  2. Choose the Dynamic Link Library (DLL) C++ template.

  3. When your project is opened select in the top menu Project and click HelloWorld properties.

  4. In the Configuration properties select Advanced and change the Target File Extension from .dll to .asi

  5. Download a release of the S4ModApi Library.

  6. Unpack the S4ModApi.lib and all the headers to C:/Users/[USERNAME]/source/repos/HelloWorld/HelloWorld. That is the directory that also contains your dllmain.cpp file. You can save the files to a dedicated directory. However for the sake of simplicity we will install the library directly to the project source.

To use the S4ModApi add the following lines to your source files:

#include "S4ModApi.h"
#pragma comment(lib, "S4ModApi")

Now you have the library installed and can start creating your plugin.

The plugin

Replace the contents of your dllmain.cpp with the following code.

#include "pch.h"

#include "S4ModApi.h"
#pragma comment(lib, "S4ModApi")

static S4API s4; // the interface to the Settlers 4 Mod API
static LPCVOID splashHandle; // the handle to the splash image

static void CleanUp() {
    if (NULL != splashHandle) {
        s4->DestroyCustomUiElement(splashHandle);
        splashHandle = NULL;
    }
    if (NULL != s4) {
        s4->Release();
        s4 = NULL;
    }
};

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved ) {    
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH: {
        s4 = S4ApiCreate(); // get an interface to the mod api
        if (NULL == s4) break;

        WCHAR imgFn[MAX_PATH]; // the filename of the splash image
        INT filenameLen = GetModuleFileNameW(hModule, imgFn, _countof(imgFn))
            - 4; // subtract 4 to remove the .asi file ending
        if (filenameLen <= 0) break;

        // append \splash.bmp to the filename of the module
        wcscpy_s(&imgFn[filenameLen], _countof(imgFn) - filenameLen, L"\\splash.bmp");

        S4CustomUiElement cuie = { 0 };
        cuie.size = sizeof(cuie);
        cuie.szImg = imgFn;
        cuie.x = 50;
        cuie.y = 50;
        cuie.screen = S4_SCREEN_MAINMENU;
        cuie.actionHandler = [](LPCVOID lpUiElement, S4_CUSTOM_UI_ENUM newstate) {
            if (newstate & S4_CUSTOM_UI_SELECTED) {
                CleanUp();
            }
            return (HRESULT)0;
        };
 
        splashHandle = s4->CreateCustomUiElement(&cuie);
        break;
    } 
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        CleanUp();
        break;
    }
    return TRUE;
}

This will create an API interface when the plugin gets attached by an ASI Loader. If the interface creation was successful, we load the filename of the ASI module and append \splash.bmp to it. This will be the splash image. We populate a S4CustomUiElement structure to use for the ISettlers4Api::CreateCustomUiElement method. We make sure that the ui element is only visible to the main screen by assigning S4_SCREEN_MAINMENU to the screen member. The action handler will simply destroy the splash image. That means it vanishes if the user clicks on it.

When the plugin gets detached we will free all resources.

Installation of the plugin

Make sure that you have an ASI Loader installed for your installation of The Settlers 4. If you do not yet have one, use nyfrk's ASI Loader. Move your helloworld.asi to your plugins directory. Inside the plugins directory create another directory and name it helloworld. Place the splash.bmp into it. Make sure that you also place the S4ModApi.dll that comes with the release of the library next to your S4_Main.exe.

Your folder structure should look like this:

plugins\
    helloworld.asi
    helloworld\
        splash.bmp
S4_Main.exe
S4ModApi.dll

Requirements

Minimum API Level 1
Target Edition Any
Header S4ModApi.h
Library S4ModApi.lib
DLL S4ModApi.dll

See also

ISettlers4Api

ISettlers4Api::CreateCustomUiElement

Clone this wiki locally