LUADOC - Farming Simulator 19

Shovel

Description
Specialization for shovels providing functionality to pick up filltypes from the ground
Functions

getCanShovelAtPosition

Description
Definition
getCanShovelAtPosition()
Code
399function Shovel:getCanShovelAtPosition(shovelNode)
400 if shovelNode == nil then
401 return false
402 end
403
404 local sx,_,sz = localToWorld(shovelNode.node, -shovelNode.width, 0, 0)
405 local activeFarm = self:getActiveFarm()
406
407 local ex,_,ez = localToWorld(shovelNode.node, shovelNode.width, 0, 0)
408 local isStartOwned = g_currentMission.accessHandler:canFarmAccessLand(activeFarm, sx, sz)
409 if not isStartOwned then
410 return false
411 end
412
413 return g_currentMission.accessHandler:canFarmAccessLand(activeFarm, ex, ez)
414end

getCanToggleDischargeToGround

Description
Definition
getCanToggleDischargeToGround()
Code
358function Shovel:getCanToggleDischargeToGround(superFunc)
359 if self.spec_shovel.shovelDischargeInfo.node ~= nil then
360 return false
361 end
362
363 return superFunc(self)
364end

getCanToggleDischargeToObject

Description
Definition
getCanToggleDischargeToObject()
Code
348function Shovel:getCanToggleDischargeToObject(superFunc)
349 if self.spec_shovel.shovelDischargeInfo.node ~= nil then
350 return false
351 end
352
353 return superFunc(self)
354end

getDischargeNodeEmptyFactor

Description
Definition
getDischargeNodeEmptyFactor()
Code
278function Shovel:getDischargeNodeEmptyFactor(superFunc, dischargeNode)
279 local spec = self.spec_shovel
280
281 local parentFactor = superFunc(self, dischargeNode)
282
283 local info = spec.shovelDischargeInfo
284 if info.node ~= nil then
285 if info.dischargeNodeIndex == dischargeNode.index then
286 return parentFactor * self:getShovelTipFactor()
287 end
288 end
289
290 return parentFactor
291end

getShovelNodeIsActive

Description
Definition
getShovelNodeIsActive()
Code
246function Shovel:getShovelNodeIsActive(shovelNode)
247 local isActive = true
248
249 if shovelNode.needsMovement then
250 local x,y,z = getWorldTranslation(shovelNode.node)
251 local _,_,dz = worldToLocal(shovelNode.node, shovelNode.lastPosition[1], shovelNode.lastPosition[2], shovelNode.lastPosition[3])
252 isActive = isActive and dz < 0
253
254 shovelNode.lastPosition[1] = x
255 shovelNode.lastPosition[2] = y
256 shovelNode.lastPosition[3] = z
257 end
258
259 if shovelNode.maxPickupAngle ~= nil then
260 local _,dy,_ = localDirectionToWorld(shovelNode.node, 0, 0, 1)
261 local angle = math.acos(dy)
262 if angle > shovelNode.maxPickupAngle then
263 return false
264 end
265 end
266
267 if shovelNode.needsAttacherVehicle then
268 if self.getAttacherVehicle ~= nil and self:getAttacherVehicle() == nil then
269 return false
270 end
271 end
272
273 return isActive
274end

getShovelTipFactor

Description
Definition
getShovelTipFactor()
Code
368function Shovel:getShovelTipFactor()
369 local spec = self.spec_shovel
370
371 local info = spec.shovelDischargeInfo
372 if info.node ~= nil then
373 local _,dy,_ = localDirectionToWorld(info.node, 0,0,1)
374 local angle = math.acos(dy)
375 if angle > info.minSpeedAngle then
376 return math.max(0, math.min(1.0, (angle - info.minSpeedAngle) / (info.maxSpeedAngle - info.minSpeedAngle)))
377 end
378 end
379
380 return 0
381end

getWearMultiplier

Description
Returns current wear multiplier
Definition
getWearMultiplier()
Return Values
floatwearMultipliercurrent wear multiplier
Code
386function Shovel:getWearMultiplier(superFunc)
387 local spec = self.spec_shovel
388 local multiplier = superFunc(self)
389
390 if spec.loadingFillType ~= FillType.UNKNOWN then
391 multiplier = multiplier + self:getWorkWearMultiplier()
392 end
393
394 return multiplier
395end

handleDischarge

Description
Definition
handleDischarge()
Code
295function Shovel:handleDischarge(superFunc, dischargeNode, dischargedLiters, minDropReached, hasMinDropFillLevel)
296 local spec = self.spec_shovel
297 -- do nothing if it is shovel dischargenode
298 if dischargeNode.index ~= spec.shovelDischargeInfo.dischargeNodeIndex or self.spec_shovel.shovelDischargeInfo.node == nil then
299 superFunc(self, dischargeNode, dischargedLiters, minDropReached, hasMinDropFillLevel)
300 end
301end

handleDischargeOnEmpty

Description
Definition
handleDischargeOnEmpty()
Code
305function Shovel:handleDischargeOnEmpty(superFunc, dischargedLiters, minDropReached, hasMinDropFillLevel)
306 if self.spec_shovel.shovelDischargeInfo.node == nil then
307 superFunc(self, dischargedLiters, minDropReached, hasMinDropFillLevel)
308 end
309end

handleDischargeRaycast

Description
Definition
handleDischargeRaycast()
Code
313function Shovel:handleDischargeRaycast(superFunc, dischargeNode, hitObject, hitShape, hitDistance, hitFillUnitIndex, hitTerrain)
314 if self.spec_shovel.shovelDischargeInfo.node ~= nil then
315 if hitObject ~= nil then
316 local fillType = self:getDischargeFillType(dischargeNode)
317 local allowFillType = hitObject:getFillUnitAllowsFillType(hitFillUnitIndex, fillType)
318 if allowFillType and hitObject:getFillUnitFreeCapacity(hitFillUnitIndex, fillType, self:getOwnerFarmId()) > 0 then
319 self:setDischargeState(Dischargeable.DISCHARGE_STATE_OBJECT, true)
320 else
321 if self:getDischargeState() == Dischargeable.DISCHARGE_STATE_OBJECT then
322 self:setDischargeState(Dischargeable.DISCHARGE_STATE_OFF, true)
323 end
324 end
325 else
326 local fillLevel = self:getFillUnitFillLevel(dischargeNode.fillUnitIndex)
327 if fillLevel > 0 and self:getShovelTipFactor() > 0 then
328 if self:getCanDischargeToGround(dischargeNode) then
329 self:setDischargeState(Dischargeable.DISCHARGE_STATE_GROUND, true)
330 else
331 if self:getIsActiveForInput(true) then
332 if not self:getCanDischargeToLand(dischargeNode) then
333 g_currentMission:showBlinkingWarning(g_i18n:getText("warning_youDontHaveAccessToThisLand"), 5000)
334 elseif not self:getCanDischargeAtPosition(dischargeNode) then
335 g_currentMission:showBlinkingWarning(g_i18n:getText("warning_actionNotAllowedHere"), 5000)
336 end
337 end
338 end
339 end
340 end
341 else
342 superFunc(self, dischargeNode, hitObject, hitShape, hitDistance, hitFillUnitIndex, hitTerrain)
343 end
344end

loadShovelNode

Description
Definition
loadShovelNode()
Code
215function Shovel:loadShovelNode(xmlFile, key, shovelNode)
216 shovelNode.node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, key .. "#node"), self.i3dMappings)
217 if shovelNode.node == nil then
218 g_logManager:xmlWarning(self.configFileName, "Missing 'node' for shovelNode '%s'!", key)
219 return false
220 end
221
222 shovelNode.fillUnitIndex = Utils.getNoNil( getXMLInt(xmlFile, key .. "#fillUnitIndex"), 1)
223 shovelNode.loadInfoIndex = Utils.getNoNil( getXMLInt(xmlFile, key .. "#loadInfoIndex"), 1)
224
225 shovelNode.width = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#width"), 1)
226 shovelNode.length = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#length"), 0.5)
227 shovelNode.yOffset = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#yOffset"), 0)
228 shovelNode.zOffset = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#zOffset"), 0)
229
230 shovelNode.needsMovement = Utils.getNoNil(getXMLBool(xmlFile, key .. "#needsMovement"), true)
231 shovelNode.lastPosition = {0, 0, 0}
232
233 shovelNode.fillLitersPerSecond = (getXMLFloat(xmlFile, key .. "#fillLitersPerSecond") or math.huge) / 1000
234 shovelNode.maxPickupAngle = getXMLFloat(xmlFile, key .. "#maxPickupAngle")
235 if shovelNode.maxPickupAngle ~= nil then
236 shovelNode.maxPickupAngle = math.rad(shovelNode.maxPickupAngle)
237 end
238
239 shovelNode.needsAttacherVehicle = Utils.getNoNil(getXMLBool(xmlFile, key .. "#needsAttacherVehicle"), true)
240
241 return true
242end

onDelete

Description
Definition
onDelete()
Code
107function Shovel:onDelete()
108 if self.isClient then
109 local spec = self.spec_shovel
110 g_effectManager:deleteEffects(spec.fillEffects)
111 end
112end

onLoad

Description
Definition
onLoad()
Code
54function Shovel:onLoad(savegame)
55 local spec = self.spec_shovel
56
57 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.shovel#pickUpNode", "vehicle.shovel.shovelNode#node") --FS17 to FS19
58 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.shovel#pickUpWidth", "vehicle.shovel.shovelNode#width") --FS17 to FS19
59 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.shovel#pickUpLength", "vehicle.shovel.shovelNode#length") --FS17 to FS19
60 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.shovel#pickUpYOffset") --FS17 to FS19
61 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.shovel#pickUpRequiresMovement", "vehicle.shovel.shovelNode#needsMovement") --FS17 to FS19
62 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.shovel#pickUpNeedsToBeTurnedOn", "vehicle.shovel.shovelNode#needsActivation") --FS17 to FS19
63
64 spec.ignoreFillUnitFillType = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.shovel#ignoreFillUnitFillType"), false)
65
66 spec.shovelNodes = {}
67 local i = 0
68 while true do
69 local key = string.format("vehicle.shovel.shovelNode(%d)", i)
70 if not hasXMLProperty(self.xmlFile, key) then
71 break
72 end
73
74 local shovelNode = {}
75
76 if self:loadShovelNode(self.xmlFile, key, shovelNode) then
77 table.insert(spec.shovelNodes, shovelNode)
78 end
79 i = i + 1
80 end
81
82 spec.shovelDischargeInfo = {}
83 spec.shovelDischargeInfo.dischargeNodeIndex = Utils.getNoNil( getXMLInt(self.xmlFile, "vehicle.shovel.dischargeInfo#dischargeNodeIndex"), 1)
84 spec.shovelDischargeInfo.node = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.shovel.dischargeInfo#node"), self.i3dMappings)
85
86 if spec.shovelDischargeInfo.node ~= nil then
87 local minSpeedAngle = getXMLFloat(self.xmlFile, "vehicle.shovel.dischargeInfo#minSpeedAngle")
88 local maxSpeedAngle = getXMLFloat(self.xmlFile, "vehicle.shovel.dischargeInfo#maxSpeedAngle")
89 if minSpeedAngle == nil or maxSpeedAngle == nil then
90 g_logManager:xmlWarning(self.configFileName, "Missing 'minSpeedAngle' or 'maxSpeedAngle' for dischargeNode 'vehicle.shovel.dischargeInfo'")
91 return false
92 end
93 spec.shovelDischargeInfo.minSpeedAngle = math.rad(minSpeedAngle)
94 spec.shovelDischargeInfo.maxSpeedAngle = math.rad(maxSpeedAngle)
95 end
96
97 if self.isClient then
98 spec.fillEffects = g_effectManager:loadEffect(self.xmlFile, "vehicle.shovel.fillEffect", self.components, self, self.i3dMappings)
99 end
100
101 spec.effectDirtyFlag = self:getNextDirtyFlag()
102 spec.loadingFillType = FillType.UNKNOWN
103end

onReadStream

Description
Definition
onReadStream()
Code
116function Shovel:onReadStream(streamId, connection)
117 local spec = self.spec_shovel
118 spec.loadingFillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS)
119end

onReadUpdateStream

Description
Definition
onReadUpdateStream()
Code
130function Shovel:onReadUpdateStream(streamId, timestamp, connection)
131 if connection:getIsServer() then
132 local spec = self.spec_shovel
133
134 if streamReadBool(streamId) then
135 spec.loadingFillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS)
136 end
137 end
138end

onUpdateTick

Description
Definition
onUpdateTick()
Code
154function Shovel:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
155 local spec = self.spec_shovel
156
157 if self.isServer then
158 local validPickupFillType = FillType.UNKNOWN
159 for _,shovelNode in pairs(spec.shovelNodes) do
160 if self:getShovelNodeIsActive(shovelNode) then
161 local fillLevel = self:getFillUnitFillLevel(shovelNode.fillUnitIndex)
162 local capacity = self:getFillUnitCapacity(shovelNode.fillUnitIndex)
163 if fillLevel < capacity then
164 local pickupFillType = self:getFillUnitFillType(shovelNode.fillUnitIndex)
165 if fillLevel / capacity < self:getFillTypeChangeThreshold() then
166 pickupFillType = FillType.UNKNOWN
167 end
168 local freeCapacity = math.min(capacity - fillLevel, shovelNode.fillLitersPerSecond * dt)
169 local sx,sy,sz = localToWorld(shovelNode.node, -shovelNode.width, shovelNode.yOffset, shovelNode.zOffset)
170 local ex,ey,ez = localToWorld(shovelNode.node, shovelNode.width, shovelNode.yOffset, shovelNode.zOffset)
171 local innerRadius = shovelNode.length
172 local radius = nil
173
174 if self:getCanShovelAtPosition(shovelNode) then
175 if pickupFillType == FillType.UNKNOWN or spec.ignoreFillUnitFillType then
176 pickupFillType = DensityMapHeightUtil.getFillTypeAtLine(sx,sy,sz, ex,ey,ez, innerRadius)
177 end
178
179 if pickupFillType ~= FillType.UNKNOWN and self:getFillUnitSupportsFillType(shovelNode.fillUnitIndex, pickupFillType) then
180 local fillDelta, lineOffset = DensityMapHeightUtil.tipToGroundAroundLine(self, -freeCapacity, pickupFillType, sx,sy,sz, ex,ey,ez, innerRadius, radius, shovelNode.lineOffset, true, nil)
181 shovelNode.lineOffset = lineOffset
182
183 if fillDelta < 0 then
184 local loadInfo = self:getFillVolumeLoadInfo(shovelNode.loadInfoIndex)
185 self:addFillUnitFillLevel(self:getOwnerFarmId(), shovelNode.fillUnitIndex, -fillDelta, pickupFillType, ToolType.UNDEFINED, loadInfo)
186 validPickupFillType = pickupFillType
187
188 -- call fill level changed callack to inform bunker silo about change
189 self:notifiyBunkerSilo(fillDelta, pickupFillType)
190 end
191 end
192 end
193 end
194 end
195 end
196
197 if spec.loadingFillType ~= validPickupFillType then
198 spec.loadingFillType = validPickupFillType
199 self:raiseDirtyFlags(spec.effectDirtyFlag)
200 end
201 end
202
203 if self.isClient then
204 if spec.loadingFillType ~= FillType.UNKNOWN then
205 g_effectManager:setFillType(spec.fillEffects, spec.loadingFillType)
206 g_effectManager:startEffects(spec.fillEffects)
207 else
208 g_effectManager:stopEffects(spec.fillEffects)
209 end
210 end
211end

onWriteStream

Description
Definition
onWriteStream()
Code
123function Shovel:onWriteStream(streamId, connection)
124 local spec = self.spec_shovel
125 streamWriteUIntN(streamId, spec.loadingFillType, FillTypeManager.SEND_NUM_BITS)
126end

onWriteUpdateStream

Description
Definition
onWriteUpdateStream()
Code
142function Shovel:onWriteUpdateStream(streamId, connection, dirtyMask)
143 if not connection:getIsServer() then
144 local spec = self.spec_shovel
145
146 if streamWriteBool(streamId, bitAND(dirtyMask, spec.effectDirtyFlag) ~= 0) then
147 streamWriteUIntN(streamId, spec.loadingFillType, FillTypeManager.SEND_NUM_BITS)
148 end
149 end
150end

prerequisitesPresent

Description
Definition
prerequisitesPresent()
Code
15function Shovel.prerequisitesPresent(specializations)
16 return SpecializationUtil.hasSpecialization(FillUnit, specializations) and SpecializationUtil.hasSpecialization(FillVolume, specializations) and SpecializationUtil.hasSpecialization(Dischargeable, specializations) and SpecializationUtil.hasSpecialization(BunkerSiloInteractor, specializations)
17end

registerEventListeners

Description
Definition
registerEventListeners()
Code
42function Shovel.registerEventListeners(vehicleType)
43 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Shovel)
44 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Shovel)
45 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Shovel)
46 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Shovel)
47 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Shovel)
48 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Shovel)
49 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Shovel)
50end

registerFunctions

Description
Definition
registerFunctions()
Code
21function Shovel.registerFunctions(vehicleType)
22 SpecializationUtil.registerFunction(vehicleType, "loadShovelNode", Shovel.loadShovelNode)
23 SpecializationUtil.registerFunction(vehicleType, "getShovelNodeIsActive", Shovel.getShovelNodeIsActive)
24 SpecializationUtil.registerFunction(vehicleType, "getCanShovelAtPosition",Shovel.getCanShovelAtPosition)
25 SpecializationUtil.registerFunction(vehicleType, "getShovelTipFactor", Shovel.getShovelTipFactor)
26end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
30function Shovel.registerOverwrittenFunctions(vehicleType)
31 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDischargeNodeEmptyFactor", Shovel.getDischargeNodeEmptyFactor)
32 SpecializationUtil.registerOverwrittenFunction(vehicleType, "handleDischarge", Shovel.handleDischarge)
33 SpecializationUtil.registerOverwrittenFunction(vehicleType, "handleDischargeOnEmpty", Shovel.handleDischargeOnEmpty)
34 SpecializationUtil.registerOverwrittenFunction(vehicleType, "handleDischargeRaycast", Shovel.handleDischargeRaycast)
35 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanToggleDischargeToObject", Shovel.getCanToggleDischargeToObject)
36 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanToggleDischargeToGround", Shovel.getCanToggleDischargeToGround)
37 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getWearMultiplier", Shovel.getWearMultiplier)
38end

updateDebugValues

Description
Definition
updateDebugValues()
Code
418function Shovel:updateDebugValues(values)
419 local spec = self.spec_shovel
420
421 local info = spec.shovelDischargeInfo
422 if info.node ~= nil then
423 local _,dy,_ = localDirectionToWorld(info.node, 0,0,1)
424 local angle = math.acos(dy)
425 table.insert(values, {name="angle", value=math.deg(angle)})
426 table.insert(values, {name="minSpeedAngle", value=math.deg(info.minSpeedAngle)})
427 table.insert(values, {name="maxSpeedAngle", value=math.deg(info.maxSpeedAngle)})
428
429 if angle > info.minSpeedAngle then
430 local factor = math.max(0, math.min(1.0, (angle - info.minSpeedAngle) / (info.maxSpeedAngle - info.minSpeedAngle)))
431 table.insert(values, {name="factor", value=factor})
432 else
433 table.insert(values, {name="factor", value="Out of Range - 0"})
434 end
435 end
436end