LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

Leveler

Description
Specialization for levelers for distributing silage/chaff in bunker silos
Functions

getIsLevelerPickupNodeActive

Description
Returns true if leveler pickup node is active
Definition
getIsLevelerPickupNodeActive(table levelerNode)
Arguments
tablelevelerNodepickup node data
Return Values
booleanisActivepickup node is active
Code
269function Leveler:getIsLevelerPickupNodeActive(levelerNode)
270 return true
271end

loadLevelerNodeFromXML

Description
Loads leveler node from xml
Definition
loadLevelerNodeFromXML(table levelerNode, integer xmlFile, string key)
Arguments
tablelevelerNodeleveler node data
integerxmlFileid of xml object
stringkeykey
Return Values
booleansuccesssuccess
Code
241function Leveler:loadLevelerNodeFromXML(levelerNode, xmlFile, key)
242 levelerNode.node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, key .. "#node"), self.i3dMappings)
243 if levelerNode.node ~= nil then
244 levelerNode.width = getXMLFloat(xmlFile, key .. "#width")
245
246 levelerNode.minDropWidth = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#minDropWidth"), levelerNode.width*0.5)
247 levelerNode.maxDropWidth = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#maxDropWidth"), levelerNode.width)
248 levelerNode.minDropHeight = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#minDropHeight"), 0)
249 levelerNode.maxDropHeight = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#maxDropHeight"), 1)
250 levelerNode.minDropDirOffset = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#minDropDirOffset"), 0.7)
251 levelerNode.maxDropDirOffset = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#maxDropDirOffset"), 0.7)
252 levelerNode.numHeightLimitChecks = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#numHeightLimitChecks"), 6)
253
254 levelerNode.lineOffsetPickUp = nil
255 levelerNode.lineOffsetDrop = nil
256
257 levelerNode.lastPickUp = 0
258 levelerNode.lastDrop = 0
259 return true
260 end
261
262 return false
263end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
38function Leveler:onLoad(savegame)
39 local spec = self.spec_leveler
40
41 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.leveler.levelerNode#index", "vehicle.leveler.levelerNode#node") -- FS17
42 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.levelerEffects", "vehicle.leveler.effects") -- FS17
43
44 spec.nodes = {}
45 local i = 0
46 while true do
47 local key = string.format("vehicle.leveler.levelerNode(%d)", i)
48 if not hasXMLProperty(self.xmlFile, key) then
49 break
50 end
51
52 local levelerNode = {}
53 if self:loadLevelerNodeFromXML(levelerNode, self.xmlFile, key) then
54 table.insert(spec.nodes, levelerNode)
55 end
56 i = i + 1
57 end
58
59 spec.pickUpDirection = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.leveler.pickUpDirection"), 1.0)
60 spec.fillUnitIndex = getXMLInt(self.xmlFile, "vehicle.leveler#fillUnitIndex")
61 spec.litersToPickup = 0
62 if not self:getFillUnitExists(spec.fillUnitIndex) then
63 g_logManager:xmlWarning(self.configFileName, "Unknown fillUnitIndex '%s' for leveler", tostring(spec.fillUnitIndex))
64 end
65
66 if self.isClient then
67 spec.effects = g_effectManager:loadEffect(self.xmlFile, "vehicle.leveler.effects", self.components, self, self.i3dMappings)
68 end
69end

onUpdate

Description
Called on update
Definition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
76function Leveler:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
77 local spec = self.spec_leveler
78
79 if self.isClient then
80 local fillType = self:getFillUnitFillType(spec.fillUnitIndex)
81 local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
82 local visible = fillLevel > 2*g_densityMapHeightManager:getMinValidLiterValue(fillType)
83 if visible and fillType ~= FillType.UNKNOWN then
84 g_effectManager:setFillType(spec.effects, fillType)
85 g_effectManager:startEffects(spec.effects)
86
87 local fillPercentage = fillLevel / self:getFillUnitCapacity(spec.fillUnitIndex)
88 for _, effect in pairs(spec.effects) do
89 effect:setFillLevel(fillPercentage)
90 effect:setLastVehicleSpeed(self.movingDirection * self:getLastSpeed())
91 end
92 else
93 g_effectManager:stopEffects(spec.effects)
94 end
95 end
96
97 if self.isServer then
98 for _, levelerNode in pairs(spec.nodes) do
99 local x0,y0,z0 = localToWorld(levelerNode.node, -levelerNode.width, 0, levelerNode.maxDropDirOffset)
100 local x1,y1,z1 = localToWorld(levelerNode.node, levelerNode.width, 0, levelerNode.maxDropDirOffset)
101 if not g_farmlandManager:getIsOwnedByFarmAtWorldPosition(self:getOwnerFarmId(), x0, z0) or
102 not g_farmlandManager:getIsOwnedByFarmAtWorldPosition(self:getOwnerFarmId(), x1, z1) then
103 break
104 end
105
106 local pickedUpFillLevel = 0
107 local fillType = self:getFillUnitFillType(spec.fillUnitIndex)
108 local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
109
110 if fillType == FillType.UNKNOWN or fillLevel < g_densityMapHeightManager:getMinValidLiterValue(fillType) + 0.001 then
111 local newFillType = DensityMapHeightUtil.getFillTypeAtLine(x0,y0,z0, x1,y1,z1, 0.5*levelerNode.maxDropDirOffset)
112 if newFillType ~= FillType.UNKNOWN and newFillType ~= fillType then
113 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -math.huge)
114 fillType = newFillType
115 end
116 end
117 local heightType = g_densityMapHeightManager:getDensityMapHeightTypeByFillTypeIndex(fillType)
118
119 if fillType ~= FillType.UNKNOWN and heightType ~= nil then
120 local innerRadius = 0
121 local outerRadius = DensityMapHeightUtil.getDefaultMaxRadius(fillType)
122 local capacity = self:getFillUnitCapacity(spec.fillUnitIndex)
123
124 -- pick up at node
125 if self:getIsLevelerPickupNodeActive(levelerNode) then
126 if spec.pickUpDirection == self.movingDirection then
127 local sx,sy,sz = localToWorld(levelerNode.node, -levelerNode.width, 0, 0)
128 local ex,ey,ez = localToWorld(levelerNode.node, levelerNode.width, 0, 0)
129
130 fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
131 local delta = -(capacity-fillLevel)
132 local numHeightLimitChecks = levelerNode.numHeightLimitChecks
133 if numHeightLimitChecks > 0 then
134 local movementY = 0
135 for i=0,numHeightLimitChecks do
136 local t = i/numHeightLimitChecks
137 local xi = sx + (ex-sx)*t
138 local yi = sy + (ey-sy)*t
139 local zi = sz + (ez-sz)*t
140 local hi = DensityMapHeightUtil.getHeightAtWorldPos(xi,yi,zi)
141 movementY = math.max(movementY, hi-0.05 - yi) -- limit to 5cm below surface
142 end
143 if movementY > 0 then
144 sy = sy+movementY
145 ey = ey+movementY
146 end
147 end
148
149 levelerNode.lastPickUp, levelerNode.lineOffsetPickUp = DensityMapHeightUtil.tipToGroundAroundLine(self, delta, fillType, sx,sy-0.1,sz, ex,ey-0.1,ez, innerRadius, outerRadius, levelerNode.lineOffsetPickUp, true, nil)
150
151 if levelerNode.lastPickUp < 0 then
152 levelerNode.lastPickUp = levelerNode.lastPickUp + spec.litersToPickup
153 spec.litersToPickup = 0
154
155 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -levelerNode.lastPickUp, fillType, ToolType.UNDEFINED, nil)
156 pickedUpFillLevel = levelerNode.lastPickUp
157 end
158 end
159 end
160
161 -- drop at node
162 fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
163 if fillLevel > 0 then
164 local f = (fillLevel/capacity)
165 local width = MathUtil.lerp(levelerNode.minDropWidth, levelerNode.maxDropWidth, f)
166
167 local sx,sy,sz = localToWorld(levelerNode.node, -width, 0, 0)
168 local ex,ey,ez = localToWorld(levelerNode.node, width, 0, 0)
169
170 local yOffset = -0.1 -0.05
171
172 levelerNode.lastDrop1, levelerNode.lineOffsetDrop1 = DensityMapHeightUtil.tipToGroundAroundLine(self, fillLevel, fillType, sx,sy+yOffset,sz, ex,ey+yOffset,ez, innerRadius, outerRadius, levelerNode.lineOffsetDrop1, true, tipOcclusionAreas)
173 if levelerNode.lastDrop1 > 0 then
174 local leftOver = fillLevel - levelerNode.lastDrop1
175 if leftOver <= g_densityMapHeightManager:getMinValidLiterValue(fillType) then
176 levelerNode.lastDrop1 = fillLevel
177 spec.litersToPickup = spec.litersToPickup + leftOver
178 end
179 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -levelerNode.lastDrop1, fillType, ToolType.UNDEFINED, nil)
180 end
181 end
182
183 -- drop further at front
184 fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
185
186 if fillLevel > 0 then
187 local f = (fillLevel/capacity)
188 local width = MathUtil.lerp(levelerNode.minDropWidth, levelerNode.maxDropWidth, f)
189
190 local yOffset = MathUtil.lerp(levelerNode.minDropHeight, levelerNode.maxDropHeight, f)
191
192 local sx,sy,sz = localToWorld(levelerNode.node, -width, 0, 0)
193 local ex,ey,ez = localToWorld(levelerNode.node, width, 0, 0)
194 local dx,dy,dz = localDirectionToWorld(levelerNode.node, 0, 0, 1)
195
196 local backOffset = -outerRadius * spec.pickUpDirection * 1.5
197 local backLen = MathUtil.lerp(levelerNode.minDropDirOffset, levelerNode.maxDropDirOffset, f) - backOffset
198
199 local backX,backY,backZ = dx*backOffset,dy*backOffset,dz*backOffset
200 dx,dy,dz = dx*backLen,dy*backLen,dz*backLen
201
202 local terrainHeightUpdater = g_densityMapHeightManager:getTerrainDetailHeightUpdater()
203 if terrainHeightUpdater ~= nil then
204 addDensityMapHeightOcclusionArea(terrainHeightUpdater, sx+backX,sy+backY,sz+backZ, ex-sx,ey-sy,ez-sz, dx, dy, dz, true)
205 if width < levelerNode.width-0.05 then
206 -- fully block left and right of the inner block area
207 local sx2,sy2,sz2 = localToWorld(levelerNode.node, -levelerNode.width, 0, 0)
208 local ex2,ey2,ez2 = localToWorld(levelerNode.node, levelerNode.width, 0, 0)
209
210 addDensityMapHeightOcclusionArea(terrainHeightUpdater, sx2+backX,sy2+backY,sz2+backZ, sx-sx2,sy-sy2,sz-sz2, dx, dy, dz, false)
211 addDensityMapHeightOcclusionArea(terrainHeightUpdater, ex +backX,ey +backY,ez +backZ, ex2-ex,ey2-ey,ez2-ez, dx, dy, dz, false)
212 end
213 end
214
215 levelerNode.lastDrop2, levelerNode.lineOffsetDrop2 = DensityMapHeightUtil.tipToGroundAroundLine(self, fillLevel, fillType, sx,sy+yOffset,sz, ex,ey+yOffset,ez, 0, outerRadius, levelerNode.lineOffsetDrop2, true, nil)
216 if levelerNode.lastDrop2 > 0 then
217 local leftOver = fillLevel - levelerNode.lastDrop2
218 if leftOver <= g_densityMapHeightManager:getMinValidLiterValue(fillType) then
219 levelerNode.lastDrop2 = fillLevel
220 spec.litersToPickup = spec.litersToPickup + leftOver
221 end
222 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -levelerNode.lastDrop2, fillType, ToolType.UNDEFINED, nil)
223 end
224 end
225 end
226
227 -- call fill level changed callack to inform bunker silo about change
228 if pickedUpFillLevel < 0 and fillType ~= FillType.UNKNOWN then
229 self:notifiyBunkerSilo(pickedUpFillLevel, fillType)
230 end
231 end
232 end
233end

prerequisitesPresent

Description
Checks if all prerequisite specializations are loaded
Definition
prerequisitesPresent(table specializations)
Arguments
tablespecializationsspecializations
Return Values
booleanhasPrerequisitetrue if all prerequisite specializations are loaded
Code
17function Leveler.prerequisitesPresent(specializations)
18 return SpecializationUtil.hasSpecialization(FillUnit, specializations) and SpecializationUtil.hasSpecialization(BunkerSiloInteractor, specializations)
19end

registerEventListeners

Description
Definition
registerEventListeners()
Code
30function Leveler.registerEventListeners(vehicleType)
31 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Leveler)
32 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Leveler)
33end

registerFunctions

Description
Definition
registerFunctions()
Code
23function Leveler.registerFunctions(vehicleType)
24 SpecializationUtil.registerFunction(vehicleType, "getIsLevelerPickupNodeActive", Leveler.getIsLevelerPickupNodeActive)
25 SpecializationUtil.registerFunction(vehicleType, "loadLevelerNodeFromXML", Leveler.loadLevelerNodeFromXML)
26end