We've all gotten so used to the default grass crop that is built into FS22 that we don't realize that not only can we *change* that grass to look different, we can also add a second grass crop to our map and allow the player to plant whichever they want. Adding a new Grass crop is a relatively simple process with just a bit of Model editing in GE, and quite a bit of XML work. Let's get into it.
Download and Unzip the map you'd like to edit. I would suggest that on the map that is being edited (the "goal" map) that you immediately rename the map folder to something like FS22_MapName_EDIT to make sure that you don't have any conflicts. Be aware that renaming the folder will require a new savegame.
We're going to work directly in your mod folder, using the unzipped folder we just renamed. To make sure that it doesn't cause conflicts with the original zip file, I'd suggest moving the original zip to a different location. If they are both in the same savegame folder, it'll be hard to tell which you are loading when you load up the game, and if they are both named the same - the game will always use the zip file over a normal folder.
This might seem a bit daunting at first glace, but if you think about it, the game comes with three additional grass looks already - the three meadow types! Each of those meadow types has everything we need to make a grass that is unique from the typical "crop grass", with the addition of a bunch of flowers & extras. In this tutorial, we're going to setup some "Alpine Grass" based off of what was originally the Alpine DLC in FS19, included in FS22 with the Erlengrat map - but you could easily follow the exact same process using either of the other two meadow textures (meadowUS or meadowFR).
First off, we'll need to create somewhere to store our new foliage type. In our map folder, we'll create a few folders, ending up with a new folder with the following path: FS22_CalmLands_grassCrops\maps\foliage\grassAlpine. In the case of the map I'm editing, the \maps\map.xml file is in the \maps directory, and the new folders that we are creating should be created at the same level as that file, depending on how the map you are editing is setup.
Browse to your data directory, and find this folder: data\foliage\meadow which on my machine is here: C:\Program Files (x86)\Steam\steamapps\common\Farming Simulator 22\data\foliage\meadow. We're going to open the file meadowDLC.i3d in the Giant's Editor.
Once it's open, select "Save As..." from the menu, and save into the folder we created a minute ago. When you save the new file, save it as grassAlpine.i3d
We're not done yet! Next, let's delete all the things that make the meadow a meadow, leaving just the grassPure/ transform group.
Save and exit GE.
Last thing we need to do (I told you it was easy) is to copy the grass.xml file from the data directory over to our new grassAlpine/ folder.
Copy data\foliage\grass\grass.xml to FS22_MapName_EDIT\maps\foliage\grassAlpine\grassAlpine.xml. Then open that file in your code editor of choice and change the shapeSource to the i3d file to match your new i3d file we created just above.
<foliageLayer cellSize="8" objectMask="16711935" decalLayer="0" densityMapChannelOffset="0" numDensityMapChannels="4" numBlocksPerUnit="3.5" shapeSource="grassAlpine.i3d">
There are two ways to do this - but I've found that doing it the "code" way is a bit quicker and allows us to spend less time mucking around in the Giants Editor.
First, we open up the map.i3d file in our source code editor. Then, we'll search for "grass.xml". This is the first edit. Every map is different when we get into it, so we're not going to specify line numbers or anything - but the quick things you can search for.
<File fileId="327" filename="$data/foliage/grass/grass.xml"/>
That's the line you want, the path may be different if the map already has a custom grass texture, but what is there doesn't directly matter - we just have to copy that line and paste just below. After pasting, edit the line to reference the grassAlpine.xml file we created earlier, and update the fileId to be a very large number, say 99999. After editing, The file should look like this:
<File fileId="327" filename="$data/foliage/grass/grass.xml"/>
<File fileId="99999" filename="foliage/grassAlpine/grassAlpine.xml"/>
Let's search for the other place we need to edit. Search the same file for the string: "foliageXmlId="327"" which will be the place that is using fileId="327" from the grass file that we just edited above. It will look something like this:
<FoliageType name="grass" foliageXmlId="327"/>
We want to add another line to the bottom of the parent block for our new foliage type, but not right next to it. The reason it has to be at the bottom is that the game references these foliage layers in order - and if you change the order, then layers that were previously painted with anything below were you "insert" a new foliage layer will then be no longer in the correct order, which will cause all kinds of bad things to happen. Let's just put it at the bottom.
When you copy the line to the bottom of the block, make sure to use the same fileId ("99999") that you created above, and update the names to match. the name here ("grassAlpine") is crucial to be the same format everywhere. It'll look something like this when you're done:
<FoliageMultiLayer densityMapId="374" numChannels="10" numTypeIndexChannels="5" compressionChannels="5">
<FoliageType name="decoFoliage" foliageXmlId="323"/>
<FoliageType name="groundFoliage" foliageXmlId="324"/>
<FoliageType name="decoBush" foliageXmlId="325"/>
<FoliageType name="meadow" foliageXmlId="326"/>
<FoliageType name="grass" foliageXmlId="327"/>
<FoliageType name="wheat" foliageXmlId="328"/>
<FoliageType name="canola" foliageXmlId="329"/>
<FoliageType name="barley" foliageXmlId="330"/>
<FoliageType name="maize" foliageXmlId="331"/>
<FoliageType name="potato" foliageXmlId="332"/>
<FoliageType name="sugarBeet" foliageXmlId="333"/>
<FoliageType name="sunflower" foliageXmlId="334"/>
<FoliageType name="soybean" foliageXmlId="335"/>
<FoliageType name="oilseedRadish" foliageXmlId="336"/>
<FoliageType name="poplar" foliageXmlId="337"/>
<FoliageType name="oat" foliageXmlId="338"/>
<FoliageType name="sugarCane" foliageXmlId="339"/>
<FoliageType name="cotton" foliageXmlId="340"/>
<FoliageType name="sorghum" foliageXmlId="341"/>
<FoliageType name="olive" foliageXmlId="342"/>
<FoliageType name="grape" foliageXmlId="343"/>
<FoliageType name="decoFoliageUS" foliageXmlId="344"/>
<FoliageType name="grassAlpine" foliageXmlId="99999"/>
</FoliageMultiLayer>
The last step is to save what you've done, then open up the same file in the Giant's Editor... but don't do anything. Just hit Save, and close the window. When the Giants editor saves the file, it will crete a new fileId where needed replacing your temporary 99999 fileId with a better one. IF you still have this i3d file open in your source code editor, you may get a warning to reload the file which is expected - GE just updated things for you. IF you're curious, you can browse back up to the foliage layer that we created, and you should see the new fileId that GE gave us. Note that it may not be right next to the grass.xml file that we copied anymore, but this is expected.
<File fileId="345" filename="foliage/grassAlpine/grassAlpine.xml"/>
A small aside here - for each of these map edits for steps 4, 5 & 6 - your map may or may not have customized these files, and may be referring to basegame files. To overcome this, it's a two step process that is very easy.
To start with, we need to find out the name of the config file for the map. Not every map uses the convention map.xml, but to find where yours is, open up the modDesc.xml file at the root of the map mod, and look for a line that looks like this:
<map id="ModMap" className="Mission00" filename="$dataS/scripts/missions/mission00.lua" configFilename="maps/calmLands.xml" defaultVehiclesXMLFilename="maps/vehicles.xml" defaultPlaceablesXMLFilename="maps/placeables.xml" defaultItemsXMLFilename="maps/items.xml">
You want to look for the value of the configFilename property - whatever name that is not only tells you the root of your map folder (in this case maps/), but the name of the file that defines the configuration of your map. You can see from the above line that Calm Lands uses it's own clever name for the configFilename - but throughout this guide, we're going to continue to use map.xml when referring to the configFilename since it's the filename that Giants uses, but as you can see... it can be different!
Once you've found your map.xml file, and based on the step of the guide, you may see a line like this that the guide is suggesting that we should customize something inside that file, but the file that it's currently referring to a file in the $data directory.
(WARNING: don't edit in the $data directory - any changes there will apply to ALL MAPS)
<growth filename="$data/maps/maps_growth.xml" />
The change we need to do here is very easy.
First we Copy the file it's referring to from your $data directory, and put the same file in your local map directory. In my case, I copied C:\Program Files (x86)\Steam\steamapps\common\Farming Simulator 22\data\maps\maps_growth.xml to my own map directory FS22_CalmLands_grassCrops\maps\calmLands_growth.xml. To note - I named the file calmLands_growth.xml in this instance to stick with a naming convention of the map I'm editing, but normally I leave the file named as is: maps_growth.xml.
Then, once the copy is done, you will need to update the same line in your map.xml file to match the new location of the file. If you want (for safety) you can leave the old value commented out. (in XML that means to put <!-- before the line and --> after the line. This tells the xml file to ignore that line.)
Inside the map.xml file, the paths are relative to the root of your map folder.
<!-- <growth filename="$data/maps/maps_growth.xml" /> -->
<growth filename="maps/calmLands_growth.xml" />
Now that the model for the map knows about our new foliage layer - we need to tell the map itself how to convert that foliage layer into a crop that we can plant. This is done with the fruitTypes file. First ensure that your map has it's own version of the file (or follow the steps above). The line in map.xml should look like something like this:
<fruitTypes filename="maps/calmLands_fruitTypes.xml" />
Next, we open that file for editing, and find the block that defines the GRASS fruit type.
A note on case - In some places the game refers to the same string in either uppercase GRASS, lowercase grass or sometimes camelCased like oiseedRadish. The case doesn't matter - as long as the string is the same wherever it's referenced.
<fruitType name="grass" shownOnMap="true" useForFieldJob="false">
<general startStateChannel="0" numStateChannels="4" />
<cultivation needsSeeding="false" allowsSeeding="true" directionSnapAngle="0" alignsToSun="false" seedUsagePerSqm="0.03" plantsWeed="false"/>
<harvest minHarvestingGrowthState="3" maxHarvestingGrowthState="4" cutState="5" allowsPartialGrowthState="true" literPerSqm="3.28" />
<harvestGroundTypeChange groundType="GRASS_CUT" />
<growth witheredState="4" numGrowthStates="4" growthStateTime="36000000" resetsSpray="true" growthRequiresLime="false" regrows="true" firstRegrowthState="2" />
<growthGroundTypeChange state="2" groundType="GRASS" groundTypeMask="GRASS GRASS_CUT SOWN DIRECT_SOWN ROLLER_LINES" />
<windrow name="grass_windrow" litersPerSqm="4.37" />
<options lowSoilDensityRequired="false" increasesSoilDensity="false" consumesLime="false" startSprayState="1" />
<cropCare maxWeederState="0" maxWeederHoeState="0" />
<mapColors default="0.0423 0.1221 0.0252 1" colorBlind="1.0000 0.9473 0.0369 1"/>
<destruction canBeDestroyed="true" />
<mulcher state="1" hasChopperGroundLayer="false"/>
</fruitType>
That looks like a pretty heavy block of text, and there is lots to unpack there - we've talked about some of those things in other guides.
Today, we're just going to copy it, paste just below and change two things - the name... to "grassAlpine", and the cultivation setting for needsSeeding. We'll set that to "true", since we do want to plant this new crop since it won't exist on the map already.
I've also altered the mapColors slightly from the values that were there for "grass" so that there is a noticeable difference from the grass color.
<fruitType name="grassAlpine" shownOnMap="true" useForFieldJob="false">
<general startStateChannel="0" numStateChannels="4" />
<cultivation needsSeeding="true" allowsSeeding="true" directionSnapAngle="0" alignsToSun="false" seedUsagePerSqm="0.03" plantsWeed="false"/>
<harvest minHarvestingGrowthState="3" maxHarvestingGrowthState="4" cutState="5" allowsPartialGrowthState="true" literPerSqm="3.28" />
<harvestGroundTypeChange groundType="GRASS_CUT" />
<growth witheredState="4" numGrowthStates="4" growthStateTime="36000000" resetsSpray="true" growthRequiresLime="false" regrows="true" firstRegrowthState="2" />
<growthGroundTypeChange state="2" groundType="GRASS" groundTypeMask="GRASS GRASS_CUT SOWN DIRECT_SOWN ROLLER_LINES" />
<windrow name="grass_windrow" litersPerSqm="4.37" />
<options lowSoilDensityRequired="false" increasesSoilDensity="false" consumesLime="false" startSprayState="1" />
<cropCare maxWeederState="0" maxWeederHoeState="0" />
<mapColors default="0.0423 0.2 0.0252 1" colorBlind="1.0000 0.8 0.0369 1"/>
<destruction canBeDestroyed="true" />
<mulcher state="1" hasChopperGroundLayer="false"/>
</fruitType>
Now we need to make sure we can use that fruitType in all the places where it needs to be used. That is controlled at the end of the file with the <fruitTypeCategories> and the <fruitTypeConverters>.
For the <fruitTypeCategories> since we know we want GRASSALPINE to work the same as GRASS, the easiest way to make the right change is to do a FIND-REPLACE for "GRASS" to replace with "GRASS GRASSALPINE". The resulting block should look like this:
<fruitTypeCategories>
<fruitTypeCategory name="GRAINHEADER" >WHEAT BARLEY OAT CANOLA SOYBEAN SORGHUM</fruitTypeCategory>
<fruitTypeCategory name="MAIZEHEADER" >MAIZE SUNFLOWER</fruitTypeCategory>
<fruitTypeCategory name="MAIZECUTTER" >MAIZE WHEAT BARLEY OAT CANOLA SOYBEAN SORGHUM SUNFLOWER</fruitTypeCategory>
<fruitTypeCategory name="DIRECTCUTTER" >GRASS GRASSALPINE WHEAT BARLEY OAT CANOLA SOYBEAN SORGHUM SUNFLOWER</fruitTypeCategory>
<fruitTypeCategory name="PICKUP" >GRASS GRASSALPINE</fruitTypeCategory>
<fruitTypeCategory name="SOWINGMACHINE" >WHEAT BARLEY OAT CANOLA SOYBEAN SORGHUM OILSEEDRADISH GRASS GRASSALPINE</fruitTypeCategory>
<fruitTypeCategory name="SUGARCANE_PLANTER" >SUGARCANE</fruitTypeCategory>
<fruitTypeCategory name="PLANTER" >MAIZE SUNFLOWER SOYBEAN SUGARBEET COTTON</fruitTypeCategory>
<fruitTypeCategory name="WEEDER" >OILSEEDRADISH GRASS GRASSALPINE</fruitTypeCategory>
</fruitTypeCategories>
For <fruitTypeConverters> we will do roughly the same thing, where we want to setup GRASSALPINE to work the same as GRASS. In this instace, we'll copy the lines that specify how to convert GRASS and create the same line for GRASSALPINE.
<fruitTypeConverters>
<fruitTypeConverter name="FORAGEHARVESTER">
<converter from="MAIZE" to="CHAFF" factor="7.8" />
<converter from="GRASS" to="GRASS_WINDROW" factor="1.0" windrowFactor="1.0" />
<converter from="GRASSALPINE" to="GRASS_WINDROW" factor="1.2" windrowFactor="1.0" />
...
</fruitTypeConverter>
<fruitTypeConverter name="MOWER">
<converter from="GRASS" to="GRASS_WINDROW" factor="1.0" windrowFactor="1.0" />
<converter from="GRASSALPINE" to="GRASS_WINDROW" factor="1.2" windrowFactor="1.0" />
<converter from="MEADOW" to="GRASS_WINDROW" factor="1.0" windrowFactor="1.0" />
...
</fruitTypeConverter>
</fruitTypeConverters>
This is one of the places where we can give the player a reason for planing one type of GRASS over the other. In this case, I've updated the factor here when harvesting with a MOWER or FORAGEHARVESTER to have a bit more output when using the GRASSALPINE since it's a bit taller than regular grass.
The change for fillTypes is about the same as for fruitTypes , where we're copying what is there for GRASS and adding a new line for GRASSALPINE. The reason we edit the fillType file is not directly for having GRASSALPINE as a fillType (because it never will be), but primarily to define the icon that is displayed in the store & map screens. This is done with the fillTypes file. First ensure that your map has it's own version of this file (or follow the steps above). The line in map.xml should look like something like this:
<fillTypes filename="maps/calmLands_fillTypes.xml" />
Next, we open that file for editing, and find the block that defines the GRASS fillType.
<fillType name="GRASS" title="$l10n_fillType_grass" showOnPriceTable="false" unitShort="$l10n_unit_literShort">
<physics massPerLiter="0.30" maxPhysicalSurfaceAngle="50" />
<economy pricePerLiter="0.048">
<factors>
<factor period="1" value="1.05" />
<factor period="2" value="1.02" />
<factor period="3" value="0.96" />
<factor period="4" value="0.93" />
<factor period="5" value="0.9" />
<factor period="6" value="0.9" />
<factor period="7" value="0.93" />
<factor period="8" value="0.99" />
<factor period="9" value="1.05" />
<factor period="10" value="1.08" />
<factor period="11" value="1.11" />
<factor period="12" value="1.11" />
</factors>
</economy>
<effects fruitSmokeColor="0.0970 0.1130 0.0171 1.0000"/>
<image hud="$dataS/menu/hud/fillTypes/hud_fill_grass.png" />
</fillType>
We don't need the details of the economy section, but we do need the rest. We'll replace GRASS with and update the image to a new hud image. The resulting block should look like the following:
<fillType name="GRASSALPINE" title="$l10n_fillType_grassAlpine" showOnPriceTable="false" unitShort="$l10n_unit_literShort">
<physics massPerLiter="0.30" maxPhysicalSurfaceAngle="50" />
<economy pricePerLiter="0.048" />
<effects fruitSmokeColor="0.0970 0.1130 0.0171 1.0000"/>
<image hud="maps/foliage/grassAlpine/hud_fill_grassAlpine.png" />
</fillType>
Don't forget to add the proper l10n translations to the modDesc.xml; we do things the right way in these guides even if it's a bit more work.
<l10n>
<text name="fillType_grassAlpine">
<en>Alpine Grass</en>
<de>Alpengras</de>
<es>Hierba Alpina</es>
</text>
</l10n>
For the hud image (the image shown as the crop type when planting & in on the map screen) above - we copied the grass icon and edited the icon in a photo editor to flip it and recolor so that it's noticeably different. Feel free to download and use the same graphic in your map.
That's it for the fillTypes file - all of the items at the bottom for <fillTypeCategories> and <fillTypeSounds> are there for fillTypes that can actually be put into containers. Since this fillType always gets converted to GRASS_WINDROW, it'll never need to be visible in any container.
The last thing we need for any crop is to define when it is planted and how it grows. This is done through the growth file. Just like in step 4 & 5, ensure that your map has it's own version of this file (or follow the steps above). The line in map.xml should look like something like this:
<growth filename="maps/calmLands_growth.xml" />
Just like the previous two steps, we're going to copy the existing GRASS setup for our new GRASS type. To make things a bit more fun and entertaining I've updated the growth chart for GRASSALPINE to be a bit more weighted towards the wintertime.
<fruit name="grassAlpine" initialState="1-4">
<period index="1">
<update range="2" add="1" />
</period>
<period index="2" plantingAllowed="true">
<update range="1" add="1" />
<update range="3" add="1" />
<update range="5" set="2" />
</period>
<period index="3" plantingAllowed="true">
<update range="1-3" add="1" />
<update range="5" set="2" />
</period>
<period index="4" plantingAllowed="true">
<update range="1-3" add="1" />
<update range="5" set="2" />
</period>
<period index="5" plantingAllowed="true">
<update range="1-3" add="1" />
<update range="5" set="2" />
</period>
<period index="6" plantingAllowed="true">
<update range="1-3" add="1" />
<update range="5" set="2" />
</period>
<period index="7" plantingAllowed="true">
<update range="1-3" add="1" />
<update range="5" set="2" />
</period>
<period index="8" plantingAllowed="true">
<update range="1-3" add="1" />
<update range="5" set="2" />
</period>
<period index="9" plantingAllowed="true">
<update range="1-3" add="1" />
<update range="5" set="2" />
</period>
<period index="10" plantingAllowed="true">
<update range="1" add="1" />
<update range="4" set="3" /><!-- knock back due to winter -->
</period>
<period index="11">
</period>
<period index="12">
</period>
</fruit>
The changes above are everything that is needed for this change. Adding a new crop doesn't completely require a new savegame, but it's recommended. Go ahead and load into the game and try it out!
The updated growth chart showing our new fruit
Freshly Mown > Stage 2 > Stage 3 > Ready to Harvest (4)
The map view on Calm Lands, showing the two types of grass
A final view of the fully grown grass side by side in the early morning on Calm Lands
It's up to you to decide how to modify the new fillType, fruitType and greowth setting above to give the end user a reason to grow your new grass type over the basegame GRASS.