Modding the Client


This tutorial will explain how to make create a DLL that changes the behaviour of the client. This will show how to work with MinGW64, but should work with Visual Studio or any other C compiler with a few changes to the Makefile. Even C++ or other languages might be possible.


The DLL will be called amod.dll ("a mod". Clever, right?). The part of the Makefile looks like this:

amod.dll:	amod.o
		$(CC) $(LDFLAGS) -shared -o amod.dll amod.o moac.a

amod.o:		amod.c amod.h

The important parts are "-shared" and "moac.a" in the second line. The first tells the linker to create a shared library (a DLL). The second adds a library of client functions you might need.


The source file containing the actual mod. This will be empty in the vanilla client. It is yours to fill. You can, of course, rename it or add more files in the Makefile.

#include <stdint.h>

#include "../../src/amod/amod.h"

__declspec(dllexport) void amod_gamestart(void) {
    note("A Mod by ModderMcModFace loaded.");

__declspec(dllexport) int trans_charno(int csprite,int *pscale,int *pcr,int *pcg,int *pcb,int *plight,int *psat,int *pc1,int *pc2,int *pc3,int *pshine,int attick)
    int scale=100;

    switch (csprite) {
        case 120:   csprite=8; scale=67; break; // tiny skelly
        default:    return _trans_charno(csprite,pscale,pcr,pcg,pcb,plight,psat,pc1,pc2,pc3,pshine,attick);

    if (pscale) *pscale=scale;

    return csprite;

Don't let the "__declspec(dllexport)" scare you. This tells the compiler that you want to export that function. Put it in front of every client function you want to override.

Here, we are overriding trans_charno() to create a small skeletton in slot 120. Please compare the original trans_charno() in sprite.c in the client.

One very important part is the call to _trans_charno(). This calls the original client function to take care of all the other sprites. Without it you would have to duplicate the whole function, and merge any future changes. You can replace functions completely, too, and in some cases you will want to do that.

The underscore in front of _trans_charno() is very important. It makes the call go to the original function instead of your override. Leave it out and the client will crash.

amod_init() and amod_exit() are called during client startup and client shutdown. Use the former to initialize your mod and the latter to save anything you need to save.

There are also amod_gamestart() which is called after the client has finished startup and is about to enter the game loop.

And amod_tick() and amod_frame(). These are called everytime a game tick has been processed and every time a frame is about to be rendered.

So far I have made the functions in sprite.c mod-able, since almost every mod will want to add sprites. Let me know which other functions you want to override (see amod.h for the current state).

Functions that can be modded can also just be called from the mod. But you will need to add the underscore mentioned above. Linking will fail if you don't.

The client exports a few other functions the mod can call. These are currently the message family (note, warn, fail, ...). Once again, see amod.h for a definite list and let me know what else you need.

Well, that's all folks. Comments and suggestions are welcome. If you could not follow the tutorial at any specific point, I'd like to know!