Skip to main content

Beginner BLT modding

This guide will be a full tutorial on how to make your first BLT mod with a suitable example to follow along.

The example mod will hide all jobs from Crime.Net which are not stealthable.


Every mod needs this file. This file is responsible for loading your mod with BLT. Below you will find the mod.txt used for this example which can serve as a template as well. Most of the fields should be self explanatory expect for the hooks.

	"name": "Hide loud jobs",
	"description": "Hides jobs from which are not stealthable",
	"author": "Your name",
	"version": "1.0",
	"blt_version": 2,
	"hooks": [
			"hook_id": "lib/managers/crimenetmanager",
			"script_path": "mod.lua"


If you followed the guide in the "Introduction" you should have the codebase available. There's no magic trick to finding the right function. It takes practice and understanding of the codebase. For this example I was specifically looking for crimenet which brought me directly to the CrimeNetManager. I knew that stealth is mostly referred to ghost so I quickly picked up on the idea of the ghost_icon which was used in the function _create_job_gui but that one is interal and gets called through the more accessible function add_server_job. Now I only had to go back to the ghost_icon to figure out how the game determined if it should display it or not.

Hooks in mod.txt

  • hook_id is the path to the file (from the original codebase) in which the function is defined which we want to manipulate.
  • script_path is the path to the file in your mods folder where your code is in.


[Hard Overwrite]

  • PRO: You are in full control by modifying the original source code
  • CON: Only 1 mod installed can hard-overwrite the function. All other mods manipulating the same function will not work.
function CrimeNetGui:add_server_job(data)
	if data.job_id and managers.job:is_job_ghostable(data.job_id) then
		local gui_data = self:_create_job_gui(data, "server")
		gui_data.server = true
		gui_data.host_name = data.host_name
		self._jobs[] = gui_data

This method is the most straightforward: It is the exact copy from the source code just with the if-statement wrapped around it. Only if the job is stealthable we actually want to add it to the browser.

[Soft Overwrite]

Not recommended.
  • PRO: better compability than the previous method
  • CON: Functions and possibly bad performance.
local old_add_server_job = CrimeNetGui.add_server_job

function CrimeNetGui:add_server_job(data)
	if data.job_id and managers.job:is_job_ghostable(data.job_id) then
		old_add_server_job(self, data)

This method


  • PRO: The original function stays completely untouched.
  • CON: Does not work for functions which return values. We will cover techniques to circumvent these issues in the "Advanced BLT modding".
Hooks:PostHook(CrimeNetGui, 'add_server_job', 'hideloudjobs_crimenetgui',
function(self, data)
	if data.job_id and not managers.job:is_job_ghostable(data.job_id) then
		self:remove_job(, true)