The immersion of the game is not only supported by the graphics but also by an appealing sound design. It is therefore possible to specify a large number of sound effects in Transport Fever 3.
All sound files used by Transport Fever 3 adhere to the following technical requirements:
.wav. The sound files may either be referenced in soundsets (mostly for vehicles) or in other resources described below:
For build and demolition sounds of constructions and terraforming, there are .builder_audio.lua resources. They contain references to the relevant subsets of sound effects:
function data() return { noMoney = "build/no_money.wav", build = "build/construction/large.wav", dragStart = "build/street/drag_start.wav", drag = { "build/street/drag_1.wav", "build/street/drag_2.wav", "build/street/drag_3.wav", "build/street/drag_4.wav", "build/street/drag_5.wav", }, dragBridge = { "build/street/drag_bridge_1.wav", "build/street/drag_bridge_2.wav", "build/street/drag_bridge_3.wav", }, dragTunnel = { "build/street/drag_tunnel_1.wav", "build/street/drag_tunnel_2.wav", "build/street/drag_tunnel_3.wav", }, dragEnd = "build/street/drag_end.wav", dragOffset = -0.2, bulldoze = "bulldoze/construction/small.wav", terraform = "terraform/smooth.wav", } end
The keys for bulldozing and construction effects are:
noMoney is played when a construction can't be constructed due to a lack of money.build is played when a construction is built.dragStart is played when the player starts dragging a street/track (mouse down).drag contains a list of effects from which some are randomly played while the player drags the street.dragBridge contains a list of effects from which some are randomly played while a street/track is dragged as a bridge.dragTunnel contains a list of effects from which some are randomly played while a street/track is dragged as a tunnel.dragEnd is played when the dragging is done (mouse release).dragOffset is an offset between the playback of dragging sounds. If negative, they slightly overlap.bulldoze is played if an element is demolished.terrain is played while the terrain is modified.
The builder_audio.lua files are referenced in different kinds of resources. Constructions, rocks and trees reference them as a property in the soundConfig:
soundConfig = { effects = { select = { "sound/selected_rail_depot.wav" } }, builderAudioRes = "::/gui/construction/sound/buildoze_construction_large.builder_audio", },
For modules, templates, edge addons, streets and tracks the builderAudioRes property is directly on their top level.
Script tools may provide the property as part of the ConstructionDefinition.
The general sound effects are defined in .gres.lua resources.
To define sound effects, .gres.lua files are used:
local sfx = {} sfx.LevelUp = { resolve("/game_mechanics/towns/sound/level_up_0.wav"), resolve("/game_mechanics/towns/sound/level_up_1.wav"), resolve("/game_mechanics/towns/sound/level_up_2.wav"), } sfx.Select = { resolve("/game_mechanics/towns/sound/select.wav") } function data() return { type = "gui_res", data = sfx, } end
The type is set to gui_res and data contains a table with keys and lists of .wav files.
To use the defined sound resources in the script and retrieve a sound file reference, the following code is used:
local companySFX = api.gui.genericRep.get(api.gui.genericRep.find("::/game_mechanics/company/sound/company_sfx.gres")).data as CompanySFX local sound : ResName if companySFX and companySFX.LevelUp and #companySFX.LevelUp > 0 then sound = companySFX.LevelUp[math.random(1, #companySFX.LevelUp)] end
To overwrite sound effects defined in .gres.lua files, it is possible to define another .gres.lua file with the following content:
function data() return { type = "gui_res_overwrite", data = { overwriteScript = { fileName = "sound_overwrite.script@overwrite", params = {}, }, }, } end
The type is set to gui_res_overwrite and the referenced script file contains
local data : OverwriteGuiRes = {} data.overwrite = function(_params : table) local soundRes = api.gui.genericRep.get(api.gui.genericRep.find("::/game_mechanics/company/sound/company_sfx.gres")) local companySounds = soundRes.data -- overwrite values companySounds.Select = { resolve("better_town_select.wav") } -- ... -- save values soundRes:setData(companySounds as table) end return data
The script does the following:
api.gui.genericRep.get(). setData.