Adding Selectable Dual Wheels in FS13

[Updated 27 Jan 2014]

Game Version: Farming Simulator 2013
Programs required: Giants Editor 5.0.1 | Winzip, Jzip, 7zip or WinRar | Notepad / Notepad++


Modding Index | Vehicle Tutorials


Just a quick :-D tutorial on adding selectable duals in FS13.

Step 1. Make a backup!

Step 2. Get comfy, get a drink, snack, bio-break, whatever you need…this could take a while.

Step 3. See step 1.

Now for the good stuff….

Things you will need:

Giants Editor which can be found in your game install directory in the SDK folder.
Notepad++ can be obtained here: Notepad++ Download
A Tractor or Combine mod
Time
Patience

Before this tutorial starts the picture have been removed due to age of tutorial, but the description should still help you along the way.

First we will open the mod in GE. You should be looking at the back of the mod from slightly above. This is the outdoorCamera…do not move it!! Instead go to the menu bar at the top of the screen and click on “Create” then “camera”. Now still on the menu bar, select “View” then “Camera” and click the camera at the bottom of the list. This is the one you just created and should be under the mod facing back. This camera can be moved /rotated anywhere you like without affecting the in-game cameras. If the image is too dark, go back to the “Create” menu and select “Light”. This light source can be rotated to illuminate whatever we are working on. Think of it as a virtual flashlight.

Now that we have a camera and light, essentially what we will be doing is copying the existing wheels, pasting them back onto themselves and repositioning them outside the stock wheels. For the purpose of this tutorial I will be using the default Same Argon3 75 which I have made into a standalone mod.

Select the first wheel in the Scenegraph, in this case the right front
Image removed

now copy it
Image removed

then paste it back onto itself
Image removed

finally, move it outwards to a position you're happy with. In this case I had the tires just touching but on a mod with a stub axle or an extended outer rim, you could move it out a bit further.
Image removed

Take note of the X translation in the Attributes Pane as we will need this number for the other side.

Repeat these steps for the other wheels, taking note that most times the rear wheels will be out of position when you paste them.
Image removed

This can be fixed by changing the translations in the Attributes Pane to 0/0/0 then moving it outwards as we did on the front.

As mentioned earlier, the X translation on each side should match. On my example, the front right is at -0.34 so the left front will be at 0.34 and the right rear and left rear are at -0.445 and 0.445 respectively. Your actual numbers may be different but should be the same from side to side. This step isn't absolutely critical but the finished mod will look better and satisfy the players with OCD.

So at this point you should have something like this….
Image removed

Just a couple more things to do and we're done with the i3d. Highlight each of the new wheels in the scenegraph and write down the index node, we'll need it for the xml file. Also, while the wheel is selected, un-check the “Visibility” box near the bottom of the Attributes Pane for each wheel. Once you have that info and the wheels are invisible, save and exit.

Now would be a good time for a snack/drink/smoke/bio-break…..take your time, I'll wait………

Ready?

Ok, we'll start with the scripts since it's a simple copy and paste. If you don't already have one, create a folder called Scripts within the mod's folder. You can use an existing folder or a different name, just make sure to use the same folder name in the modDesc.xml. Now copy these three scripts to that folder and save them with the indicated name:

Einblendung.lua

--
-- Einblendungs .lua inkl. Setblends 1 & 2
-- Specialization for Einblendung
--
-- [url=http://www.LS-Landtechnik.de]www.LS-Landtechnik.de[/url]
-- @author  LS-Landtechnik.de
-- @date:  01/01/11
-- @version: v2.0
-- @copyright: LS-Landtechnik.de

Einblendung = {};

function Einblendung.prerequisitesPresent(specializations)
    return true;
end;
function Einblendung:load(xmlFile)

 self.setblends1Visibility = SpecializationUtil.callSpecializationsFunction("setblends1Visibility");
 self.setblends2Visibility = SpecializationUtil.callSpecializationsFunction("setblends2Visibility");
 
    self.blends1 = {};
        local i = 0;
        while true do
        local key = string.format("vehicle.blends1.blend1(%d)", i);
            if not hasXMLProperty(xmlFile, key) then
             break;
        end;
            local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
            if node ~= nil then
        setVisibility(node, false);
            table.insert(self.blends1, {node=node});
        end;
        i = i + 1;
        end;
    self.blends1Active = false;
 
    self.blends2 = {};
        local i = 0;
        while true do
        local key = string.format("vehicle.blends2.blend2(%d)", i);
            if not hasXMLProperty(xmlFile, key) then
            break;
        end;
            local node = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"));
            if node ~= nil then
        setVisibility(node, false);
            table.insert(self.blends2, {node=node});
        end;
        i = i + 1;
    end;
 self.blends2Active = false;
end;
function Einblendung:delete()
end;
function Einblendung:readStream(streamId, connection)
 self.isLoading = true;
 local visibility = streamReadBool(streamId);
 self:setblends1Visibility(visibility, true);
 local visibility = streamReadBool(streamId);
 self:setblends2Visibility(visibility, true);
end;

function Einblendung:writeStream(streamId, connection)
 streamWriteBool(streamId, self.blends1Active);
 streamWriteBool(streamId, self.blends2Active);
end;
function Einblendung:mouseEvent(posX, posY, isDown, isUp, button)
end;
function Einblendung:keyEvent(unicode, sym, modifier, isDown)
end;
function Einblendung:update(dt)

    if self:getIsActiveForInput() and self.isClient then
        if InputBinding.hasEvent(InputBinding.EinblendungEins) then
              self:setblends1Visibility(not self.blends1Active);
        end;
        if InputBinding.hasEvent(InputBinding.EinblendungZwei) then
              self:setblends2Visibility(not self.blends2Active);
        end;
 end;
end;
function Einblendung:onLeave()
end;
function Einblendung:draw()
 g_currentMission:addHelpButtonText(g_i18n:getText("EinblendungEins"), InputBinding.EinblendungEins); 
 g_currentMission:addHelpButtonText(g_i18n:getText("EinblendungZwei"), InputBinding.EinblendungZwei);
end;
function Einblendung:setblends1Visibility(visibility, noEventSend)
    if visibility ~= self.blends1Active then
  
        if noEventSend == nil or noEventSend == false then
            if g_server ~= nil then
                g_server:broadcastEvent(Setblends1Event:new(self, visibility), nil, nil, self);
            else
                g_client:getServerConnection():sendEvent(Setblends1Event:new(self, visibility));
            end;
        end;
  
        self.blends1Active = visibility;
  
        for _, blend1 in pairs(self.blends1) do
            setVisibility(blend1.node, visibility);
        end;
        for _,v in pairs(self.specializations) do
            if v.setblend1Visibility ~= nil then
                v.setblend1Visibility(self, visibility);
            end;
        end;
    end;
end;
function Einblendung:setblends2Visibility(visibility, noEventSend)
    if visibility ~= self.blends2Active then
  
        if noEventSend == nil or noEventSend == false then
            if g_server ~= nil then
                g_server:broadcastEvent(Setblends2Event:new(self, visibility), nil, nil, self);
            else
                g_client:getServerConnection():sendEvent(Setblends2Event:new(self, visibility));
            end;
        end;
  
        self.blends2Active = visibility;
  
        for _, blend2 in pairs(self.blends2) do
            setVisibility(blend2.node, visibility);
        end;
        for _,v in pairs(self.specializations) do
            if v.setblend2Visibility ~= nil then
                v.setblend2Visibility(self, visibility);
            end;
        end;
    end;
end;

Setblends1Event.lua

--
-- Einblendungs .lua -- Set Blends 1
-- Specialization for Einblendung
--
-- [url=http://www.LS-Landtechnik.de]www.LS-Landtechnik.de[/url]
-- @author  LS-Landtechnik.de
-- @date:  01/01/11
-- @version: v2.0
-- @copyright: LS-Landtechnik.de



Setblends1Event = {};
Setblends1Event_mt = Class(Setblends1Event, Event);
InitEventClass(Setblends1Event, "Setblends1Event");
function Setblends1Event:emptyNew()
      local self = Event:new(Setblends1Event_mt);
      self.className="Setblends1Event";
      return self;
end;
function Setblends1Event:new(object, active)
      local self = Setblends1Event:emptyNew()
      self.active = active;
      self.object = object;
      return self;
end;
function Setblends1Event:readStream(streamId, connection)
      local id = streamReadInt32(streamId);
      self.active = streamReadBool(streamId);
      self.object = networkGetObject(id);
      self:run(connection);
end;
function Setblends1Event:writeStream(streamId, connection)
      streamWriteInt32(streamId, networkGetObjectId(self.object));
      streamWriteBool(streamId, self.active);
end;
function Setblends1Event:run(connection)
      self.object:setblends1Visibility(self.active, true);
      if not connection:getIsServer() then
          g_server:broadcastEvent(Setblends1Event:new(self.object, self.active), nil, connection, self.object);
      end;
end;

Setblends2Event.lua

--
-- Einblendungs .lua -- Set Blends 2
-- Specialization for Einblendung
--
-- [url=http://www.LS-Landtechnik.de]www.LS-Landtechnik.de[/url]
-- @author  LS-Landtechnik.de
-- @date:  01/01/11
-- @version: v2.0
-- @copyright: LS-Landtechnik.de


Setblends2Event = {};
Setblends2Event_mt = Class(Setblends2Event, Event);
InitEventClass(Setblends2Event, "Setblends2Event");
function Setblends2Event:emptyNew()
      local self = Event:new(Setblends2Event_mt);
      self.className="Setblends2Event";
      return self;
end;
function Setblends2Event:new(object, active)
      local self = Setblends2Event:emptyNew()
      self.active = active;
      self.object = object;
      return self;
end;
function Setblends2Event:readStream(streamId, connection)
      local id = streamReadInt32(streamId);
      self.active = streamReadBool(streamId);
      self.object = networkGetObject(id);
      self:run(connection);
end;
function Setblends2Event:writeStream(streamId, connection)
      streamWriteInt32(streamId, networkGetObjectId(self.object));
      streamWriteBool(streamId, self.active);
end;
function Setblends2Event:run(connection)
      self.object:setblends2Visibility(self.active, true);
      if not connection:getIsServer() then
          g_server:broadcastEvent(Setblends2Event:new(self.object, self.active), nil, connection, self.object);
      end;
end;

Now for the vehicle.xml…..Open the xml with Notepad++ and insert these lines

<blends1>
     <blend1 index="0|0|0" />
     <blend1 index="1|0|0" />
 </blends1>
 <blends2>
     <blend2 index="2|0" />
     <blend2 index="3|0" />
 </blends2>

Make sure you substitute the index nodes you wrote down for the ones shown. Save and exit. Next is the modDesc.xml…first up is the extraSourceFiles. If your mod already has this section, copy and paste the lines only, otherwise copy the whole code block

<extraSourceFiles>
  <sourceFile filename="Scripts/Setblends1Event.lua" />
        <sourceFile filename="Scripts/Setblends2Event.lua" />
    </extraSourceFiles>

Specializations are next…again, if you have this section copy the single line only.

<specializations>
  <specialization name="Einblendung" className="Einblendung" filename="Scripts/Einblendung.lua" />
 </specializations>

Under vehicleTypes insert this line

<specialization name="Einblendung" />

Note that in the above codes, the folder named “Scripts” needs to be changed to whatever folder name you used. Here are the entries for the l10n section

<l10n>
  <text name="EinblendungZwei">
   <de>Hinzuf/Entfernen Hinterr</de>
   <en>Add/Remove Rear Wheels</en>
  </text>
     <text name="EinblendungEins">
   <de>Hinzuf/Entfernen Vorderr</de>
   <en>Add/Remove Front Wheels</en>
  </text>
 </l10n>

And finally, the inputBindings

<inputBindings>
      <input name="EinblendungZwei"    key1="KEY_KP_9"     button="" /> 
         <input name="EinblendungEins"    key1="KEY_KP_8"     button="" />
        </inputBindings>

Save the modDesc, exit NP++ and the mod should be ready for testing. If everything was done correctly, you should have something like this….
Image removed

Pressing Keypad 9…
Image removed

…and Keypad 8…
Image removed

So that's it for our Duals adventure. I hope this works for everyone, and if there are any issues, feel free to post your questions here.

Disclaimer: I take absolutely no credit for the scripts presented here. They are the property of their respective creators who are way smarter than me. I also accept no liability for any errors, game crashes or broken keyboards caused by using this tutorial. Caveat Emptor.

Update Draw function of the Einblendung.lua script has been updated so info now shows in the help box.


Original Author: Scorpion210 | Date: June 03, 2013

Modding Index | Vehicle Tutorials