LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

MixerWagon

Description
Specialization for forage mixer wagons creating forage from bales, chaff, straw and/or hay
Functions

addFillUnitFillLevel

Description
Definition
addFillUnitFillLevel()
Code
320function MixerWagon:addFillUnitFillLevel(superFunc, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData)
321 local spec = self.spec_mixerWagon
322
323 if fillUnitIndex ~= spec.fillUnitIndex then
324 return superFunc(self, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData)
325 end
326
327 local oldFillLevel = self:getFillUnitFillLevel(fillUnitIndex)
328
329 local mixerWagonFillType = spec.fillTypeToMixerWagonFillType[fillTypeIndex]
330
331 -- allow to put forage back to mixer. Split it up into valid forage mixing ratios
332 if fillTypeIndex == FillType.FORAGE and fillLevelDelta > 0 then
333 for _, entry in pairs(spec.mixerWagonFillTypes) do
334 local delta = fillLevelDelta * entry.ratio
335 self:addFillUnitFillLevel(farmId, fillUnitIndex, delta, next(entry.fillTypes), toolType, fillPositionData)
336 end
337
338 return fillLevelDelta
339 end
340
341 if mixerWagonFillType == nil then
342 -- used for discharge
343 if fillLevelDelta < 0 and oldFillLevel > 0 then
344 -- remove values from all fill types such that the ratio doesn't change
345 fillLevelDelta = math.max(fillLevelDelta, -oldFillLevel)
346
347 local newFillLevel = 0
348 for _, entry in pairs(spec.mixerWagonFillTypes) do
349 local entryDelta = fillLevelDelta * (entry.fillLevel / oldFillLevel)
350 entry.fillLevel = math.max(entry.fillLevel + entryDelta, 0)
351 newFillLevel = newFillLevel + entry.fillLevel
352 end
353
354 if newFillLevel < 0.1 then
355 for _, entry in pairs(spec.mixerWagonFillTypes) do
356 entry.fillLevel = 0
357 end
358 fillLevelDelta = -oldFillLevel
359 end
360
361 self:raiseDirtyFlags(spec.dirtyFlag)
362 local ret = superFunc(self, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData)
363 return ret
364 end
365
366 return 0
367 end
368
369 local capacity = self:getFillUnitCapacity(fillUnitIndex)
370 local free = capacity - oldFillLevel
371
372 if fillLevelDelta > 0 then
373 mixerWagonFillType.fillLevel = mixerWagonFillType.fillLevel + math.min(free, fillLevelDelta)
374 spec.activeTimer = spec.activeTimerMax
375 else
376 mixerWagonFillType.fillLevel = math.max(0, mixerWagonFillType.fillLevel + fillLevelDelta)
377 end
378
379 local newFillLevel = 0
380 for _, mixerWagonFillType in pairs(spec.mixerWagonFillTypes) do
381 newFillLevel = newFillLevel + mixerWagonFillType.fillLevel
382 end
383 newFillLevel = MathUtil.clamp(newFillLevel, 0, self:getFillUnitCapacity(fillUnitIndex))
384
385 local newFillType = FillType.UNKNOWN
386 local isSingleFilled = false
387 local isForageOk = false
388
389 for _, mixerWagonFillType in pairs(spec.mixerWagonFillTypes) do
390 if newFillLevel == mixerWagonFillType.fillLevel then
391 isSingleFilled = true
392 newFillType = next(mixerWagonFillType.fillTypes)
393 break
394 end
395 end
396
397 if not isSingleFilled then
398 isForageOk = true
399 for _, mixerWagonFillType in pairs(spec.mixerWagonFillTypes) do
400 if mixerWagonFillType.fillLevel < mixerWagonFillType.minPercentage * newFillLevel - 0.01 or mixerWagonFillType.fillLevel > mixerWagonFillType.maxPercentage * newFillLevel + 0.01 then
401 isForageOk = false
402 break
403 end
404 end
405 end
406
407 if isForageOk then
408 newFillType = FillType.FORAGE
409 elseif not isSingleFilled then
410 newFillType = FillType.FORAGE_MIXING
411 end
412
413 self:raiseDirtyFlags(spec.dirtyFlag)
414
415 self:setFillUnitFillType(fillUnitIndex, newFillType)
416
417 return superFunc(self, farmId, fillUnitIndex, newFillLevel-oldFillLevel, newFillType, toolType, fillPositionData)
418end

getDischargeFillType

Description
Definition
getDischargeFillType()
Code
437function MixerWagon:getDischargeFillType(superFunc, dischargeNode)
438 local spec = self.spec_mixerWagon
439 local fillUnitIndex = dischargeNode.fillUnitIndex
440
441 if fillUnitIndex == spec.fillUnitIndex then
442 local currentFillType = self:getFillUnitFillType(fillUnitIndex)
443 local fillLevel = self:getFillUnitFillLevel(fillUnitIndex)
444
445 if currentFillType == FillType.FORAGE_MIXING and fillLevel > 0 then
446 for _, entry in pairs(spec.mixerWagonFillTypes) do
447 if entry.fillLevel > 0 then
448 currentFillType = next(entry.fillTypes)
449 break
450 end
451 end
452 end
453
454 return currentFillType
455 end
456
457 return superFunc(self, dischargeNode)
458end

getFillUnitAllowsFillType

Description
Definition
getFillUnitAllowsFillType()
Code
422function MixerWagon:getFillUnitAllowsFillType(superFunc, fillUnitIndex, fillTypeIndex)
423 local spec = self.spec_mixerWagon
424
425 if spec.fillUnitIndex == fillUnitIndex then
426 local mixerWagonFillType = spec.fillTypeToMixerWagonFillType[fillTypeIndex];
427 if mixerWagonFillType ~= nil then
428 return true
429 end
430 end
431
432 return superFunc(self, fillUnitIndex, fillTypeIndex)
433end

mixerWagonBaleTriggerCallback

Description
Trigger callback
Definition
mixerWagonBaleTriggerCallback(integer triggerId, integer otherActorId, boolean onEnter, boolean onLeave, boolean onStay, integer otherShapeId)
Arguments
integertriggerIdid of trigger
integerotherActorIdid of other actor
booleanonEnteron enter
booleanonLeaveon leave
booleanonStayon stay
integerotherShapeIdid of other shape
Code
290function MixerWagon:mixerWagonBaleTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
291 if onEnter then
292 -- this happens if a compound child of a deleted compound is entering
293 if otherActorId ~= 0 then
294 local bale = g_currentMission:getNodeObject(otherActorId)
295 if bale ~= nil then
296 if bale:isa(Bale) then
297 local spec = self.spec_mixerWagon
298 local fillLevel = bale:getFillLevel()
299 local fillTypeIndex = bale:getFillType()
300
301 if self:getFillUnitSupportsFillType(spec.fillUnitIndex, fillTypeIndex) and self:getFillUnitFreeCapacity(spec.fillUnitIndex) > 0 then
302 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, fillLevel, fillTypeIndex, ToolType.BALE, nil)
303 bale:delete()
304 spec.activeTimer = spec.activeTimerMax
305 self:raiseDirtyFlags(spec.dirtyFlag)
306 else
307 if self.isClient then
308 g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_CRITICAL, g_i18n:getText("warning_baleNotSupported"))
309 end
310 g_server:broadcastEvent(MixerWagonBaleNotAcceptedEvent:new(self), nil, nil, self)
311 end
312 end
313 end
314 end
315 end
316end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
174function MixerWagon:onDelete()
175 local spec = self.spec_mixerWagon
176 if self.isServer then
177 if spec.baleTriggerNode ~= nil then
178 removeTrigger(spec.baleTriggerNode)
179 end
180 end
181
182 if self.isClient then
183 g_animationManager:deleteAnimations(spec.mixAnimationNodes)
184 g_animationManager:deleteAnimations(spec.pickupAnimationNodes)
185 end
186end

onFillUnitFillLevelChanged

Description
Definition
onFillUnitFillLevelChanged()
Code
463function MixerWagon:onFillUnitFillLevelChanged(fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData, appliedDelta)
464 local spec = self.spec_mixerWagon
465
466 if spec.fillUnitIndex == fillUnitIndex then
467 local fillLevel = self:getFillUnitFillLevel(fillUnitIndex)
468 if fillLevel == 0 then
469 for _, entry in pairs(spec.mixerWagonFillTypes) do
470 entry.fillLevel = 0
471 end
472 end
473 end
474end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
59function MixerWagon:onLoad(savegame)
60
61 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mixerWagonBaleTrigger#index", "vehicle.mixerWagon.baleTrigger#node") --FS17 to FS19
62 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mixerWagon.baleTrigger#index", "vehicle.mixerWagon.baleTrigger#node") --FS19 to FS19
63
64 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mixerWagonPickupStartSound", "vehicle.turnOnVehicle.sounds.start") --FS17 to FS19
65 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mixerWagonPickupStopSound", "vehicle.turnOnVehicle.sounds.stop") --FS17 to FS19
66 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mixerWagonPickupSound", "vehicle.turnOnVehicle.sounds.work") --FS17 to FS19
67
68 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mixerWagonRotatingParts.mixerWagonRotatingPart#type", "vehicle.mixerWagon.mixAnimationNodes.animationNode", "mixerWagonMix") --FS17 to FS19
69 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mixerWagonRotatingParts.mixerWagonRotatingPart#type", "vehicle.mixerWagon.pickupAnimationNodes.animationNode", "mixerWagonPickup") --FS17 to FS19
70
71 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.mixerWagonRotatingParts.mixerWagonScroller", "vehicle.mixerWagon.pickupAnimationNodes.pickupAnimationNode") --FS17 to FS19
72
73 local spec = self.spec_mixerWagon
74
75 if self.isClient then
76 spec.mixAnimationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.mixerWagon.mixAnimationNodes", self.components, self, self.i3dMappings)
77 spec.pickupAnimationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.mixerWagon.pickupAnimationNodes", self.components, self, self.i3dMappings)
78 end
79
80 if self.isServer then
81 spec.baleTriggerNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.mixerWagon.baleTrigger#node"), self.i3dMappings)
82 if spec.baleTriggerNode ~= nil then
83 addTrigger(spec.baleTriggerNode, "mixerWagonBaleTriggerCallback", self)
84 end
85 end
86
87 spec.activeTimerMax = 5000
88 spec.activeTimer = 0
89
90 spec.fillUnitIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.mixerWagon#fillUnitIndex"), 1)
91
92 -- remove grass_windrow from fillTypes, we do not want to support grass in mixer wagons becasue this would make hay "useless"
93 local fillUnit = self:getFillUnitByIndex(spec.fillUnitIndex)
94 if fillUnit ~= nil then
95 fillUnit.needsSaving = false
96 if fillUnit.supportedFillTypes[FillType.GRASS_WINDROW] then
97 fillUnit.supportedFillTypes[FillType.GRASS_WINDROW] = nil
98 end
99 end
100
101 -- disable sync of fillLevels for fillUnit - will be handled by mixerWagon
102 fillUnit.synchronizeFillLevel = false
103
104 spec.mixerWagonFillTypes = {}
105 spec.fillTypeToMixerWagonFillType = {}
106 local sumRatio = 0
107 local i=0
108 while true do
109 local baseName = string.format("vehicle.mixerWagon.mixerWagonFillTypes.mixerWagonFillType(%d)", i)
110 if not hasXMLProperty(self.xmlFile, baseName) then
111 break
112 end
113 local entry = {}
114 entry.fillTypes = {}
115
116 local j=0
117 while true do
118 local fillTypeKey = baseName..string.format(".fillType(%d)", j)
119 if not hasXMLProperty(self.xmlFile, fillTypeKey) then
120 break
121 end
122 local fillTypeStr = getXMLString(self.xmlFile, fillTypeKey.."#fillType")
123 if fillTypeStr ~= nil then
124 local fillTypeIndex = g_fillTypeManager:getFillTypeIndexByName(fillTypeStr)
125 -- we do not want to support grass in mixer wagons becasue this would make hay "useless"
126 if fillTypeIndex ~= nil and fillTypeIndex ~= FillType.GRASS_WINDROW then
127 if spec.fillTypeToMixerWagonFillType[fillTypeIndex] == nil then
128 entry.fillTypes[fillTypeIndex] = true
129 spec.fillTypeToMixerWagonFillType[fillTypeIndex] = entry
130 else
131 g_logManager:xmlWarning(self.configFileName, "MixerWagonFillType '%s' in '%s' already used! Ignoring it!", fillTypeKey, fillTypeStr)
132 end
133 else
134 g_logManager:xmlWarning(self.configFileName, "FillType '%s' not defined for mixerWagonFillType '%s'!", fillTypeStr, fillTypeKey)
135 end
136 end
137
138 j = j+1
139 end
140
141 entry.name = Utils.getNoNil(getXMLString(self.xmlFile, baseName.."#name"), "unknown")
142 entry.minPercentage = Utils.getNoNil(getXMLFloat(self.xmlFile, baseName.."#minPercentage"), 0)*0.01
143 entry.maxPercentage = Utils.getNoNil(getXMLFloat(self.xmlFile, baseName.."#maxPercentage"), 100)*0.01
144 entry.ratio = entry.maxPercentage - entry.minPercentage
145 entry.fillLevel = 0
146
147 if next(entry.fillTypes) ~= nil then
148 sumRatio = sumRatio + entry.ratio
149 table.insert(spec.mixerWagonFillTypes, entry)
150 end
151 i = i+1
152 end
153
154 for i, entry in ipairs(spec.mixerWagonFillTypes) do
155 entry.ratio = entry.ratio / sumRatio
156 end
157
158 spec.dirtyFlag = self:getNextDirtyFlag()
159
160 if savegame ~= nil then
161 for i, entry in ipairs(spec.mixerWagonFillTypes) do
162 local fillTypeKey = savegame.key..string.format(".mixerWagon.fillType(%d)#fillLevel", i-1)
163 local fillLevel = Utils.getNoNil(getXMLFloat(savegame.xmlFile, fillTypeKey), 0)
164
165 if fillLevel > 0 then
166 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, fillLevel, next(entry.fillTypes), ToolType.UNDEFINED, nil)
167 end
168 end
169 end
170end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
203function MixerWagon:onReadStream(streamId, connection)
204 local spec = self.spec_mixerWagon
205 for _, entry in ipairs(spec.mixerWagonFillTypes) do
206 local fillLevel = streamReadFloat32(streamId)
207 if fillLevel > 0 then
208 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, fillLevel, next(entry.fillTypes), ToolType.UNDEFINED, nil)
209 end
210 end
211end

onReadUpdateStream

Description
Called on on update
Definition
onReadUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
229function MixerWagon:onReadUpdateStream(streamId, timestamp, connection)
230 if connection:getIsServer() then
231 if streamReadBool(streamId) then
232 local spec = self.spec_mixerWagon
233
234 for _, entry in ipairs(spec.mixerWagonFillTypes) do
235 local fillLevel = streamReadFloat32(streamId)
236 local delta = fillLevel - entry.fillLevel
237 if delta ~= 0 then
238 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, delta, next(entry.fillTypes), ToolType.UNDEFINED, nil)
239 end
240 end
241 end
242 end
243end

onTurnedOff

Description
Definition
onTurnedOff()
Code
487function MixerWagon:onTurnedOff()
488 if self.isClient then
489 local spec = self.spec_mixerWagon
490 g_animationManager:stopAnimations(spec.pickupAnimationNodes)
491 end
492end

onTurnedOn

Description
Definition
onTurnedOn()
Code
478function MixerWagon:onTurnedOn()
479 if self.isClient then
480 local spec = self.spec_mixerWagon
481 g_animationManager:startAnimations(spec.pickupAnimationNodes)
482 end
483end

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
267function MixerWagon:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
268 local spec = self.spec_mixerWagon
269
270 local tipState = self:getTipState()
271 local isTurnedOn = self:getIsTurnedOn()
272 local isDischarging = tipState == Trailer.TIPSTATE_OPENING or tipState == Trailer.TIPSTATE_OPEN
273
274 if spec.activeTimer > 0 or isTurnedOn or isDischarging then
275 spec.activeTimer = spec.activeTimer - dt
276 g_animationManager:startAnimations(spec.mixAnimationNodes)
277 else
278 g_animationManager:stopAnimations(spec.mixAnimationNodes)
279 end
280end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
217function MixerWagon:onWriteStream(streamId, connection)
218 local spec = self.spec_mixerWagon
219 for _, entry in ipairs(spec.mixerWagonFillTypes) do
220 streamWriteFloat32(streamId, entry.fillLevel)
221 end
222end

onWriteUpdateStream

Description
Called on on update
Definition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
250function MixerWagon:onWriteUpdateStream(streamId, connection, dirtyMask)
251 if not connection:getIsServer() then
252 local spec = self.spec_mixerWagon
253 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
254
255 for _, entry in ipairs(spec.mixerWagonFillTypes) do
256 streamWriteFloat32(streamId, entry.fillLevel)
257 end
258 end
259 end
260end

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
22function MixerWagon.prerequisitesPresent(specializations)
23 return SpecializationUtil.hasSpecialization(Trailer, specializations) and SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations)
24end

registerEventListeners

Description
Definition
registerEventListeners()
Code
43function MixerWagon.registerEventListeners(vehicleType)
44 SpecializationUtil.registerEventListener(vehicleType, "onLoad", MixerWagon)
45 SpecializationUtil.registerEventListener(vehicleType, "onDelete", MixerWagon)
46 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", MixerWagon)
47 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", MixerWagon)
48 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", MixerWagon)
49 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", MixerWagon)
50 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", MixerWagon)
51 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", MixerWagon)
52 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", MixerWagon)
53 SpecializationUtil.registerEventListener(vehicleType, "onFillUnitFillLevelChanged", MixerWagon)
54end

registerFunctions

Description
Definition
registerFunctions()
Code
28function MixerWagon.registerFunctions(vehicleType)
29 SpecializationUtil.registerFunction(vehicleType, "mixerWagonBaleTriggerCallback", MixerWagon.mixerWagonBaleTriggerCallback)
30end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
34function MixerWagon.registerOverwrittenFunctions(vehicleType)
35 SpecializationUtil.registerOverwrittenFunction(vehicleType, "addFillUnitFillLevel", MixerWagon.addFillUnitFillLevel)
36 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitAllowsFillType", MixerWagon.getFillUnitAllowsFillType)
37 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDischargeFillType", MixerWagon.getDischargeFillType)
38-- SpecializationUtil.registerOverwrittenFunction(vehicleType, "drawMixerWagonHelp", MixerWagon.drawMixerWagonHelp)
39end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
190function MixerWagon:saveToXMLFile(xmlFile, key, usedModNames)
191 local spec = self.spec_mixerWagon
192
193 for i, fillType in ipairs(spec.mixerWagonFillTypes) do
194 local fillTypeKey = string.format("%s.fillType(%d)", key, i-1)
195 setXMLFloat(xmlFile, fillTypeKey.."#fillLevel", fillType.fillLevel)
196 end
197end

updateDebugValues

Description
Definition
updateDebugValues()
Code
496function MixerWagon:updateDebugValues(values)
497 local spec = self.spec_mixerWagon
498
499 table.insert(values, {name="Forage isOK", value=tostring(self:getFillUnitFillType(spec.fillUnitIndex) == FillType.FORAGE)})
500
501 for _, mixerWagonFillType in ipairs(spec.mixerWagonFillTypes) do
502 local fillTypes = ""
503 for fillTypeIndex, _ in pairs(mixerWagonFillType.fillTypes) do
504 fillTypes = fillTypes .. " " .. tostring(g_fillTypeManager:getFillTypeNameByIndex(fillTypeIndex))
505 end
506 table.insert(values, {name=fillTypes, value=mixerWagonFillType.fillLevel})
507 end
508end