Skip to content

Commit

Permalink
v0.4.0.0
Browse files Browse the repository at this point in the history
- testAreas are no longer needed!
- performance improvements (hopefully)
  • Loading branch information
RivalAUT committed Dec 3, 2020
1 parent ff323a0 commit 395c459
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.bat
*.png
*.docx
*.bak
Binary file modified FS19_HardiMega2200.zip
Binary file not shown.
Binary file modified FS19_SprayerSectionControl.zip
Binary file not shown.
32 changes: 15 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,40 +29,38 @@ The script alone does not give you any functionality, you need adapted sprayers
But as there is only one workArea for the full working width this is not possible.

### How you make sprayers compatible
**As of v0.4.0.0, creating testAreas is no longer needed!**

Converting sprayers to work with section control is not difficult. You need some entries in the XML and one workArea per section in the i3D.

**Warning: The HUD is restricted to 13 sections. If you have a sprayer with every spray nozzle as extra section you need to group the nozzles to bigger sections for a correct HUD display. In automatic mode, they will still be controlled separately.**
**Warning: The HUD is restricted to 13 sections. If you have more than 13 sections you need to group them for a correct HUD display. In automatic mode, they will still be controlled separately.**

#### i3D part
The workAreas need to be set up around each spraying section, with a little overlap to the next section.
It is also needed to create a testArea which is a little bigger by increasing the length in driving direction for 1m.

Image: *(testArea uses the height node of the workArea in this example.)*
![workArea setup](http://rival.bplaced.net/SSC_workArea2.png)
Create one workArea for each section you want to have and link them in the xml.
There is no limit of maximum sections. However, it is recommended to have less than 25 sections due to performance drops at high section counts.

#### XML part
The XML part is mainly copy-paste. The following lines need to be copied into the sprayer's XML file.
```
<sprayerSectionControl>
<sections>
<section workingWidth="3" workAreaId="1" effectNodeId="1" testAreaStartNode="testAreaStart1" testAreaWidthNode="testAreaWidth1" testAreaHeightNode="workAreaHeight1" />
<section workingWidth="3" workAreaId="2" effectNodeId="2" testAreaStartNode="testAreaStart2" testAreaWidthNode="testAreaWidth2" testAreaHeightNode="workAreaHeight2" />
<section workingWidth="2.5" workAreaId="3" effectNodeId="3" testAreaStartNode="testAreaStart3" testAreaWidthNode="testAreaWidth3" testAreaHeightNode="workAreaHeight3" />
<section workingWidth="2.5" workAreaId="4" effectNodeId="4" testAreaStartNode="testAreaStart4" testAreaWidthNode="testAreaWidth4" testAreaHeightNode="workAreaHeight4" />
<section workingWidth="2" workAreaId="5" effectNodeId="5" testAreaStartNode="testAreaStart5" testAreaWidthNode="testAreaWidth5" testAreaHeightNode="workAreaHeight5" />
<section workingWidth="2.5" workAreaId="6" effectNodeId="6" testAreaStartNode="testAreaStart6" testAreaWidthNode="testAreaWidth6" testAreaHeightNode="workAreaHeight6" />
<section workingWidth="2.5" workAreaId="7" effectNodeId="7" testAreaStartNode="testAreaStart7" testAreaWidthNode="testAreaWidth7" testAreaHeightNode="workAreaHeight7" />
<section workingWidth="3" workAreaId="8" effectNodeId="8" testAreaStartNode="testAreaStart8" testAreaWidthNode="testAreaWidth8" testAreaHeightNode="workAreaHeight8" />
<section workingWidth="3" workAreaId="9" effectNodeId="9" testAreaStartNode="testAreaStart9" testAreaWidthNode="testAreaWidth9" testAreaHeightNode="workAreaHeight9" />
</sections>
<section workingWidth="3" workAreaId="1" effectNodeId="1" />
<section workingWidth="3" workAreaId="2" effectNodeId="2" />
<section workingWidth="2.5" workAreaId="3" effectNodeId="3" />
<section workingWidth="2.5" workAreaId="4" effectNodeId="4" />
<section workingWidth="2" workAreaId="5" effectNodeId="5" />
<section workingWidth="2.5" workAreaId="6" effectNodeId="6" />
<section workingWidth="2.5" workAreaId="7" effectNodeId="7" />
<section workingWidth="3" workAreaId="8" effectNodeId="8" />
<section workingWidth="3" workAreaId="9" effectNodeId="9" />
</sections>
</sprayerSectionControl>
```
Although the entries should be self-explaining I will explain them for you:
- All sections get linked to their workAreas and effect nodes here.
- workingWidth is the working width of this section. All section working widths combined should be equal to the total working width (24m in this example). This is used for calculating the spray usage.
- workAreaId is the index of the workArea in the `<workAreas>` part. The first workArea has index/id 1.
- effectNodeId is the index of the effect node in the `<sprayer> <effects>` part. Again, the first effectNode has index/id 1. If more than one effectNodes are used for one section, you can add them like this: `effectNodeId="1 2 3 4"`
- testAreaStartNode / testAreaWidthNode / testAreaHeightNode are indices to the i3D node.
- To set up the groups mentioned earlier paste this before `</sprayerSectionControl>`:
```
<groups>
Expand Down
89 changes: 59 additions & 30 deletions SprayerSectionControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ end
function SprayerSectionControl.registerEventListeners(vehicleType)
SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", SprayerSectionControl)
SpecializationUtil.registerEventListener(vehicleType, "onLoad", SprayerSectionControl)
SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", SprayerSectionControl)
SpecializationUtil.registerEventListener(vehicleType, "onUpdate", SprayerSectionControl)
SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", SprayerSectionControl)
SpecializationUtil.registerEventListener(vehicleType, "onDraw", SprayerSectionControl)
SpecializationUtil.registerEventListener(vehicleType, "onPostAttach", SprayerSectionControl)
SpecializationUtil.registerEventListener(vehicleType, "onPreDetach", SprayerSectionControl)
Expand All @@ -63,6 +62,7 @@ function SprayerSectionControl.registerFunctions(vehicleType)
SpecializationUtil.registerFunction(vehicleType, "changeSectionGroupState", SprayerSectionControl.changeSectionGroupState)
SpecializationUtil.registerFunction(vehicleType, "toggleAutomaticMode", SprayerSectionControl.toggleAutomaticMode)
SpecializationUtil.registerFunction(vehicleType, "createSSCHUDElement", SprayerSectionControl.createSSCHUDElement)
SpecializationUtil.registerFunction(vehicleType, "createTestAreas", SprayerSectionControl.createTestAreas)
end

function SprayerSectionControl:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
Expand Down Expand Up @@ -104,20 +104,16 @@ function SprayerSectionControl:onLoad(savegame)
end
i = i + 1
local workAreaId = getXMLInt(self.xmlFile, key.."#workAreaId")
local testStart, testWidth, testHeight, coordinates = self:createTestAreas(workAreaId)
local effectNodes = StringUtil.getVectorNFromString(getXMLString(self.xmlFile, key.."#effectNodeId"))
local testAreaStart = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#testAreaStartNode"), self.i3dMappings)
local testAreaWidth = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#testAreaWidthNode"), self.i3dMappings)
local testAreaHeight = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#testAreaHeightNode"), self.i3dMappings)
local workingWidth = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#workingWidth"), 3)
if workAreaId == nil and self.spec_workArea.workAreas[i] ~= nil then
workAreaId = i
end
if workAreaId ~= nil and effectNodes ~= nil and testAreaStart ~= nil and testAreaWidth ~= nil and testAreaHeight ~= nil then
spec.sections[i] = {workAreaId=workAreaId, effectNodes=effectNodes, testAreaStart=testAreaStart, testAreaWidth=testAreaWidth, testAreaHeight=testAreaHeight, active=true, workingWidth = workingWidth}
self.spec_workArea.workAreas[workAreaId].sscId = i
spec.sections[i].sprayType = self.spec_workArea.workAreas[workAreaId].sprayType

if testStart ~= nil and testWidth ~= nil and testHeight ~= nil and effectNodes ~= nil then
spec.sections[i] = {workAreaId=workAreaId, effectNodes=effectNodes, testAreaStart=testStart, testAreaWidth=testWidth, testAreaHeight=testHeight, active=true, workingWidth = workingWidth, direction = 1, coordinates = coordinates}
self:getWorkAreaByIndex(workAreaId).sscId = i
spec.sections[i].sprayType = self:getWorkAreaByIndex(workAreaId).sprayType
else
print("Warning: Invalid sprayer section setup '"..key.."' in '" .. self.configFileName.."'")
print("Warning: Invalid sprayer section setup '"..key.."' in '" .. self.configFileName.."'!")
end
end
if hasXMLProperty(self.xmlFile, "vehicle.sprayerSectionControl.groups") then
Expand Down Expand Up @@ -231,18 +227,44 @@ function SprayerSectionControl:onLoad(savegame)
end
end

function SprayerSectionControl:onPostLoad(savegame)
if g_client.serverStreamId ~= 0 then
local spec = self.spec_ssc -- multiplayer --> make testAreas bigger
if spec.isSSCReady then
for k,section in pairs(spec.sections) do
local x, y, z = getTranslation(section.testAreaStart)
setTranslation(section.testAreaStart, x, y, z+0.8)
x, y, z = getTranslation(section.testAreaWidth)
setTranslation(section.testAreaWidth, x, y, z+0.8)
end
end
function SprayerSectionControl:createTestAreas(workAreaId)
local workArea = self:getWorkAreaByIndex(workAreaId)
if workArea == nil then
print(string.format("Error: workArea %d not found! Could not create testArea!", workareaId))
return
end
local parentNode = getParent(workArea.start)
local x1,y1,z1 = worldToLocal(parentNode, getWorldTranslation(workArea.start))
local x2,y2,z2 = worldToLocal(workArea.start, getWorldTranslation(workArea.width))
local x3,y3,z3 = worldToLocal(workArea.start, getWorldTranslation(workArea.height))
local max1 = math.max(z2,z3)
local adjust = g_client.serverStreamId ~= 0 and 1.8 or 1
if max1 == 0 then
z1 = z1 + adjust
end
if (z2 == max1 and max1 ~= 0) then
z2 = z2 + adjust
elseif (max1 == 0 and z2 < max1) then
z2 = z2 - adjust
end
if (z3 == max1 and max1 ~= 0) then
z3 = z3 + adjust
elseif (max1 == 0 and z3 < max1) then
z3 = z3 - adjust
end
local testAreaStartNode = createTransformGroup(string.format("testAreaStart%d", workAreaId))
setTranslation(testAreaStartNode, x1,y1,z1)
link(parentNode, testAreaStartNode)

local testAreaWidthNode = createTransformGroup(string.format("testAreaWidth%d", workAreaId))
setTranslation(testAreaWidthNode, x2,y2,z2)
link(testAreaStartNode, testAreaWidthNode)

local testAreaHeightNode = createTransformGroup(string.format("testAreaHeight%d", workAreaId))
setTranslation(testAreaHeightNode, x3,y3,z3)
link(testAreaStartNode, testAreaHeightNode)

return testAreaStartNode, testAreaWidthNode, testAreaHeightNode, {x1,y1,z1,adjust}
end

function SprayerSectionControl:createSSCHUDElement(image, x, y, hudScale, uvs, alignment, onClickCallback, sectionId)
Expand All @@ -267,7 +289,7 @@ function SprayerSectionControl:createSSCHUDElement(image, x, y, hudScale, uvs, a
return overlay, w, h
end

function SprayerSectionControl:onUpdate(dt)
function SprayerSectionControl:onUpdateTick(dt)
if self.spec_ssc.isSSCReady then
local spec = self.spec_ssc
if spec.isAutomaticMode and self:getIsTurnedOn() then
Expand All @@ -281,6 +303,16 @@ function SprayerSectionControl:onUpdate(dt)
end
end
if sActive then
if self.movingDirection == 1 and section.direction ~= 1 then -- if driving reverse, adjust testAreas to cover area behind sprayer
setTranslation(section.testAreaStart, section.coordinates[1], section.coordinates[2], section.coordinates[3])
section.direction = 1
elseif self.movingDirection == 0 and section.direction ~= 0 then
setTranslation(section.testAreaStart, section.coordinates[1], section.coordinates[2], section.coordinates[3]-section.coordinates[4]/2)
section.direction = 0
elseif self.movingDirection == -1 and section.direction ~= -1 then
setTranslation(section.testAreaStart, section.coordinates[1], section.coordinates[2], section.coordinates[3]-section.coordinates[4])
section.direction = -1
end
local fillType = self:getFillUnitLastValidFillType(self:getSprayerFillUnitIndex())
if fillType == FillType.UNKNOWN then
fillType = self:getFillUnitFirstSupportedFillType(self:getSprayerFillUnitIndex())
Expand Down Expand Up @@ -441,16 +473,13 @@ function SprayerSectionControl:onTurnedOff()
end

function SprayerSectionControl:doCheckSpeedLimit(superFunc)
if self:getActiveSprayerSectionsWidth() == 0 then
return false
end
return superFunc(self)
return superFunc(self) and self:getActiveSprayerSectionsWidth() > 0
end

function SprayerSectionControl:getSprayerUsage(superFunc, fillType, dt)
local origUsage = superFunc(self, fillType, dt)
if self.spec_ssc.isSSCReady then
return origUsage * self:getLastSpeed() / self.speedLimit * self:getActiveSprayerSectionsWidth() / self:getSprayerFullWidth()
return origUsage * (self:getLastSpeed() / self.speedLimit) * (self:getActiveSprayerSectionsWidth() / self:getSprayerFullWidth())
else
return origUsage
end
Expand Down
Binary file modified XML Helper/SSC_XML_Helper.exe
Binary file not shown.
Binary file modified XML Helper/XML Helper Manual.pdf
Binary file not shown.
4 changes: 4 additions & 0 deletions loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ end

VehicleTypeManager.validateVehicleTypes = Utils.prependedFunction(VehicleTypeManager.validateVehicleTypes, validateVehicleTypes)

--[[function SSCLoader:loadMap()
table.insert(g_storeManager:getItemByCustomEnvironment(modName).functions, g_i18n:getText("function_SprayerSectionControl_ready"))
end]]

function SSCLoader:mouseEvent(posX, posY, isDown, isUp, mouseKey)
if g_currentMission.paused or g_gui.currentGui ~= nil then return end

Expand Down
2 changes: 1 addition & 1 deletion modDesc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</en>
</description>
<author>Rival</author>
<version>0.3.2.0</version>
<version>0.4.0.0</version>
<iconFilename>icon.dds</iconFilename>
<multiplayer supported="true"/>

Expand Down

0 comments on commit 395c459

Please sign in to comment.