Extending A Loco Script Without the LUA Source

Discussion of rolling-stock creation & re-painting.

Extending A Loco Script Without the LUA Source

Unread postby wacampbell » Wed Feb 04, 2015 2:39 pm

I learned something new today and thought others might be interested. I was wanting to add my spring return brake controls ( http://railworksamerica.com/forum/viewtopic.php?f=9&t=13013 ) to a locomotive where I didn't have the LUA source for the .OUT file. I stumbled across this interesting post at UKTrainSim:

http://forums.uktrainsim.com/viewtopic. ... 8#p1687192

Basically, its a way to insert your own script instructions in front of the default script provided by the builder. Using his technique I was able to hook the OnControlValueChange function such that my script could process the brake key presses to achieve the spring return effect, while all other key presses pass on to the default script so the locomotive operates as the designer intended otherwise.

This is a pretty advanced technique, but for those who are into script writing, etc I am sure you can think of some cool uses for this.

PS, just a starting point, I'll provide the script I used for my brake control mods. The script requires some other mods to the InputMappers etc, but you might find it a helpful example for your own projects.

Code: Select all
-- -*- lua -*-

-- this is the original engine script .out file
require("Assets/GreatNortherner/EMD-SD7-9/RailVehicles/Engines/SD7/Models/RWA/sd7_EngineScript.out")

-- keep previous functions before we provide our own
__OnControlValueChange = OnControlValueChange
__Update = Update
__Initialise = Initialise

function Initialise()
   __Initialise()
   -- you can add your custom code here
end

function Update(interval)
   __Update(interval)
   -- you can add your custom code here
end


previousReverserValue = 0
ReverserState = 0

function OnControlValueChange ( name, index, value )

   --- ADD SNAP TO REVERSER
   if name == "Reverser" then
      --- Make reverser snap from forward to reverse
      if value > previousReverserValue then
         ReverserState = 1
      elseif value < previousReverserValue then
         ReverserState = -1
      end
      previousReverserValue = value
      value = ReverserState

   --- TRAIN BRAKE CONTROLS
   elseif name == "ApplyBrake" then
      if  value > 0.1 then
         --- When Apostrophe is pressed, TrainBrakeControl sets to FullService
         Call( "*:SetControlValue", "TrainBrakeControl", 0, 0.6 ) 
         Call( "*:SetControlValue", "Regulator", 0, 0 ) 
      else
         --- When Apostrophe is released, TrainBrakeControl sets to Hold
         Call( "*:SetControlValue", "TrainBrakeControl", 0, 0.4 ) 
      end
   elseif name == "ReleaseBrake" then
      if  value > 0.1 then
         --- When SemiColon is pressed, TrainBrakeControl sets to Release
         Call( "*:SetControlValue", "TrainBrakeControl", 0, 0 )   
      else
         --- When SemiColon is released, TrainBrakeControl moves to Running
         Call( "*:SetControlValue", "TrainBrakeControl", 0, 0.2 )
      end
   
   --- ENGINE BRAKE CONTROLS
   elseif name == "ApplyEngineBrake" then
      if  value > 0.1 then
         --- When RightBracket is pressed, EngineBrakeControl sets to FullService
         Call( "*:SetControlValue", "EngineBrakeControl", 0, 1.0 ) 
         Call( "*:SetControlValue", "Regulator", 0, 0 ) 
      else
         --- When RightBracket is released, EngineBrakeControl sets to Hold
         Call( "*:SetControlValue", "EngineBrakeControl", 0, 0.5 ) 
      end
   elseif name == "ReleaseEngineBrake" then
      if  value > 0.1 then
         --- When LeftBracket is pressed, EngineBrakeControl sets to Release
         Call( "*:SetControlValue", "EngineBrakeControl", 0, 0 )   
      else
         --- When LeftBracket is released, EngineBrakeControl moves to Running
         Call( "*:SetControlValue", "EngineBrakeControl", 0, 0.5 )
      end
   
   --- THROTTLE / BRAKE INTERLOCK - if throttle increased, and brakes are on, release them
   elseif name == "Regulator" then
      if value > 0.05 then
         if Call( "*:GetControlValue", "TrainBrakeControl", 0 ) > 0.3 then
            Call( "*:SetControlValue", "TrainBrakeControl", 0, 0 )   
         end
         if Call( "*:GetControlValue", "LocoBrakeCylinderPressurePSI", 0 ) > 5 then
            Call( "*:SetControlValue", "EngineBrakeControl", 0, 0 )   
         end
      end

   end
   
   --- fall through to the original engine script
   __OnControlValueChange( name, index, value )
   

end  --- OnControlValueChange
Wayne Campbell
wacampbell
 
Posts: 516
Joined: Tue Sep 27, 2011 12:45 pm
Location: BC, Canada

Re: Extending A Loco Script Without the LUA Source

Unread postby PapaXpress » Wed Feb 04, 2015 3:00 pm

This can be hit or miss in some cases. Take for example my VRC controls. I have made liberal use of virtual controls which may not behave well when called by this external script.
Image
"Just post some random unrelated text. We have members here who can help you with that." ~ Chacal
"When all else fails, read the instructions... if that doesn't work either, try following them." ~ Old Prof
Image
The Grade Crossing - Atlanta North Project - Virtual Rail Creations
User avatar
PapaXpress
 
Posts: 5147
Joined: Sat Oct 23, 2010 10:30 pm
Location: that "other" timezone

Re: Extending A Loco Script Without the LUA Source

Unread postby mrennie » Wed Feb 04, 2015 5:32 pm

PapaXpress wrote:This can be hit or miss in some cases. Take for example my VRC controls. I have made liberal use of virtual controls which may not behave well when called by this external script.


Exactly. The technique is probably useful only for "standard" locos that have a "bare bones" (i.e. practically empty) engine script as default. Otherwise the two are bound to interfere with each other.
User avatar
mrennie
 
Posts: 3214
Joined: Wed May 30, 2012 12:22 pm

Re: Extending A Loco Script Without the LUA Source

Unread postby wacampbell » Wed Feb 04, 2015 6:21 pm

As a general technique to intercept and modify messages to the engine script, it is sound and completely transparent, even for virtual controls. But I agree, the trick is knowing what messages to alter. It would be easy to cause problems.
Wayne Campbell
wacampbell
 
Posts: 516
Joined: Tue Sep 27, 2011 12:45 pm
Location: BC, Canada

Re: Extending A Loco Script Without the LUA Source

Unread postby Kali » Thu Feb 19, 2015 12:18 am

wacampbell wrote:As a general technique to intercept and modify messages to the engine script, it is sound and completely transparent, even for virtual controls. But I agree, the trick is knowing what messages to alter. It would be easy to cause problems.


Be very wary of changing values in OnControlValueChange before you pass them through - the HUD has a habit of getting in a huge fight with the script at that point, the underlying code in that area is a disaster. In general just to extend things this is a perfectly valid method - it's a perfectly valid thing to do even when you *have* the base source, I used it in an ancient library I uploaded here somewhere once, and of course you can do this too:

Code: Select all
fPUpdate = Update
function Update( ptFrame )
  <some code>
  fPUpdate( ptFrame )
 <some more code>
end


or just not call the old Update callback, or call it twice in yours, or whatever. Lua functions are first-class variables just like single values and tables ( and actually I think that's all the types in lua right there ), you can have much fun with that.
Kali
 
Posts: 1600
Joined: Mon Mar 14, 2011 1:00 am
Location: England-by-Sea


Return to Rolling-Stock Design

Who is online

Users browsing this forum: No registered users and 3 guests