locomotives.lua 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. local S = dlxtrains_diesel_locomotives.S
  2. local use_attachment_patch = advtrains_attachment_offset_patch and advtrains_attachment_offset_patch.setup_advtrains_wagon
  3. local mod_name = "dlxtrains_diesel_locomotives"
  4. dlxtrains.register_mod(mod_name)
  5. -- ////////////////////////////////////////////////////////////////////////////////////
  6. local livery_type1_unit_number_info = {
  7. [0] = { {x = 205, y = 117, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#848C8B", color2 = "#787B78"}, },
  8. [1] = { {x = 133, y = 133, spacing = 5, justify = 0, digit_width = 9, digit_height = 14, font_id = 2, color1 = "#938731", color2 = "#948839"},
  9. {x = 281, y = 133, spacing = 5, justify = 2, digit_width = 9, digit_height = 14, font_id = 2, color1 = "#938731", color2 = "#948839"}, },
  10. [2] = { {x = 356, y = 19, spacing = 1, justify = 2, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#C3C3C3", color2 = "#B9B8B8"}, },
  11. [3] = { {x = 205, y = 103, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#2A2A2A", color2 = "#474443"}, },
  12. }
  13. local livery_type2_unit_number_info = {
  14. [0] = { {x = 278, y = 80, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#C3C3C3", color2 = "#B9B8B8"},
  15. {x = 356, y = 80, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#C3C3C3", color2 = "#B9B8B8"}, },
  16. [1] = { {x = 48, y = 114, spacing = 3, justify = 0, digit_width = 7, digit_height = 10, font_id = 3, color1 = "#938731", color2 = "#948839"},
  17. {x = 47, y = 59, spacing = 3, justify = 2, digit_width = 7, digit_height = 10, font_id = 3, color1 = "#938731", color2 = "#948839"}, },
  18. [2] = { {x = 277, y = 83, spacing = 1, justify = 1, digit_width = 4, digit_height = 7, font_id = 5, color1 = "#C3C3C3", color2 = "#B9B8B8"},
  19. {x = 354, y = 83, spacing = 1, justify = 1, digit_width = 4, digit_height = 7, font_id = 5, color1 = "#C3C3C3", color2 = "#B9B8B8"}, },
  20. [3] = { {x = 277, y = 81, spacing = 1, justify = 1, digit_width = 4, digit_height = 7, font_id = 5, color1 = "#C3C3C3", color2 = "#B9B8B8"},
  21. {x = 354, y = 81, spacing = 1, justify = 1, digit_width = 4, digit_height = 7, font_id = 5, color1 = "#C3C3C3", color2 = "#B9B8B8"}, },
  22. }
  23. local livery_type3_unit_number_info = {
  24. [0] = { {x = 192, y = 17, spacing = 1, justify = 2, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#636363", color2 = "#595858"},
  25. {x = 248, y = 100, spacing = 1, justify = 0, digit_width = 2, digit_height = 2, font_id = 4, color1 = "#C3C3C3", color2 = "#B9B8B8"},
  26. {x = 295, y = 100, spacing = 1, justify = 0, digit_width = 2, digit_height = 2, font_id = 4, color1 = "#C3C3C3", color2 = "#B9B8B8"}, },
  27. [1] = { {x = 83, y = 130, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#938731", color2 = "#9E913B"},
  28. {x = 126, y = 175, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#938731", color2 = "#9E913B"}, },
  29. [2] = { {x = 83, y = 137, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#848C8B", color2 = "#787B78"},
  30. {x = 126, y = 182, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#848C8B", color2 = "#787B78"}, },
  31. [3] = { {x = 192, y = 122, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#2A2A2A", color2 = "#474443"},
  32. {x = 192, y = 167, spacing = 1, justify = 1, digit_width = 3, digit_height = 5, font_id = 1, color1 = "#2A2A2A", color2 = "#474443"}, },
  33. }
  34. local function GetDigitOverlay(livery_unit_number_info, x, d, alt_scheme)
  35. local digit_font_name = "dlxtrains_diesel_locomotives_font"..livery_unit_number_info.font_id.."_digit_"
  36. -- Colorize the digit based on the age appearance of the locomotive.
  37. local color = livery_unit_number_info.color1
  38. if alt_scheme then color = livery_unit_number_info.color2 end
  39. return ":"..x..","..livery_unit_number_info.y
  40. .."="..digit_font_name..d
  41. ..".png\\^\\[resize\\:"
  42. ..livery_unit_number_info.digit_width.."x"
  43. ..livery_unit_number_info.digit_height
  44. .."\\^\\[colorize\\:"..color.."\\:255"
  45. end
  46. local function Get_unit_number_overlays(livery_unit_number_info, wagon_number, unit_number, alt_scheme)
  47. -- Assumes the given wagon_number is a string representation of a positive whole number, possibly
  48. -- with leading zeros, < 1000 and that unit_number is the integer value of that number. Leading
  49. -- spaces will be converted into leading zeros.
  50. -- Determine value of each digit
  51. local d1 = math.floor(unit_number / 100)
  52. local d2 = math.floor((unit_number - (d1 * 100)) / 10)
  53. local d3 = math.floor(unit_number - (d1 * 100 + d2 * 10))
  54. local overlays = ""
  55. local digit_count = #wagon_number -- Use length of wagon_number string to allow for leading zeros
  56. if digit_count > 3 then digit_count = 3 end
  57. for i, unit_number_info in pairs(livery_unit_number_info) do
  58. local increment = unit_number_info.digit_width + unit_number_info.spacing
  59. -- Determine the starting x position of the first digit overlay based on the value of
  60. -- unit_number_info.justify: 1 == Centered, 2 = Right justify, anything else == Left justify
  61. local pos_offset = 0
  62. if unit_number_info.justify == 1 then
  63. if digit_count == 1 then
  64. pos_offset = increment
  65. elseif digit_count == 2 then
  66. pos_offset = increment / 2
  67. end
  68. elseif unit_number_info.justify == 2 then
  69. if digit_count == 1 then
  70. pos_offset = increment * 2
  71. elseif digit_count == 2 then
  72. pos_offset = increment
  73. end
  74. end
  75. -- Calculate the x position of each digit
  76. local x1 = unit_number_info.x + pos_offset
  77. local x2 = x1 + increment
  78. local x3 = x2 + increment
  79. -- Get the digit overlays
  80. if digit_count == 3 then
  81. overlays = overlays
  82. ..GetDigitOverlay(unit_number_info, x1, d1, alt_scheme)
  83. ..GetDigitOverlay(unit_number_info, x2, d2, alt_scheme)
  84. ..GetDigitOverlay(unit_number_info, x3, d3, alt_scheme)
  85. elseif digit_count == 2 then
  86. overlays = overlays
  87. ..GetDigitOverlay(unit_number_info, x1, d2, alt_scheme)
  88. ..GetDigitOverlay(unit_number_info, x2, d3, alt_scheme)
  89. else
  90. overlays = overlays
  91. ..GetDigitOverlay(unit_number_info, x1, d3, alt_scheme)
  92. end
  93. end
  94. return overlays
  95. end
  96. local livery_scheme_diesel_locomotive_type1 = {
  97. filename_prefix = "dlxtrains_diesel_locomotives_locomotive_type1",
  98. [0]={code="wf"},
  99. [1]={code="t"},
  100. [2]={code="dz"},
  101. [3]={code="zr"},
  102. count = 4,
  103. on_update_texture = function(wagon, data, texture)
  104. local new_texture = texture
  105. if texture ~= nil then
  106. local overlays = nil
  107. -- Update lights
  108. local white_light = "dlxtrains_diesel_locomotives_white_light.png\\^\\[resize\\:10x10"
  109. local red_light = "dlxtrains_diesel_locomotives_red_light.png\\^\\[resize\\:10x10"
  110. if data.light_config == 1 then
  111. -- Short hood end of locomotive is moving forward
  112. overlays = (overlays or "")..":363,161="..white_light..":374,172="..red_light
  113. elseif data.light_config == 2 then
  114. -- Long hood end of locomotive is moving forward
  115. overlays = (overlays or "")..":374,161="..white_light..":363,172="..red_light
  116. end
  117. -- Update cooling fans
  118. if data.light_config == 1 or data.light_config == 2 then
  119. -- Show cooling fan in spinning state
  120. overlays = (overlays or "")..":270,85=".."dlxtrains_diesel_locomotives_spinning_fan.png\\^\\[resize\\:17x17"
  121. end
  122. -- Update unit number
  123. local wagon_number = data.roadnumber
  124. local unit_number = tonumber(wagon_number)
  125. if unit_number ~= nil and unit_number >= 0 and unit_number < 1000 and string.find(wagon_number, "[,%.]") == nil then
  126. overlays = (overlays or "")..Get_unit_number_overlays(livery_type1_unit_number_info[data.scheme_id or 0], wagon_number, unit_number, data.alt_scheme)
  127. end
  128. -- Update the texture if any overlays were created
  129. if overlays ~= nil then
  130. new_texture = "[combine:384x384:0,0=("..texture..")"..overlays
  131. end
  132. end
  133. return new_texture
  134. end,
  135. }
  136. local livery_scheme_diesel_locomotive_type2 = {
  137. filename_prefix = "dlxtrains_diesel_locomotives_locomotive_type2",
  138. [0]={code="dlx"},
  139. [1]={code="t"},
  140. [2]={code="nr"},
  141. [3]={code="tt"},
  142. count = 4,
  143. on_update_texture = function(wagon, data, texture)
  144. local new_texture = texture
  145. if texture ~= nil then
  146. local overlays = nil
  147. -- Update lights
  148. local white_light = "dlxtrains_diesel_locomotives_white_light.png\\^\\[resize\\:10x10"
  149. if data.light_config == 1 or data.light_config == 2 then
  150. -- Turn on running lights
  151. overlays = (overlays or "")..":374,168="..white_light
  152. end
  153. -- Update unit number
  154. local wagon_number = data.roadnumber
  155. local unit_number = tonumber(wagon_number)
  156. if unit_number ~= nil and unit_number >= 0 and unit_number < 1000 and string.find(wagon_number, "[,%.]") == nil then
  157. overlays = (overlays or "")..Get_unit_number_overlays(livery_type2_unit_number_info[data.scheme_id or 0], wagon_number, unit_number, data.alt_scheme)
  158. end
  159. -- Update the texture if any overlays were created
  160. if overlays ~= nil then
  161. new_texture = "[combine:384x384:0,0=("..texture..")"..overlays
  162. end
  163. end
  164. return new_texture
  165. end,
  166. }
  167. local livery_scheme_diesel_locomotive_type3 = {
  168. filename_prefix = "dlxtrains_diesel_locomotives_locomotive_type3",
  169. [0]={code="dz"},
  170. [1]={code="t"},
  171. [2]={code="wf"},
  172. [3]={code="zr"},
  173. count = 4,
  174. on_update_texture = function(wagon, data, texture)
  175. local new_texture = texture
  176. if texture ~= nil then
  177. local overlays = nil
  178. -- Update lights
  179. local white_light = "dlxtrains_diesel_locomotives_white_light.png\\^\\[resize\\:10x10"
  180. local red_light = "dlxtrains_diesel_locomotives_red_light.png\\^\\[resize\\:10x10"
  181. if data.light_config == 1 then
  182. -- Cab1 end of locomotive is moving forward
  183. overlays = (overlays or "")..":363,161="..white_light..":374,172="..red_light
  184. elseif data.light_config == 2 then
  185. -- Cab2 end of locomotive is moving forward
  186. overlays = (overlays or "")..":374,161="..white_light..":363,172="..red_light
  187. end
  188. -- Update cooling fans
  189. if data.light_config == 1 or data.light_config == 2 then
  190. -- Show cooling fan in spinning state
  191. overlays = (overlays or "")..":345,174=".."dlxtrains_diesel_locomotives_spinning_fan.png\\^\\[resize\\:17x17"
  192. end
  193. -- Update unit number
  194. local wagon_number = data.roadnumber
  195. local unit_number = tonumber(wagon_number)
  196. if unit_number ~= nil and unit_number >= 0 and unit_number < 1000 and string.find(wagon_number, "[,%.]") == nil then
  197. overlays = (overlays or "")..Get_unit_number_overlays(livery_type3_unit_number_info[data.scheme_id or 0], wagon_number, unit_number, data.alt_scheme)
  198. end
  199. -- Update the texture if any overlays were created
  200. if overlays ~= nil then
  201. new_texture = "[combine:384x384:0,0=("..texture..")"..overlays
  202. end
  203. end
  204. return new_texture
  205. end,
  206. }
  207. -- ////////////////////////////////////////////////////////////////////////////////////
  208. local livery_templates = {
  209. ["dlxtrains_diesel_locomotives:locomotive_type1"] = {
  210. dlxtrains.init_livery_template(mod_name, 0, dlxtrains.livery_type.standard, "WF", "locomotive_type1_wf"),
  211. dlxtrains.init_livery_template(mod_name, 1, dlxtrains.livery_type.standard, "T", "locomotive_type1_t"),
  212. dlxtrains.init_livery_template(mod_name, 2, dlxtrains.livery_type.standard, "DZ", "locomotive_type1_dz"),
  213. dlxtrains.init_livery_template(mod_name, 3, dlxtrains.livery_type.standard, "ZR", "locomotive_type1_zr"),
  214. },
  215. ["dlxtrains_diesel_locomotives:locomotive_type2"] = {
  216. dlxtrains.init_livery_template(mod_name, 0, dlxtrains.livery_type.standard, "DL&X", "locomotive_type2_dlx"),
  217. dlxtrains.init_livery_template(mod_name, 1, dlxtrains.livery_type.standard, "T", "locomotive_type2_t"),
  218. dlxtrains.init_livery_template(mod_name, 2, dlxtrains.livery_type.standard, "NR", "locomotive_type2_nr"),
  219. dlxtrains.init_livery_template(mod_name, 3, dlxtrains.livery_type.standard, "TT", "locomotive_type2_tt"),
  220. },
  221. ["dlxtrains_diesel_locomotives:locomotive_type3"] = {
  222. dlxtrains.init_livery_template(mod_name, 0, dlxtrains.livery_type.standard, "DZ", "locomotive_type3_dz"),
  223. dlxtrains.init_livery_template(mod_name, 1, dlxtrains.livery_type.standard, "T", "locomotive_type3_t"),
  224. dlxtrains.init_livery_template(mod_name, 2, dlxtrains.livery_type.standard, "WF", "locomotive_type3_wf"),
  225. dlxtrains.init_livery_template(mod_name, 3, dlxtrains.livery_type.standard, "ZR", "locomotive_type3_zr"),
  226. },
  227. }
  228. -- ////////////////////////////////////////////////////////////////////////////////////
  229. local meshes_diesel_locomotive_type1 = {
  230. default = "dlxtrains_diesel_locomotives_locomotive_type1.b3d",
  231. chimneys = {
  232. {x=0.27, y=2.4, z=0.60}
  233. },
  234. audio_loop_name = "dlxtrains_diesel_locomotives_locomotive_type1_loop",
  235. audio_loop_gain = .3
  236. }
  237. local meshes_diesel_locomotive_type2 = {
  238. default = "dlxtrains_diesel_locomotives_locomotive_type2.b3d",
  239. chimneys = {
  240. {x=0.0, y=2.4, z= 0.90},
  241. {x=0.0, y=2.4, z=-0.30}
  242. },
  243. audio_loop_name = "dlxtrains_diesel_locomotives_locomotive_type1_loop", -- Using locomotive_type1 audio for now.
  244. audio_loop_gain = .3
  245. }
  246. local meshes_diesel_locomotive_type3 = {
  247. default = "dlxtrains_diesel_locomotives_locomotive_type3.b3d",
  248. chimneys = {
  249. {x=-0.29, y=2.6, z=1.80, type="left"},
  250. {x= 0.29, y=2.6, z=1.80, type="right"}
  251. },
  252. audio_loop_name = "dlxtrains_diesel_locomotives_locomotive_type1_loop", -- Using locomotive_type1 audio for now.
  253. audio_loop_gain = .3
  254. }
  255. -- ////////////////////////////////////////////////////////////////////////////////////
  256. local function Get_diesel_smoke_particle_def(type)
  257. local index = type or "default"
  258. local burst_defs = {
  259. default = {
  260. amount = 10,
  261. time = 0,
  262. minvel = {x=-0.2, y=1.8, z=-0.2},
  263. maxvel = {x=0.2, y=2, z=0.2},
  264. minacc = {x=0, y=-0.1, z=0},
  265. maxacc = {x=0, y=-0.3, z=0},
  266. minexptime = 2,
  267. maxexptime = 4,
  268. minsize = 1,
  269. maxsize = 5,
  270. collisiondetection = true,
  271. vertical = false,
  272. texture = "dlxtrains_diesel_locomotives_smoke_puff.png",
  273. },
  274. left = {
  275. amount = 10,
  276. time = 0,
  277. minvel = {x=-0.8, y=1.8, z=-0.2},
  278. maxvel = {x=-1.2, y=2, z=0.2},
  279. minacc = {x=0.3, y=-0.3, z=0},
  280. maxacc = {x=0.1, y=-0.1, z=0},
  281. minexptime = 2,
  282. maxexptime = 4,
  283. minsize = 1,
  284. maxsize = 5,
  285. collisiondetection = true,
  286. vertical = false,
  287. texture = "dlxtrains_diesel_locomotives_smoke_puff.png",
  288. },
  289. right = {
  290. amount = 10,
  291. time = 0,
  292. minvel = {x=0.8, y=1.8, z=-0.2},
  293. maxvel = {x=1.2, y=2, z=0.2},
  294. minacc = {x=-0.3, y=-0.3, z=0},
  295. maxacc = {x=-0.1, y=-0.1, z=0},
  296. minexptime = 2,
  297. maxexptime = 4,
  298. minsize = 1,
  299. maxsize = 5,
  300. collisiondetection = true,
  301. vertical = false,
  302. texture = "dlxtrains_diesel_locomotives_smoke_puff.png",
  303. },
  304. }
  305. return burst_defs[index]
  306. end
  307. local function Terminate_locomotive_sound(wagon)
  308. if wagon.sound_loop_handle then
  309. minetest.sound_stop(wagon.sound_loop_handle)
  310. wagon.sound_loop_handle = nil
  311. end
  312. wagon.sound_loop_tmr = nil
  313. wagon.sound_loop_idx = nil
  314. end
  315. local function Update_locomotive_sound(wagon, time_expired, audio_loop_name, audio_loop_gain)
  316. local locomotive_sound_idx = 7
  317. if dlxtrains.locomotive_sounds == 2 then
  318. if wagon:train().velocity < 20 then
  319. locomotive_sound_idx = math.floor(wagon:train().velocity/2)
  320. else
  321. locomotive_sound_idx = 9
  322. end
  323. end
  324. if time_expired or locomotive_sound_idx ~= wagon.sound_loop_idx then
  325. Terminate_locomotive_sound(wagon)
  326. wagon.sound_loop_idx = locomotive_sound_idx
  327. wagon.sound_loop_handle = minetest.sound_play({name=audio_loop_name..locomotive_sound_idx, gain=audio_loop_gain}, {object=wagon.object})
  328. wagon.sound_loop_tmr = 3.0 -- This is slightly shorter than the audio clip in order to minimize audio dropouts if there is some system lag. (i.e. the sound will keep playing briefly after the timer has expired while this function is yet to be called)
  329. end
  330. end
  331. local function Update_locomotive_smoke(data, wagon, chimneys, old_velocity, new_velocity)
  332. if dlxtrains.locomotive_smoke > 0 and chimneys ~= nil then
  333. -- If dynamic smoke is enabled, add extra smoke puffs when accelerating
  334. if dlxtrains.locomotive_smoke == 2 and new_velocity > old_velocity then
  335. local dynamic_amount = 4 - new_velocity
  336. if #chimneys > 1 then dynamic_amount = dynamic_amount/#chimneys end
  337. if dynamic_amount < 1 then dynamic_amount = 1 end
  338. for _, chimney_pos in pairs(chimneys) do
  339. local smoke_def = Get_diesel_smoke_particle_def(chimney_pos.type)
  340. smoke_def.time = 1 -- Automatically end after a unit of time.
  341. smoke_def.amount = dynamic_amount
  342. smoke_def.minpos = chimney_pos
  343. smoke_def.maxpos = chimney_pos
  344. smoke_def.attached = wagon.object
  345. minetest.add_particlespawner(smoke_def)
  346. end
  347. end
  348. -- Compute the amount of smoke based on velocity and length of train. (This will be used later if dynamic smoke is enabled)
  349. local dynamic_amount = new_velocity + #(wagon:train().trainparts) - 1
  350. if #chimneys > 1 then dynamic_amount = dynamic_amount/#chimneys end
  351. if dynamic_amount < 1 then
  352. dynamic_amount = 1
  353. elseif dynamic_amount > 12 then
  354. dynamic_amount = 12
  355. end
  356. data.particle_spawner_ids = {}
  357. for _, chimney_pos in pairs(chimneys) do
  358. local smoke_def = Get_diesel_smoke_particle_def(chimney_pos.type)
  359. if dlxtrains.locomotive_smoke == 2 then
  360. -- If dynamic smoke is enabled, define smoke stream based on velocity and length of train
  361. smoke_def.amount = dynamic_amount
  362. else
  363. if #chimneys > 1 then
  364. smoke_def.amount = smoke_def.amount/#chimneys
  365. if smoke_def.amount < 1 then
  366. smoke_def.amount = 1
  367. end
  368. end
  369. end
  370. smoke_def.minpos = chimney_pos
  371. smoke_def.maxpos = chimney_pos
  372. smoke_def.attached = wagon.object
  373. table.insert(data.particle_spawner_ids, minetest.add_particlespawner(smoke_def))
  374. end
  375. end
  376. end
  377. -- ////////////////////////////////////////////////////////////////////////////////////
  378. if dlxtrains_diesel_locomotives.max_wagon_length >= 7.35 then
  379. local wagon_type = "dlxtrains_diesel_locomotives:locomotive_type1"
  380. dlxtrains.register_livery_templates(wagon_type, mod_name, livery_templates)
  381. local wagon_def = {
  382. mesh = meshes_diesel_locomotive_type1.default,
  383. textures = {dlxtrains.get_init_texture()},
  384. set_textures = function(wagon, data)
  385. dlxtrains.set_textures_for_livery_scheme(wagon, data, livery_scheme_diesel_locomotive_type1, meshes_diesel_locomotive_type1)
  386. end,
  387. custom_may_destroy = function(wagon, puncher, time_from_last_punch, tool_capabilities, direction)
  388. return not dlxtrains.update_livery(wagon, puncher, livery_scheme_diesel_locomotive_type1)
  389. end,
  390. seats = {
  391. {
  392. name = "Driver Stand",
  393. attach_offset={x=2.8, y=2.8, z=12},
  394. view_offset = use_attachment_patch and {x=0, y=0, z=0} or {x=0, y=3.6, z=0},
  395. driving_ctrl_access = true,
  396. group = "cabin",
  397. }
  398. },
  399. seat_groups = {
  400. cabin={
  401. name = "Cabin",
  402. access_to = {},
  403. require_doors_open = false,
  404. driving_ctrl_access = true,
  405. },
  406. },
  407. assign_to_seat_group = {"cabin"},
  408. drives_on={default=true},
  409. max_speed=25,
  410. visual_size = {x=1, y=1},
  411. wagon_span=3.675,
  412. wheel_positions = {1.8, -1.8},
  413. is_locomotive=true,
  414. collisionbox = {-0.5,-0.5,-0.5,0.5,2.5,0.5},
  415. coupler_types_front = {chain=true},
  416. coupler_types_back = {chain=true},
  417. drops={dlxtrains.materials.steelblock and (dlxtrains.materials.steelblock.." 2")},
  418. horn_sound = "advtrains_industrial_horn",
  419. has_inventory = false,
  420. custom_on_step=function(wagon, dtime)
  421. if dlxtrains.locomotive_sounds > 0 and wagon:train().velocity > 0 then
  422. if not wagon.sound_loop_tmr or wagon.sound_loop_tmr <= 0 then
  423. Update_locomotive_sound(wagon, true, meshes_diesel_locomotive_type1.audio_loop_name, meshes_diesel_locomotive_type1.audio_loop_gain)
  424. end
  425. wagon.sound_loop_tmr = wagon.sound_loop_tmr - dtime
  426. else
  427. Terminate_locomotive_sound(wagon)
  428. end
  429. end,
  430. custom_on_velocity_change = function(wagon, velocity, old_velocity)
  431. if velocity ~= old_velocity then
  432. local data = advtrains.wagons[wagon.id]
  433. local light_config = 0
  434. -- Keep the following for legacy locomotives (Remove after 2023?)
  435. if data.particle_spawner_id ~= nil then
  436. minetest.delete_particlespawner(data.particle_spawner_id)
  437. data.particle_spawner_id = nil
  438. end
  439. if data.particle_spawner_ids ~= nil then
  440. for _, particle_spawner_id in ipairs(data.particle_spawner_ids) do
  441. if particle_spawner_id ~= nil then
  442. minetest.delete_particlespawner(particle_spawner_id)
  443. end
  444. end
  445. data.particle_spawner_ids = nil
  446. end
  447. if velocity > 0 then
  448. -- Set light configuration based on direction of travel
  449. light_config = 1
  450. if data.wagon_flipped then
  451. light_config = 2
  452. end
  453. Update_locomotive_smoke(data, wagon, meshes_diesel_locomotive_type1.chimneys, old_velocity, velocity)
  454. end
  455. if light_config ~= data.light_config then
  456. data.light_config = light_config
  457. wagon:set_textures(data)
  458. end
  459. if dlxtrains.locomotive_sounds == 2 then
  460. Update_locomotive_sound(wagon, false, meshes_diesel_locomotive_type1.audio_loop_name, meshes_diesel_locomotive_type1.audio_loop_gain)
  461. end
  462. end
  463. end,
  464. }
  465. if use_attachment_patch then
  466. advtrains_attachment_offset_patch.setup_advtrains_wagon(wagon_def);
  467. end
  468. advtrains.register_wagon(wagon_type, wagon_def, S("European G1206 Diesel Locomotive"), "dlxtrains_diesel_locomotives_locomotive_type1_inv.png")
  469. end
  470. if dlxtrains_diesel_locomotives.max_wagon_length >= 6.80725 then
  471. local wagon_type = "dlxtrains_diesel_locomotives:locomotive_type2"
  472. dlxtrains.register_livery_templates(wagon_type, mod_name, livery_templates)
  473. local wagon_def = {
  474. mesh = meshes_diesel_locomotive_type2.default,
  475. textures = {dlxtrains.get_init_texture()},
  476. set_textures = function(wagon, data)
  477. dlxtrains.set_textures_for_livery_scheme(wagon, data, livery_scheme_diesel_locomotive_type2, meshes_diesel_locomotive_type2)
  478. end,
  479. custom_may_destroy = function(wagon, puncher, time_from_last_punch, tool_capabilities, direction)
  480. return not dlxtrains.update_livery(wagon, puncher, livery_scheme_diesel_locomotive_type2)
  481. end,
  482. seats = {
  483. {
  484. name = "Driver Stand",
  485. attach_offset={x=3.6, y=4.2, z=-21.2},
  486. view_offset = use_attachment_patch and {x=0, y=0, z=0} or {x=1.3, y=6.5, z=0},
  487. driving_ctrl_access = true,
  488. group = "cabin",
  489. }
  490. },
  491. seat_groups = {
  492. cabin={
  493. name = "Cabin",
  494. access_to = {},
  495. require_doors_open = false,
  496. driving_ctrl_access = true,
  497. },
  498. },
  499. assign_to_seat_group = {"cabin"},
  500. drives_on={default=true},
  501. max_speed=25,
  502. visual_size = {x=1, y=1},
  503. wagon_span=3.403625,
  504. wheel_positions = {1.5625, -1.5625},
  505. is_locomotive=true,
  506. collisionbox = {-0.5,-0.5,-0.5,0.5,2.5,0.5},
  507. coupler_types_front = {knuckle=true},
  508. coupler_types_back = {knuckle=true},
  509. drops={dlxtrains.materials.steelblock and (dlxtrains.materials.steelblock.." 2")},
  510. horn_sound = "advtrains_industrial_horn",
  511. has_inventory = false,
  512. custom_on_step=function(wagon, dtime)
  513. if dlxtrains.locomotive_sounds > 0 and wagon:train().velocity > 0 then
  514. if not wagon.sound_loop_tmr or wagon.sound_loop_tmr <= 0 then
  515. Update_locomotive_sound(wagon, true, meshes_diesel_locomotive_type1.audio_loop_name, meshes_diesel_locomotive_type1.audio_loop_gain) -- Using locomotive_type1 audio for now.
  516. end
  517. wagon.sound_loop_tmr = wagon.sound_loop_tmr - dtime
  518. else
  519. Terminate_locomotive_sound(wagon)
  520. end
  521. end,
  522. custom_on_velocity_change = function(wagon, velocity, old_velocity)
  523. if velocity ~= old_velocity then
  524. local data = advtrains.wagons[wagon.id]
  525. local light_config = 0
  526. if data.particle_spawner_ids ~= nil then
  527. for _, particle_spawner_id in ipairs(data.particle_spawner_ids) do
  528. if particle_spawner_id ~= nil then
  529. minetest.delete_particlespawner(particle_spawner_id)
  530. end
  531. end
  532. data.particle_spawner_ids = nil
  533. end
  534. if velocity > 0 then
  535. -- Set light configuration based on direction of travel
  536. light_config = 1
  537. if data.wagon_flipped then
  538. light_config = 2
  539. end
  540. Update_locomotive_smoke(data, wagon, meshes_diesel_locomotive_type2.chimneys, old_velocity, velocity)
  541. end
  542. if light_config ~= data.light_config then
  543. data.light_config = light_config
  544. wagon:set_textures(data)
  545. end
  546. if dlxtrains.locomotive_sounds == 2 then
  547. Update_locomotive_sound(wagon, false, meshes_diesel_locomotive_type1.audio_loop_name, meshes_diesel_locomotive_type1.audio_loop_gain) -- Using locomotive_type1 audio for now.
  548. end
  549. end
  550. end,
  551. }
  552. if use_attachment_patch then
  553. advtrains_attachment_offset_patch.setup_advtrains_wagon(wagon_def);
  554. end
  555. advtrains.register_wagon(wagon_type, wagon_def, S("North American SW1500 Diesel Locomotive"), "dlxtrains_diesel_locomotives_locomotive_type2_inv.png")
  556. end
  557. if dlxtrains_diesel_locomotives.max_wagon_length >= 8.2 then
  558. local wagon_type = "dlxtrains_diesel_locomotives:locomotive_type3"
  559. dlxtrains.register_livery_templates(wagon_type, mod_name, livery_templates)
  560. local wagon_def = {
  561. mesh = meshes_diesel_locomotive_type3.default,
  562. textures = {dlxtrains.get_init_texture()},
  563. set_textures = function(wagon, data)
  564. dlxtrains.set_textures_for_livery_scheme(wagon, data, livery_scheme_diesel_locomotive_type3, meshes_diesel_locomotive_type3)
  565. end,
  566. custom_may_destroy = function(wagon, puncher, time_from_last_punch, tool_capabilities, direction)
  567. return not dlxtrains.update_livery(wagon, puncher, livery_scheme_diesel_locomotive_type3)
  568. end,
  569. seats = {
  570. {
  571. name = "Cab 1 Driver Stand",
  572. attach_offset={x=2.8, y=2.8, z=30},
  573. view_offset = use_attachment_patch and {x=0, y=0, z=0} or {x=0, y=9.65, z=0},
  574. driving_ctrl_access = true,
  575. group = "cab_1",
  576. },
  577. {
  578. name = "Cab 2 Driver Stand",
  579. attach_offset={x=-2.8, y=2.8, z=-30},
  580. view_offset = use_attachment_patch and {x=0, y=0, z=0} or {x=0, y=9.65, z=0},
  581. advtrains_attachment_offset_patch_attach_rotation = {x=0, y=180, z=0},
  582. driving_ctrl_access = true,
  583. group = "cab_2",
  584. }
  585. },
  586. seat_groups = {
  587. cab_1={
  588. name = "Cab 1",
  589. access_to = {"cab_2"},
  590. require_doors_open = false,
  591. driving_ctrl_access = true,
  592. },
  593. cab_2={
  594. name = "Cab 2",
  595. access_to = {"cab_1"},
  596. require_doors_open = false,
  597. driving_ctrl_access = true,
  598. },
  599. },
  600. assign_to_seat_group = {"cab_1"},
  601. drives_on={default=true},
  602. max_speed=25,
  603. visual_size = {x=1, y=1},
  604. wagon_span=4.1,
  605. wheel_positions = {1.8, -1.8},
  606. is_locomotive=true,
  607. collisionbox = {-0.5,-0.5,-0.5,0.5,2.5,0.5},
  608. coupler_types_front = {chain=true},
  609. coupler_types_back = {chain=true},
  610. drops={dlxtrains.materials.steelblock and (dlxtrains.materials.steelblock.." 2")},
  611. horn_sound = "advtrains_industrial_horn",
  612. has_inventory = false,
  613. custom_on_step=function(wagon, dtime)
  614. if dlxtrains.locomotive_sounds > 0 and wagon:train().velocity > 0 then
  615. if not wagon.sound_loop_tmr or wagon.sound_loop_tmr <= 0 then
  616. Update_locomotive_sound(wagon, true, meshes_diesel_locomotive_type1.audio_loop_name, meshes_diesel_locomotive_type1.audio_loop_gain)
  617. end
  618. wagon.sound_loop_tmr = wagon.sound_loop_tmr - dtime
  619. else
  620. Terminate_locomotive_sound(wagon)
  621. end
  622. end,
  623. custom_on_velocity_change = function(wagon, velocity, old_velocity)
  624. if velocity ~= old_velocity then
  625. local data = advtrains.wagons[wagon.id]
  626. local light_config = 0
  627. if data.particle_spawner_ids ~= nil then
  628. for _, particle_spawner_id in ipairs(data.particle_spawner_ids) do
  629. if particle_spawner_id ~= nil then
  630. minetest.delete_particlespawner(particle_spawner_id)
  631. end
  632. end
  633. data.particle_spawner_ids = nil
  634. end
  635. if velocity > 0 then
  636. -- Set light configuration based on direction of travel
  637. light_config = 1
  638. if data.wagon_flipped then
  639. light_config = 2
  640. end
  641. Update_locomotive_smoke(data, wagon, meshes_diesel_locomotive_type3.chimneys, old_velocity, velocity)
  642. end
  643. if light_config ~= data.light_config then
  644. data.light_config = light_config
  645. wagon:set_textures(data)
  646. end
  647. if dlxtrains.locomotive_sounds == 2 then
  648. Update_locomotive_sound(wagon, false, meshes_diesel_locomotive_type3.audio_loop_name, meshes_diesel_locomotive_type3.audio_loop_gain)
  649. end
  650. end
  651. end,
  652. }
  653. if use_attachment_patch then
  654. advtrains_attachment_offset_patch.setup_advtrains_wagon(wagon_def);
  655. end
  656. advtrains.register_wagon(wagon_type, wagon_def, S("European BR218 Diesel Locomotive"), "dlxtrains_diesel_locomotives_locomotive_type3_inv.png")
  657. end