LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

ConveyorBelt

Description
Class for conveyor belts to control unloading start time and unloading effects
Functions

getDischargeNodeEmptyFactor

Description
Definition
getDischargeNodeEmptyFactor()
Code
246function ConveyorBelt:getDischargeNodeEmptyFactor(superFunc, dischargeNode)
247 local spec = self.spec_conveyorBelt
248 local parentFactor = superFunc(self, dischargeNode)
249
250 if spec.dischargeNodeIndex == dischargeNode.index then
251 if spec.morphEndPos == 1 then
252 return spec.emptyFactor
253 else
254 return 0
255 end
256 end
257
258 return parentFactor
259end

getIsEnterable

Description
Definition
getIsEnterable()
Code
283function ConveyorBelt:getIsEnterable(superFunc)
284 return (self.getAttacherVehicle == nil or self:getAttacherVehicle() == nil) and superFunc(self)
285end

handleDischarge

Description
Definition
handleDischarge()
Code
273function ConveyorBelt:handleDischarge(superFunc, dischargeNode, dischargedLiters, minDropReached, hasMinDropFillLevel)
274 local spec = self.spec_conveyorBelt
275 -- do nothing if it is conveyor dischargenode
276 if dischargeNode.index ~= spec.dischargeNodeIndex then
277 superFunc(self, dischargeNode, dischargedLiters, minDropReached, hasMinDropFillLevel)
278 end
279end

handleDischargeOnEmpty

Description
Definition
handleDischargeOnEmpty()
Code
263function ConveyorBelt:handleDischargeOnEmpty(superFunc, dischargeNode)
264 local spec = self.spec_conveyorBelt
265 -- do nothing if conveyorBelt dischargenode is empty
266 if dischargeNode.index ~= spec.dischargeNodeIndex then
267 superFunc(self, dischargeNode)
268 end
269end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
164function ConveyorBelt:onDelete()
165 local spec = self.spec_conveyorBelt
166 g_effectManager:deleteEffects(spec.effects)
167 g_animationManager:deleteAnimations(spec.animationNodes)
168end

onFillUnitFillLevelChanged

Description
Definition
onFillUnitFillLevelChanged()
Code
289function ConveyorBelt:onFillUnitFillLevelChanged(fillUnitIndex, fillLevelDelta, fillType, toolType, fillPositionData, appliedDelta)
290 local spec = self.spec_conveyorBelt
291 if spec.fillUnitIndex == fillUnitIndex then
292 local fillLevel = self:getFillUnitFillLevel(fillUnitIndex)
293
294 if fillLevelDelta > 0 then
295 spec.morphStartPos = 0
296 spec.morphEndPos = math.max(spec.morphEndPos, fillLevel / self:getFillUnitCapacity(fillUnitIndex))
297 spec.isEffectDirty = true
298 end
299
300 if fillLevelDelta ~= 0 then
301 spec.scrollUpdateTime = 1000
302 end
303
304 if fillLevel == 0 then
305 g_effectManager:stopEffects(spec.effects)
306 spec.morphStartPos = 0
307 spec.morphEndPos = 0
308 spec.isEffectDirty = true
309 else
310 g_effectManager:setFillType(spec.effects, fillType)
311 g_effectManager:startEffects(spec.effects)
312 end
313 end
314end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
44function ConveyorBelt:onLoad(savegame)
45
46 local spec = self.spec_conveyorBelt
47
48 self.showOnMap = true
49
50 if self.isClient then
51 spec.animationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.conveyorBelt.animationNodes", self.components, self, self.i3dMappings)
52 end
53
54 spec.effects = g_effectManager:loadEffect(self.xmlFile, "vehicle.conveyorBelt.effects", self.components, self, self.i3dMappings)
55 spec.currentDelay = 0
56 table.sort(spec.effects, function(effect1, effect2) return effect1.startDelay < effect2.startDelay end)
57
58 for _, effect in pairs(spec.effects) do
59 if effect.planeFadeTime ~= nil then
60 spec.currentDelay = spec.currentDelay + effect.planeFadeTime
61 end
62 if effect.setScrollUpdate ~= nil then
63 effect:setScrollUpdate(false)
64 end
65 end
66 spec.maxDelay = spec.currentDelay
67
68 spec.morphStartPos = 0
69 spec.morphEndPos = 0
70 spec.isEffectDirty = false
71 spec.emptyFactor = 1
72 spec.scrollUpdateTime = 0
73 spec.lastScrollUpdate = false
74
75 spec.dischargeNodeIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.conveyorBelt#dischargeNodeIndex"), 1)
76 self:setCurrentDischargeNodeIndex(spec.dischargeNodeIndex)
77 local dischargeNode = self:getDischargeNodeByIndex(spec.dischargeNodeIndex)
78 local capacity = self:getFillUnitCapacity(dischargeNode.fillUnitIndex)
79 spec.fillUnitIndex = dischargeNode.fillUnitIndex
80 spec.startFillLevel = capacity * Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.conveyorBelt#startPercentage"), 0.9)
81
82 local i = 0
83 while true do
84 local key = string.format("vehicle.conveyorBelt.offset(%d)", i)
85 if not hasXMLProperty(self.xmlFile, key) then
86 break
87 end
88
89 local movingToolNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key.."#movingToolNode"), self.i3dMappings)
90 if movingToolNode ~= nil then
91 if spec.offsets == nil then
92 spec.offsets = {}
93 end
94
95 local offset = {}
96 offset.lastState = 0
97 offset.movingToolNode = movingToolNode
98 offset.effects = {}
99 local j = 0
100 while true do
101 local effectKey = string.format(key..".effect(%d)", j)
102 if not hasXMLProperty(self.xmlFile, effectKey) then
103 break
104 end
105
106 local effectIndex = Utils.getNoNil(getXMLInt(self.xmlFile, effectKey.."#index"), 0)
107 local effect = spec.effects[effectIndex]
108 if effect ~= nil and effect.setOffset ~= nil then
109 local entry = {}
110 entry.effect = effect
111 entry.minValue = Utils.getNoNil(getXMLFloat(self.xmlFile, effectKey.."#minOffset"), 0)*1000
112 entry.maxValue = Utils.getNoNil(getXMLFloat(self.xmlFile, effectKey.."#maxOffset"), 1)*1000
113 entry.inverted = Utils.getNoNil(getXMLBool(self.xmlFile, effectKey.."#inverted"), false)
114 table.insert(offset.effects, entry)
115 else
116 g_logManager:xmlWarning(self.configFileName, "Effect index '%d' not found!", effectIndex)
117 end
118 j = j + 1
119 end
120
121 table.insert(spec.offsets, offset)
122 else
123 g_logManager:xmlWarning(self.configFileName, "Missing movingToolNode for conveyor offset '%s'!", key)
124 end
125 i = i + 1
126 end
127end

onMovingToolChanged

Description
Definition
onMovingToolChanged()
Code
318function ConveyorBelt:onMovingToolChanged(movingTool, speed, dt)
319 local spec = self.spec_conveyorBelt
320 if spec.offsets ~= nil then
321 local offset = spec.movingToolToOffset[movingTool]
322
323 if offset ~= nil then
324 local state = Cylindered.getMovingToolState(self, movingTool)
325 if state ~= offset.lastState then
326 local updateDelay = false
327
328 for _, entry in pairs(offset.effects) do
329 local effectState = state
330 if entry.inverted then
331 effectState = 1 - effectState
332 end
333
334 entry.effect:setOffset(MathUtil.lerp(entry.minValue, entry.maxValue, effectState))
335 updateDelay = true
336 end
337
338 if updateDelay then
339 spec.currentDelay = 0
340 for _, effect in pairs(spec.effects) do
341 if effect.planeFadeTime ~= nil then
342 spec.currentDelay = spec.currentDelay + effect.planeFadeTime - effect.offset
343 end
344 end
345 end
346
347 offset.lastState = state
348 end
349 end
350 end
351end

onPostLoad

Description
Definition
onPostLoad()
Code
131function ConveyorBelt:onPostLoad(savegame)
132 local spec = self.spec_conveyorBelt
133
134 -- we need to check movingTool in post load to avoid order dependencies
135 if spec.offsets ~= nil then
136 if self.getMovingToolByNode ~= nil then
137 spec.movingToolToOffset = {}
138 for i=#spec.offsets, 1, -1 do
139 local offset = spec.offsets[i]
140 local movingTool = self:getMovingToolByNode(offset.movingToolNode)
141 if movingTool ~= nil then
142 offset.movingTool = movingTool
143 spec.movingToolToOffset[movingTool] = offset
144 ConveyorBelt.onMovingToolChanged(self, movingTool, 0, 0)
145 else
146 g_logManager:xmlWarning(self.configFileName, "No movingTool node '%s' defined for conveyor offset '%d'!", getName(offset.movingToolNode), i)
147 table.remove(spec.offsets, i)
148 end
149 end
150
151 if #spec.offsets == 0 then
152 spec.offsets = nil
153 spec.movingToolToOffset = nil
154 end
155 else
156 g_logManager:xmlError(self.configFileName, "'Cylindered' specialization is required to use conveyorBelt offsets!")
157 spec.offsets = nil
158 end
159 end
160end

onUpdateTick

Description
Called on update tick
Definition
onUpdateTick(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
175function ConveyorBelt:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
176 if self.isClient then
177 local spec = self.spec_conveyorBelt
178
179 local isBeltActive = self:getDischargeState() ~= Dischargeable.DISCHARGE_STATE_OFF
180 if isBeltActive then
181 local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
182 if fillLevel > 0.0001 then
183 local movedFactor = dt / spec.currentDelay
184 spec.morphStartPos = MathUtil.clamp(spec.morphStartPos + movedFactor, 0, 1)
185 spec.morphEndPos = MathUtil.clamp(spec.morphEndPos + movedFactor, 0, 1)
186
187 -- we calculate the empty factor based on visual effect mesh and filllevel to get a smooth transition
188 local fillFactor = fillLevel/self:getFillUnitCapacity(spec.fillUnitIndex)
189 local visualFactor = spec.morphEndPos-spec.morphStartPos
190
191 spec.emptyFactor = 1
192 if visualFactor > fillFactor then
193 spec.emptyFactor = MathUtil.clamp(fillFactor/visualFactor, 0, 1)
194 else
195 local offset = fillFactor - visualFactor
196 spec.offset = offset
197 spec.morphStartPos = MathUtil.clamp(spec.morphStartPos - (offset/((1-spec.morphStartPos)*spec.currentDelay))*dt , 0, 1)
198 end
199
200 spec.isEffectDirty = true
201 end
202 end
203
204 if spec.isEffectDirty then
205 for _, effect in pairs(spec.effects) do
206 if effect.setMorphPosition ~= nil then
207 local effectStart = effect.startDelay/spec.currentDelay
208 local effectEnd = (effect.startDelay+effect.planeFadeTime-effect.offset)/spec.currentDelay
209 local offsetFactor = effect.offset/effect.planeFadeTime
210
211 local startMorphFactor = (spec.morphStartPos-effectStart)/(effectEnd-effectStart)
212 local startMorph = MathUtil.clamp(offsetFactor + startMorphFactor*(1-offsetFactor), offsetFactor, 1)
213
214 local endMorphFactor = (spec.morphEndPos-effectStart)/(effectEnd-effectStart)
215 local endMorph = MathUtil.clamp(offsetFactor + endMorphFactor*(1-offsetFactor), offsetFactor, 1)
216
217 --renderText(0.6, 0.8-i*0.015, 0.012, string.format("%d: effectStart %.4f effectEnd %.4f -> startMorph %.4f endMorph %.4f | offset %.4f | %.4f %.4f", i, effectStart, effectEnd, startMorph, endMorph, effect.offset/effect.planeFadeTime, (spec.morphStartPos-effectStart)/(effectEnd-effectStart), (spec.morphEndPos-effectStart)/(effectEnd-effectStart)))
218 effect:setMorphPosition(startMorph, endMorph)
219 end
220 end
221 spec.isEffectDirty = false
222 end
223
224 spec.scrollUpdateTime = math.max(spec.scrollUpdateTime - dt, 0)
225 local doScrollUpdate = spec.scrollUpdateTime > 0
226 if doScrollUpdate ~= spec.lastScrollUpdate then
227 if doScrollUpdate then
228 g_animationManager:startAnimations(spec.animationNodes)
229 else
230 g_animationManager:stopAnimations(spec.animationNodes)
231 end
232
233 for _, effect in pairs(spec.effects) do
234 if effect.setScrollUpdate ~= nil then
235 effect:setScrollUpdate(doScrollUpdate)
236 end
237 end
238
239 spec.lastScrollUpdate = doScrollUpdate
240 end
241 end
242end

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 ConveyorBelt.prerequisitesPresent(specializations)
18 return SpecializationUtil.hasSpecialization(Dischargeable, specializations)
19end

registerEventListeners

Description
Definition
registerEventListeners()
Code
32function ConveyorBelt.registerEventListeners(vehicleType)
33 SpecializationUtil.registerEventListener(vehicleType, "onLoad", ConveyorBelt)
34 SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", ConveyorBelt)
35 SpecializationUtil.registerEventListener(vehicleType, "onDelete", ConveyorBelt)
36 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", ConveyorBelt)
37 SpecializationUtil.registerEventListener(vehicleType, "onFillUnitFillLevelChanged", ConveyorBelt)
38 SpecializationUtil.registerEventListener(vehicleType, "onMovingToolChanged", ConveyorBelt)
39end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
23function ConveyorBelt.registerOverwrittenFunctions(vehicleType)
24 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDischargeNodeEmptyFactor", ConveyorBelt.getDischargeNodeEmptyFactor)
25 SpecializationUtil.registerOverwrittenFunction(vehicleType, "handleDischargeOnEmpty", ConveyorBelt.handleDischargeOnEmpty)
26 SpecializationUtil.registerOverwrittenFunction(vehicleType, "handleDischarge", ConveyorBelt.handleDischarge)
27 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsEnterable", ConveyorBelt.getIsEnterable)
28end

updateDebugValues

Description
Definition
updateDebugValues()
Code
355function ConveyorBelt:updateDebugValues(values)
356 local spec = self.spec_conveyorBelt
357
358 table.insert(values, {name="offset", value=spec.offset})
359 table.insert(values, {name="morphStartPos", value=spec.morphStartPos})
360 table.insert(values, {name="morphEndPos", value=spec.morphEndPos})
361end