LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

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