Skip to content

Commit 395c459

Browse files
committed
v0.4.0.0
- testAreas are no longer needed! - performance improvements (hopefully)
1 parent ff323a0 commit 395c459

File tree

9 files changed

+80
-48
lines changed

9 files changed

+80
-48
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
*.bat
33
*.png
44
*.docx
5+
*.bak

FS19_HardiMega2200.zip

-243 Bytes
Binary file not shown.

FS19_SprayerSectionControl.zip

475 Bytes
Binary file not shown.

README.md

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,40 +29,38 @@ The script alone does not give you any functionality, you need adapted sprayers
2929
But as there is only one workArea for the full working width this is not possible.
3030

3131
### How you make sprayers compatible
32+
**As of v0.4.0.0, creating testAreas is no longer needed!**
33+
3234
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.
3335

34-
**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.**
36+
**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.**
3537

3638
#### i3D part
37-
The workAreas need to be set up around each spraying section, with a little overlap to the next section.
38-
It is also needed to create a testArea which is a little bigger by increasing the length in driving direction for 1m.
39-
40-
Image: *(testArea uses the height node of the workArea in this example.)*
41-
![workArea setup](http://rival.bplaced.net/SSC_workArea2.png)
39+
Create one workArea for each section you want to have and link them in the xml.
40+
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.
4241

4342
#### XML part
4443
The XML part is mainly copy-paste. The following lines need to be copied into the sprayer's XML file.
4544
```
4645
<sprayerSectionControl>
4746
<sections>
48-
<section workingWidth="3" workAreaId="1" effectNodeId="1" testAreaStartNode="testAreaStart1" testAreaWidthNode="testAreaWidth1" testAreaHeightNode="workAreaHeight1" />
49-
<section workingWidth="3" workAreaId="2" effectNodeId="2" testAreaStartNode="testAreaStart2" testAreaWidthNode="testAreaWidth2" testAreaHeightNode="workAreaHeight2" />
50-
<section workingWidth="2.5" workAreaId="3" effectNodeId="3" testAreaStartNode="testAreaStart3" testAreaWidthNode="testAreaWidth3" testAreaHeightNode="workAreaHeight3" />
51-
<section workingWidth="2.5" workAreaId="4" effectNodeId="4" testAreaStartNode="testAreaStart4" testAreaWidthNode="testAreaWidth4" testAreaHeightNode="workAreaHeight4" />
52-
<section workingWidth="2" workAreaId="5" effectNodeId="5" testAreaStartNode="testAreaStart5" testAreaWidthNode="testAreaWidth5" testAreaHeightNode="workAreaHeight5" />
53-
<section workingWidth="2.5" workAreaId="6" effectNodeId="6" testAreaStartNode="testAreaStart6" testAreaWidthNode="testAreaWidth6" testAreaHeightNode="workAreaHeight6" />
54-
<section workingWidth="2.5" workAreaId="7" effectNodeId="7" testAreaStartNode="testAreaStart7" testAreaWidthNode="testAreaWidth7" testAreaHeightNode="workAreaHeight7" />
55-
<section workingWidth="3" workAreaId="8" effectNodeId="8" testAreaStartNode="testAreaStart8" testAreaWidthNode="testAreaWidth8" testAreaHeightNode="workAreaHeight8" />
56-
<section workingWidth="3" workAreaId="9" effectNodeId="9" testAreaStartNode="testAreaStart9" testAreaWidthNode="testAreaWidth9" testAreaHeightNode="workAreaHeight9" />
57-
</sections>
47+
<section workingWidth="3" workAreaId="1" effectNodeId="1" />
48+
<section workingWidth="3" workAreaId="2" effectNodeId="2" />
49+
<section workingWidth="2.5" workAreaId="3" effectNodeId="3" />
50+
<section workingWidth="2.5" workAreaId="4" effectNodeId="4" />
51+
<section workingWidth="2" workAreaId="5" effectNodeId="5" />
52+
<section workingWidth="2.5" workAreaId="6" effectNodeId="6" />
53+
<section workingWidth="2.5" workAreaId="7" effectNodeId="7" />
54+
<section workingWidth="3" workAreaId="8" effectNodeId="8" />
55+
<section workingWidth="3" workAreaId="9" effectNodeId="9" />
56+
</sections>
5857
</sprayerSectionControl>
5958
```
6059
Although the entries should be self-explaining I will explain them for you:
6160
- All sections get linked to their workAreas and effect nodes here.
6261
- 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.
6362
- workAreaId is the index of the workArea in the `<workAreas>` part. The first workArea has index/id 1.
6463
- 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"`
65-
- testAreaStartNode / testAreaWidthNode / testAreaHeightNode are indices to the i3D node.
6664
- To set up the groups mentioned earlier paste this before `</sprayerSectionControl>`:
6765
```
6866
<groups>

SprayerSectionControl.lua

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ end
4040
function SprayerSectionControl.registerEventListeners(vehicleType)
4141
SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", SprayerSectionControl)
4242
SpecializationUtil.registerEventListener(vehicleType, "onLoad", SprayerSectionControl)
43-
SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", SprayerSectionControl)
44-
SpecializationUtil.registerEventListener(vehicleType, "onUpdate", SprayerSectionControl)
43+
SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", SprayerSectionControl)
4544
SpecializationUtil.registerEventListener(vehicleType, "onDraw", SprayerSectionControl)
4645
SpecializationUtil.registerEventListener(vehicleType, "onPostAttach", SprayerSectionControl)
4746
SpecializationUtil.registerEventListener(vehicleType, "onPreDetach", SprayerSectionControl)
@@ -63,6 +62,7 @@ function SprayerSectionControl.registerFunctions(vehicleType)
6362
SpecializationUtil.registerFunction(vehicleType, "changeSectionGroupState", SprayerSectionControl.changeSectionGroupState)
6463
SpecializationUtil.registerFunction(vehicleType, "toggleAutomaticMode", SprayerSectionControl.toggleAutomaticMode)
6564
SpecializationUtil.registerFunction(vehicleType, "createSSCHUDElement", SprayerSectionControl.createSSCHUDElement)
65+
SpecializationUtil.registerFunction(vehicleType, "createTestAreas", SprayerSectionControl.createTestAreas)
6666
end
6767

6868
function SprayerSectionControl:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
@@ -104,20 +104,16 @@ function SprayerSectionControl:onLoad(savegame)
104104
end
105105
i = i + 1
106106
local workAreaId = getXMLInt(self.xmlFile, key.."#workAreaId")
107+
local testStart, testWidth, testHeight, coordinates = self:createTestAreas(workAreaId)
107108
local effectNodes = StringUtil.getVectorNFromString(getXMLString(self.xmlFile, key.."#effectNodeId"))
108-
local testAreaStart = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#testAreaStartNode"), self.i3dMappings)
109-
local testAreaWidth = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#testAreaWidthNode"), self.i3dMappings)
110-
local testAreaHeight = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#testAreaHeightNode"), self.i3dMappings)
111109
local workingWidth = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#workingWidth"), 3)
112-
if workAreaId == nil and self.spec_workArea.workAreas[i] ~= nil then
113-
workAreaId = i
114-
end
115-
if workAreaId ~= nil and effectNodes ~= nil and testAreaStart ~= nil and testAreaWidth ~= nil and testAreaHeight ~= nil then
116-
spec.sections[i] = {workAreaId=workAreaId, effectNodes=effectNodes, testAreaStart=testAreaStart, testAreaWidth=testAreaWidth, testAreaHeight=testAreaHeight, active=true, workingWidth = workingWidth}
117-
self.spec_workArea.workAreas[workAreaId].sscId = i
118-
spec.sections[i].sprayType = self.spec_workArea.workAreas[workAreaId].sprayType
110+
111+
if testStart ~= nil and testWidth ~= nil and testHeight ~= nil and effectNodes ~= nil then
112+
spec.sections[i] = {workAreaId=workAreaId, effectNodes=effectNodes, testAreaStart=testStart, testAreaWidth=testWidth, testAreaHeight=testHeight, active=true, workingWidth = workingWidth, direction = 1, coordinates = coordinates}
113+
self:getWorkAreaByIndex(workAreaId).sscId = i
114+
spec.sections[i].sprayType = self:getWorkAreaByIndex(workAreaId).sprayType
119115
else
120-
print("Warning: Invalid sprayer section setup '"..key.."' in '" .. self.configFileName.."'")
116+
print("Warning: Invalid sprayer section setup '"..key.."' in '" .. self.configFileName.."'!")
121117
end
122118
end
123119
if hasXMLProperty(self.xmlFile, "vehicle.sprayerSectionControl.groups") then
@@ -231,18 +227,44 @@ function SprayerSectionControl:onLoad(savegame)
231227
end
232228
end
233229

234-
function SprayerSectionControl:onPostLoad(savegame)
235-
if g_client.serverStreamId ~= 0 then
236-
local spec = self.spec_ssc -- multiplayer --> make testAreas bigger
237-
if spec.isSSCReady then
238-
for k,section in pairs(spec.sections) do
239-
local x, y, z = getTranslation(section.testAreaStart)
240-
setTranslation(section.testAreaStart, x, y, z+0.8)
241-
x, y, z = getTranslation(section.testAreaWidth)
242-
setTranslation(section.testAreaWidth, x, y, z+0.8)
243-
end
244-
end
230+
function SprayerSectionControl:createTestAreas(workAreaId)
231+
local workArea = self:getWorkAreaByIndex(workAreaId)
232+
if workArea == nil then
233+
print(string.format("Error: workArea %d not found! Could not create testArea!", workareaId))
234+
return
235+
end
236+
local parentNode = getParent(workArea.start)
237+
local x1,y1,z1 = worldToLocal(parentNode, getWorldTranslation(workArea.start))
238+
local x2,y2,z2 = worldToLocal(workArea.start, getWorldTranslation(workArea.width))
239+
local x3,y3,z3 = worldToLocal(workArea.start, getWorldTranslation(workArea.height))
240+
local max1 = math.max(z2,z3)
241+
local adjust = g_client.serverStreamId ~= 0 and 1.8 or 1
242+
if max1 == 0 then
243+
z1 = z1 + adjust
245244
end
245+
if (z2 == max1 and max1 ~= 0) then
246+
z2 = z2 + adjust
247+
elseif (max1 == 0 and z2 < max1) then
248+
z2 = z2 - adjust
249+
end
250+
if (z3 == max1 and max1 ~= 0) then
251+
z3 = z3 + adjust
252+
elseif (max1 == 0 and z3 < max1) then
253+
z3 = z3 - adjust
254+
end
255+
local testAreaStartNode = createTransformGroup(string.format("testAreaStart%d", workAreaId))
256+
setTranslation(testAreaStartNode, x1,y1,z1)
257+
link(parentNode, testAreaStartNode)
258+
259+
local testAreaWidthNode = createTransformGroup(string.format("testAreaWidth%d", workAreaId))
260+
setTranslation(testAreaWidthNode, x2,y2,z2)
261+
link(testAreaStartNode, testAreaWidthNode)
262+
263+
local testAreaHeightNode = createTransformGroup(string.format("testAreaHeight%d", workAreaId))
264+
setTranslation(testAreaHeightNode, x3,y3,z3)
265+
link(testAreaStartNode, testAreaHeightNode)
266+
267+
return testAreaStartNode, testAreaWidthNode, testAreaHeightNode, {x1,y1,z1,adjust}
246268
end
247269

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

270-
function SprayerSectionControl:onUpdate(dt)
292+
function SprayerSectionControl:onUpdateTick(dt)
271293
if self.spec_ssc.isSSCReady then
272294
local spec = self.spec_ssc
273295
if spec.isAutomaticMode and self:getIsTurnedOn() then
@@ -281,6 +303,16 @@ function SprayerSectionControl:onUpdate(dt)
281303
end
282304
end
283305
if sActive then
306+
if self.movingDirection == 1 and section.direction ~= 1 then -- if driving reverse, adjust testAreas to cover area behind sprayer
307+
setTranslation(section.testAreaStart, section.coordinates[1], section.coordinates[2], section.coordinates[3])
308+
section.direction = 1
309+
elseif self.movingDirection == 0 and section.direction ~= 0 then
310+
setTranslation(section.testAreaStart, section.coordinates[1], section.coordinates[2], section.coordinates[3]-section.coordinates[4]/2)
311+
section.direction = 0
312+
elseif self.movingDirection == -1 and section.direction ~= -1 then
313+
setTranslation(section.testAreaStart, section.coordinates[1], section.coordinates[2], section.coordinates[3]-section.coordinates[4])
314+
section.direction = -1
315+
end
284316
local fillType = self:getFillUnitLastValidFillType(self:getSprayerFillUnitIndex())
285317
if fillType == FillType.UNKNOWN then
286318
fillType = self:getFillUnitFirstSupportedFillType(self:getSprayerFillUnitIndex())
@@ -441,16 +473,13 @@ function SprayerSectionControl:onTurnedOff()
441473
end
442474

443475
function SprayerSectionControl:doCheckSpeedLimit(superFunc)
444-
if self:getActiveSprayerSectionsWidth() == 0 then
445-
return false
446-
end
447-
return superFunc(self)
476+
return superFunc(self) and self:getActiveSprayerSectionsWidth() > 0
448477
end
449478

450479
function SprayerSectionControl:getSprayerUsage(superFunc, fillType, dt)
451480
local origUsage = superFunc(self, fillType, dt)
452481
if self.spec_ssc.isSSCReady then
453-
return origUsage * self:getLastSpeed() / self.speedLimit * self:getActiveSprayerSectionsWidth() / self:getSprayerFullWidth()
482+
return origUsage * (self:getLastSpeed() / self.speedLimit) * (self:getActiveSprayerSectionsWidth() / self:getSprayerFullWidth())
454483
else
455484
return origUsage
456485
end

XML Helper/SSC_XML_Helper.exe

-2.5 KB
Binary file not shown.

XML Helper/XML Helper Manual.pdf

-12.8 KB
Binary file not shown.

loader.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ end
2828

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

31+
--[[function SSCLoader:loadMap()
32+
table.insert(g_storeManager:getItemByCustomEnvironment(modName).functions, g_i18n:getText("function_SprayerSectionControl_ready"))
33+
end]]
34+
3135
function SSCLoader:mouseEvent(posX, posY, isDown, isUp, mouseKey)
3236
if g_currentMission.paused or g_gui.currentGui ~= nil then return end
3337

modDesc.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
</en>
1212
</description>
1313
<author>Rival</author>
14-
<version>0.3.2.0</version>
14+
<version>0.4.0.0</version>
1515
<iconFilename>icon.dds</iconFilename>
1616
<multiplayer supported="true"/>
1717

0 commit comments

Comments
 (0)