My recommendation is that you do not change any C++ code in the sources and avoid changing core modules (like corelib, gamelib and game_interface). If you need any change then use new modules to add new functionality or overwrite the current modules. There is a system for overwriting modules, scripts and images using the "mods" directory, I will try to explain how to do this the correct way here.
Let me explain how the mods directory works, first run this command in otclient's terminal, you should get an output similar to mine:
> table.dump(g_resources.getSearchPaths())
1: /home/bart/coding/otclient/mods
2: /home/bart/coding/otclient/modules
3: /home/bart/coding/otclient/data
4: /home/bart/.otclient
Otclient search for any file in these paths, in order, first it tries to search in the first path, then the second and so on. For example, if I'm trying to load "/images/clienticon.png
it will look first in "/home/bart/coding/otclient/mods/images/clienticon.png", if the image is not found there, then in "/home/bart/coding/otclient/modules/images/clienticon.png", if the image is not found there neither, finally it will look in "/home/bart/coding/otclient/data/images/clienticon.png". What does this mean? That you can still change clienticon.png without touching the otclient's data or modules directory, and this also works for scripts, otuis or any file.
Knowing that, I will show four specific cases for customizing the client with examples.
First case, change a game module:
Let suppose that you want to change the inventory layout, because you do not need the standard tibia layout. To do that you would need to change "modules/game_inventory/inventory.otui", however you do not want to change that file directly, because you still need compatibility with latest otclient sources. So to do that corretly, you copy the file to "mods/game_inventory/inventory.otui", and then make your changes there. Because g_resources will look for "mods/game_inventory/inventory.otui" first, the standard otclient's file in "modules/game_inventory/inventory.otui" will be ignored. You can use the same ideia to change, battle, viplist, images, styles, etc.
Second case, add a new module:
Lets suppose that you want to create a new module for a new cool interface that interacts with your game. First you create the module inside mods directory, then configure autoloading in the module, to make it always load. If your need any protocol change you can use the extended opcode, there is patch for tfs sources inside tools directory to enable extended opcode in your server, alternatively you could use tfs trunk, because it is already patched.
Third case, change core functionality:
Changing core functionality would need to change the C++ source codes or lua modules that is dependency for many other modules that are used everywhere, you should avoid that because the otclient devs is frequently updating these codes and maintaining your own difference while keeping up to date would make your life much harder. In this case, first see if the scenario can fit the official otclient sources, if so try to contribute to our repository, then your changes will be inside otclient sources, making your life easier and would also help to make otclient more flexible. There are many codes already inside otclient that work this way, the g_game.enableFeature() is an example, where you can disable/enable features depending in the protocol, and there even extra features not used by tibia there, like changing the effects from U8 to U16.
Fourth case, change core functionality for experienced users who knows git:
So you need to change core functionality, but it doesn't fit otclient official sources. What you want to do is known as fork for git users, you will need to create a fork of the project as a git branch in your local git repository. I'm not going in many details but what you have to do is to clone the otclient sources, then create a branch for your project, commit your own changes in there, then whenever otclient is updated, you first use "git fetch" to download latest otclient source, then "git rebase" to rebase your changes in the latest otclient sources, this will reapply everything that you changed over the latest otclient code, alternatively you can use "git merge" if really changed a lot of codes. However I do not recommend this for anyone, unless you really know what you are doing, and you already master git.
In summary, try to keep all the changes inside "mods" directory, whenever you cannot maintain the changes there, contribute to the otclient project to improve its flexibility. A good project made with otclient would always work with the latest official otclient core modules and binary release, even if you do not compiled yourself. You should use just the lua API to make your whole client project.