Four separate programs, one shipped library. What actually differs between them isn't how they're built — it's how much of that one library they bother to touch.
libFacade/Facade.cpp is nine lines and a comment. It's also the literal, physical reason the AI region of the Systems Map can say “no dynamic loading” and mean it.
The file's own comment says the whole thing: “vcmiFacade is an aggregator shared library that bundles vcmiCore with every AI implementation and the Lua scripting backend. It carries no code of its own — this translation unit exists only because CMake requires every library target to have at least one source file.” vcmiMain, vcmiLua, and every enabled AI (EmptyAI, Nullkiller2, StupidAI, BattleAI, MMAI when built) are CMake OBJECT libraries — not archives some other target later selects from, but loose object files that get folded wholesale into one target, vcmi (SHARED on desktop, STATIC on mobile). libFacade/CMakeLists.txt links every one of them PRIVATE, and says exactly why in a comment: PRIVATE keeps CMake from re-propagating those object files onto whatever links vcmi afterward, which would otherwise duplicate every symbol into every consumer.
Every tool in this belt links vcmi. What they actually #include from it tells a different story for each one — confirmed by grepping their real includes, not guessed from folder names.
never touches game logic
Every lib/ header vcmilauncher actually includes is infrastructure: CConfigHandler, VCMIDirs, filesystem/Filesystem.h, logging/CBasicLogConfigurator.h, texts/Languages.h. Nothing about CGameState, battle, or maps. It downloads and installs mods, edits settings, picks a language, and launches the real client/server processes — it needs the engine's config and archive-reading code, and stops there.
the direct UI on top of two earlier docs
vcmieditor includes mapping/CMap.h, CMapEditManager.h, CMapService.h, MapFormatJson.h, and rmg/CMapGenerator.h/CRmgTemplate.h directly. This is a UI wrapped straight around the exact undo-stack and save/load mechanics Map Formats already traced, and the exact generator the Random Map Generator doc already traced — nothing new to explain here, just the confirmation that it's the same code, not a reimplementation.
the same protocol, plus a second channel
vcmilobby's includes are JsonNode, filesystem, logging, VCMIDirs, and — concretely — network/NetworkDefines.h. LobbyServer is the actual TCP/JSON gameplay-protocol server Wire Protocol already described, right down to the same message names (receiveClientLogin, receiveJoinGameRoom, the proxy handlers). LobbyHttpApi is something else entirely: a small read-only REST API (getApiStats, getApiChats, getApiRooms, each cached 30 seconds) serving the web/ front-end alongside it — a second channel into the same LobbyDatabase, not a second implementation of the same protocol.
Three earlier docs called into this without showing what they were calling into. Battle System's damage calculator, Spell System's effect scripts, and Map Formats' HotA decompiler are all the same registry, three different ways in.
Every script is exactly one of three ScriptKinds (lib/scripting/ScriptTypeDescription.h): DAMAGE_CALCULATOR, SPELL_EFFECT, COMBAT_EVENT. A ScriptTypeDescription holds one script's identity (scriptId, its ordered patches, a priority for same-event ordering) regardless of which kind it is — kinds share one entity type and simply ignore the fields they have no use for. ScriptHandler, a config-loading handler exactly like every other entity handler this atlas has met, loads these from JSON the ordinary way (loadObject()) and holds one registered IScriptFactory. LuaScriptFactory is the only factory that exists: given a script id, it hands back whichever concrete interface the requesting code asked for — createDamageCalculatorScript(), createSpellEffect(), createCombatEventScript() — all backed by the same loaded LuaScriptInstance.
One more piece none of the earlier docs needed: LuaScriptPool, owned by CGameState, hands out a LuaContext — a real Lua VM state — per script per thread, via tbb::enumerable_thread_specific, created lazily on each thread's first use and never locked. Its own header comment states the price of that concurrency plainly: scripts must be stateless, taking their configuration as a per-call argument rather than accumulating anything in a global or in their own table, because two threads may be running the same script's separate VM state at the same instant. The damage calculator that Battle System found with no C++ fallback, and the spell effects Spell System found the same way — every one of them runs under exactly this constraint.