# Custom Files

This is a mod requirable hack that must be required by a mod to be enabled.

This hack allows mods to provide custom files without modifying the game install.

It also allows mods to handle the game requesting files with Lua scripts which allows for a number of powerful features.

# Requiring This Hack

To require this hack, add this line to your mod's Meta.ini:

RequiredHack=CustomFiles


Your mod must provide one of the following things when requiring this hack:

• CustomFiles.ini
• CustomFiles.lua
• A CustomFiles folder.
• An AdditionalFiles folder.

# Configuring This Hack

To configure this hack, create a file named CustomFiles.ini and add the parameters necessary for your mod inside it.

[Miscellaneous]
; OccludedPath
; 	Occlude a file from the game's view, this will make the game think it doesn't exist. Be careful with this.
; 	Repeatable to occlude multiple files.
OccludedPath=path\\to\\file.p3d

; ReadOnly
; 	Prevents the game from writing to a file, but it can still read it.
; 	Repeatable to make multiple files read only.
ReadOnly=path\\to\\file.p3d

; SuppressedPath
; 	Tries to prevent the game from loading a file.
; 	Repeatable to suppress multiple files.
SuppressedPath=path\\to\\file.p3d

[PathRedirections]

; PATH_TO_FILE
; 	Redirect the file on the left to the path on the right.
;	Repeatable to redirect multiple files.
art\\frontend\\dynaload\\images\\license\\*.p3d=art\\license\\license.p3d

[PathHandlers]
; PATH_TO_FILE
; 	Specify a file path that, when requested, will cause a Lua Path Handler script to be executed.
; 	Repeatable to handle multiple files.
art\\cars\\family_v.p3d=Resources/scripts/handlers/famil_v.lua

[AdditionalFiles]
; PATH_TO_FILE
; 	Specify a file on the right that will also be loaded when the left file is loaded.
;	Repeatable for the same base file or for any number of different files.
art\\cars\\famil_v.p3d=art\\cars\\famil_vH.p3d


* Wildcard can be used in a path to indicate anything of any length. ? Wildcard can be used in a path to indicate anything of a set length.

# Folders

## CustomFiles

The main folder for this hack is one called "CustomFiles". This folder allows mods to override files in the base game.

For example, a mod with a custom version of the Family Sedan at the path CustomFiles\art\cars\famil_v.p3d will override the game's original model for it.

## AdditionalFiles

Mods can also use a folder named "AdditionalFiles" is similar to "CustomFiles" but instead of overriding the files, it makes the game load the original file and the custom file.

This functionality can break the game in a number of cases such as when it is used on a sound script (.spt).

## Resources

Lastly, mods that use this hack's Lua Scripting are expected to use a folder named "Resources" for any Lua scripts (besides CustomFiles.lua) and any other files that are exclusively redirected to or read by Lua scripts.

# Lua Scripting

For more detailed information, see Lua Scripting.

# Version History

## 1.26

Fixed a buffer overflow when reading the header of some Bink files when playing them that could cause memory corruption and lead to a crash.

## 1.25

### General

• Fixed an assert when attempting to enable Data Execution Prevention in a couple cases:
• When the SetProcessDEPPolicy API is not implemented (such as when running in Wine).
• When the system DEP policy is set to "AlwaysOff" or "AlwaysOn".

### Lua Scripting

Added the GetGameLanguage function. This allows you to check what language version of the game the user is playing.

## 1.24

### General

• Added an [AdditionalFiles] section to the hack's configuration file.
• This allows you to define any number of additional files to be loaded when a particular file is requested.
• This is useful for the new husk features of Custom Car Support, allowing you to keep a car specific husk model separate and have it get loaded alongside the regular car model.

### Lua Scripting

• Fixed a memory leak when Lua failed to allocate memory to return the result of a call to the ReadFile function.
• Fixed a major issue where Lua functions that are only supposed to work when handling a path (Output, Redirect, GetPath, IsWriting and UseCallbacks) could be called in a UseCallbacks callback but would not work properly. Now they cannot be called in this case.
• Added the ReadFileOffset function. This allows you to read part of a file.

## 1.23.12

### General

Fixed a bug where Data Execution Prevention was enabled on executables that don't support it.

### Lua Scripting

• Removed the "interval too large" check from the math.random function.
• Previously, the range could not be more than 9,223,372,036,854,775,807 (the value of math.maxinteger).
• This limitation no longer applies to this implementation of math.random so this check has been removed.
• Made math.randomseed not get the argument as a double precision floating point and cast it to a 64-bit integer.

## 1.23.10

### General

• Made this hack enable Data Execution Prevention if any mods provide custom files, path redirections, path handlers or an AdditionalFiles folder.
• Also added the -noenabledep command line argument to opt out of this.

### Lua Scripting

• Made the math.random function use a 64-bit Mersenne Twister 19937 random number generator initially seeded (at load time) with a cryptographically secure random number instead of just using a cryptographically secure random number.
• Added the math.randomseed function. This allows you to set the seed on a sandboxed, per-mod, basis.
• See this page for more details on this function.
• Fixed an issue where the GetSetting and GetSettings functions read the low 32-bits of the 64-bit signed integer setting values as unsigned and casted that to a 64-bit signed integer to give it to Lua. This caused negative integer setting values to wrap as if they were 32-bit unsigned values.
• If you'd like, you can use something like if SettingValue > 2147483647 then SettingValue = SettingValue - 4294967296 end to support old versions of the Mod Launcher.
• Fixed a bug where coroutine.isyieldable wasn't allowed.
• Removed functions from the global table that don't get copied into mod environments as is.
• Fixed a bug where calling DirectoryGetEntries on / yielded no results (when not using the -legacyfilesystem command line argument).
• Added the GetShared function. This returns a table that is shared by all mods.
• Added the Pause function. This will pause the console and prompt the user to "Press any key to continue...".
• If the Console feature of the Console and Logging hack is not enabled, a console window will still be shown temporarily to prompt the user.
• Added the IsDemo function. This returns true when the user is playing the Demo version of the game.

## 1.23.9

• Improved efficency of the Output Lua function for path handlers, particularly when calling it multiple times.
• Also added a -legacyoutput command line argument to opt out of this change.
• Also added the IsLegacyOutput Lua function to detect if that argument is in use.

## 1.23.8

• Made it so the start of Lua file names are truncated instead of the end.
• Also added -notruncateluafilenamestart to opt out of this change.
• Made various improvements to Lua execution errors.
• They now include the title of the mod that executed the script.
• They now include a stack trace.
• Also added -noluastacktrace to opt out of this addition.
• They now get logged to the log files (when "Logging" is enabled in the "Console and Logging" hack).
• Made various improvements to Lua load errors.
• They now include the title of the mod that loaded the script.
• They now get logged to the log files (when "Logging" is enabled in the "Console and Logging" hack).

## 1.19

### General

• Made CustomFiles.lua execute after all hacks that are supposed to be loaded are loaded.
• Made this hack only mount "CustomFiles" folders that exist.
• This change can dramatically improve performance if you have lots of mods enabled but only a few have CustomFiles folders (like Mod Hacks for instance).

### Lua Scripting

• Added GetLauncherVersion. This returns the current version of the Mod Launcher.
• Added GetMainMod. This returns the InternalName of the current main mod (if there is one).
• Added GetSettings. This returns the settings of the current mod (or the specified mod) in a Lua table.
• Added IsTesting. This checks if the user is has the Mod Launcher's testing mode enabled.
• Added UseCallbacks. This is an advanced function for handling files with Lua that may or may not have a use case.
• Fixed an issue where "ComparePaths" was always case sensitive and always slash sensitive.

## 1.13.2

### General

Fixed a crash when redirecting files loaded by frontend pages.

## 1.13

### Lua Scripting

• Added several previously inaccessible Lua provided functions.
• assert
• collectgarbage
• debug.debug
• debug.gethook
• debug.getlocal
• debug.getmetatable
• debug.getregistry
• debug.getupvalue
• debug.getuservalue
• debug.sethook
• debug.setlocal
• debug.setmetatable
• debug.setupvalue
• debug.setuservalue
• debug.upvaluejoin
• getmetatable
• math.maxinteger
• math.mininteger
• math.tointeger
• math.type
• math.ult
• os.setlocale
• rawequal
• rawget
• rawlen
• rawset
• setmetatable
• string.dump
• string.pack
• string.packsize
• string.unpack
• table.concat
• table.move
• table.pack
• Fixed a bug where IsModEnabled returned false for mod hacks.
• Made GetSetting return nil instead of throwing an error if a setting doesn't exist. Mod creators should do checks for nil on UncompiledOnly settings.
• Updated math.random to support integers.

## 1.12.1

### Lua Scripting

Fixed a bug where using GetSetting on an Integer type Number setting would return a number.

## 1.12

### General

Added various Console output messages.

### Lua Scripting

• Now uses the Lua Support hack.
• This means this version effectively upgrades from Lua 5.2.3 to 5.3.1.
• This change also removes the following functions:
• math.atan2
• math.cosh
• math.frexp
• math.ldexp
• math.log10
• math.pow
• math.sinh
• math.tanh
• table.maxn
• This also makes the utf8 library available.
• Made the coroutine library available.
• Removed support for compiled Lua files.

Added this hack.