LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

TreePlanter

Description
Specialization for tree planters providing possibility to pick up seedling pallets and create trees
Functions

actionEventToggleTreePlanterFieldLimitation

Description
Definition
actionEventToggleTreePlanterFieldLimitation()
Code
959function TreePlanter.actionEventToggleTreePlanterFieldLimitation(self, actionName, inputValue, callbackState, isAnalog)
960 self:setPlantLimitToField(not self.spec_treePlanter.limitToField)
961end

addFillUnitFillLevel

Description
Definition
addFillUnitFillLevel()
Code
594function TreePlanter:addFillUnitFillLevel(superFunc, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData)
595 local spec = self.spec_treePlanter
596 local pallet = spec.mountedSaplingPallet
597
598 if pallet ~= nil then
599 local fillUnits = pallet:getFillUnits()
600 for palletFillUnitIndex, _ in pairs(fillUnits) do
601 if pallet:getFillUnitFillType(fillUnitIndex) == fillTypeIndex then
602 return pallet:addFillUnitFillLevel(self:getOwnerFarmId(), palletFillUnitIndex, fillLevelDelta, fillTypeIndex, ToolType.UNDEFINED)
603 end
604 end
605 end
606
607 return 0
608end

addNodeObjectMapping

Description
Definition
addNodeObjectMapping()
Code
892function TreePlanter:addNodeObjectMapping(superFunc, list)
893 superFunc(self, list)
894
895 local spec = self.spec_treePlanter
896 if spec.palletTrigger ~= nil then
897 list[spec.palletTrigger] = self
898 end
899end

createTree

Description
Create tree on current position
Definition
createTree()
Code
732function TreePlanter:createTree()
733 local spec = self.spec_treePlanter
734
735 if not g_treePlantManager:canPlantTree() then
736 spec.showTooManyTreesWarning = true
737 return
738 end
739
740 if self.isServer and spec.mountedSaplingPallet ~= nil then
741 local pallet = spec.mountedSaplingPallet
742 local x, y, z = getWorldTranslation(spec.node)
743 local yRot = math.random() * 2*math.pi
744
745 local fillType = pallet:getFillUnitFillType(1)
746 local treeTypeIndex = 1
747 if fillType == FillType.TREESAPLINGS then
748 local treeTypeName = pallet:getTreeType()
749 if treeTypeName ~= nil then
750 local desc = g_treePlantManager:getTreeTypeDescFromName(treeTypeName)
751 if desc ~= nil then
752 treeTypeIndex = desc.index
753 end
754 end
755 end
756
757 g_treePlantManager:plantTree(treeTypeIndex, x, y, z, 0, yRot, 0, 0)
758 spec.lastTreePos = {x,y,z}
759
760 local stats = g_farmManager:getFarmById(self:getActiveFarm()).stats
761
762 if g_currentMission.missionInfo.helperBuySeeds and self:getIsAIActive() then
763 local storeItem = g_storeManager:getItemByXMLFilename(pallet.configFileName)
764 local pricePerSapling = 1.5 * (storeItem.price / pallet:getFillUnitCapacity(1))
765
766 stats:updateStats("expenses", pricePerSapling)
767 g_currentMission:addMoney(-pricePerSapling, self:getActiveFarm(), MoneyType.PURCHASE_SEEDS)
768 else
769 -- use 0.9999 instead of 1 to compansate float precision on mp sync
770 local fillLevelChange = -0.9999
771 if self:getFillUnitFillLevel(spec.fillUnitIndex) < 1.5 then
772 fillLevelChange = -math.huge
773 end
774
775 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, fillLevelChange, self:getFillUnitFillType(spec.fillUnitIndex), ToolType.UNDEFINED)
776 end
777
778 -- increase tree plant counter for achievements
779 stats:updateStats("plantedTreeCount", 1)
780 end
781end

doCheckSpeedLimit

Description
Returns if speed limit should be checked
Definition
doCheckSpeedLimit()
Return Values
booleancheckSpeedlimitcheck speed limit
Code
854function TreePlanter:doCheckSpeedLimit(superFunc)
855 return superFunc(self) or (self:getIsTurnedOn() and self:getIsImplementChainLowered())
856end

getCanBeSelected

Description
Definition
getCanBeSelected()
Code
860function TreePlanter:getCanBeSelected(superFunc)
861 return true
862end

getCanPlantOutsideSeason

Description
Definition
getCanPlantOutsideSeason()
Code
712function TreePlanter:getCanPlantOutsideSeason()
713 return false
714end

getDefaultSpeedLimit

Description
Returns default speed limit
Definition
getDefaultSpeedLimit()
Return Values
floatspeedLimitspeed limit
Code
966function TreePlanter.getDefaultSpeedLimit()
967 return 5
968end

getDirtMultiplier

Description
Returns current dirt multiplier
Definition
getDirtMultiplier()
Return Values
floatdirtMultipliercurrent dirt multiplier
Code
797function TreePlanter:getDirtMultiplier(superFunc)
798 local multiplier = superFunc(self)
799
800 local spec = self.spec_treePlanter
801 if spec.hasGroundContact then
802 multiplier = multiplier + self:getWorkDirtMultiplier() * self:getLastSpeed() / self.speedLimit
803 end
804
805 return multiplier
806end

getFillLevelInformation

Description
Definition
getFillLevelInformation()
Code
695function TreePlanter:getFillLevelInformation(superFunc, display)
696 local spec = self.spec_treePlanter
697 local pallet = spec.mountedSaplingPallet
698
699 if pallet ~= nil then
700 local capacity = self:getFillUnitCapacity()
701 local fillLevel = self:getFillUnitFillLevel()
702 local fillType = self:getFillUnitFillType()
703
704 display:addFillLevel(fillType, fillLevel, capacity)
705 end
706
707 superFunc(self, display)
708end

getFillUnitAllowsFillType

Description
Definition
getFillUnitAllowsFillType()
Code
683function TreePlanter:getFillUnitAllowsFillType(superFunc, fillUnitIndex, fillType)
684 return false
685end

getFillUnitCapacity

Description
Definition
getFillUnitCapacity()
Code
666function TreePlanter:getFillUnitCapacity(superFunc, fillUnitIndex)
667 local spec = self.spec_treePlanter
668 local pallet = spec.mountedSaplingPallet
669
670 local capacity = 0
671 if pallet ~= nil then
672 local fillUnits = pallet:getFillUnits()
673 for palletFillUnitIndex, _ in pairs(fillUnits) do
674 capacity = capacity + pallet:getFillUnitCapacity(palletFillUnitIndex)
675 end
676 end
677
678 return capacity
679end

getFillUnitFillLevel

Description
Definition
getFillUnitFillLevel()
Code
612function TreePlanter:getFillUnitFillLevel(superFunc, fillUnitIndex)
613 local spec = self.spec_treePlanter
614 local pallet = spec.mountedSaplingPallet
615
616 local fillLevel = 0
617 if pallet ~= nil then
618 local fillUnits = pallet:getFillUnits()
619 for palletFillUnitIndex, _ in pairs(fillUnits) do
620 fillLevel = fillLevel + pallet:getFillUnitFillLevel(palletFillUnitIndex)
621 end
622 end
623
624 return fillLevel
625end

getFillUnitFillLevelPercentage

Description
Definition
getFillUnitFillLevelPercentage()
Code
629function TreePlanter:getFillUnitFillLevelPercentage(superFunc, fillUnitIndex)
630 local spec = self.spec_treePlanter
631 local pallet = spec.mountedSaplingPallet
632
633 if pallet ~= nil then
634 local capacity = self:getFillUnitCapacity(fillUnitIndex)
635 local fillLevel = self:getFillUnitFillLevel(fillUnitIndex)
636 if capacity > 0 then
637 return fillLevel / capacity
638 end
639 end
640
641 return 0
642end

getFillUnitFillType

Description
Definition
getFillUnitFillType()
Code
646function TreePlanter:getFillUnitFillType(superFunc, fillUnitIndex)
647 local spec = self.spec_treePlanter
648 local pallet = spec.mountedSaplingPallet
649
650 if pallet ~= nil then
651 local fillUnits = pallet:getFillUnits()
652 for palletFillUnitIndex, _ in pairs(fillUnits) do
653 if pallet:getFillUnitFillLevel(palletFillUnitIndex) > 0 then
654 return pallet:getFillUnitFillType(palletFillUnitIndex)
655 end
656 end
657
658 return FillType.UNKNOWN
659 end
660
661 return nil
662end

getFillUnitFreeCapacity

Description
Definition
getFillUnitFreeCapacity()
Code
689function TreePlanter:getFillUnitFreeCapacity(superFunc, fillUnitIndex, fillTypeIndex, farmId)
690 return 0
691end

getIsOnField

Description
Definition
getIsOnField()
Code
877function TreePlanter:getIsOnField(superFunc)
878 if superFunc(self) then
879 return true
880 end
881
882 -- since we don't need to be on a field to work we check only for ground contract
883 if self.spec_treePlanter.hasGroundContact then
884 return true
885 end
886
887 return false
888end

getIsSpeedRotatingPartActive

Description
Returns true if speed rotating part is active
Definition
getIsSpeedRotatingPartActive(table speedRotatingPart)
Arguments
tablespeedRotatingPartspeedRotatingPart
Return Values
booleanisActivespeed rotating part is active
Code
826function TreePlanter:getIsSpeedRotatingPartActive(superFunc, speedRotatingPart)
827 local spec = self.spec_treePlanter
828
829 if not spec.hasGroundContact then
830 return false
831 end
832
833 return superFunc(self, speedRotatingPart)
834end

getIsWorkAreaActive

Description
Definition
getIsWorkAreaActive()
Code
838function TreePlanter:getIsWorkAreaActive(superFunc, workArea)
839 local spec = self.spec_treePlanter
840
841 local isActive = superFunc(self, workArea)
842 if workArea.groundReferenceNode == spec.groundReferenceNode then
843 if not self:getIsTurnedOn() then
844 isActive = false
845 end
846 end
847
848 return isActive
849end

getSaplingPalletInRange

Description
Returns nearest sapling pallet in range
Definition
getSaplingPalletInRange(integer refNode)
Arguments
integerrefNodeid of reference node
Return Values
tableobjectobject of sapling pallet
Code
974function TreePlanter.getSaplingPalletInRange(self, refNode, palletsInTrigger)
975 local spec = self.spec_treePlanter
976
977 local nearestDistance = spec.nearestPalletDistance
978 local nearestSaplingPallet = nil
979
980 for object, state in pairs(palletsInTrigger) do
981 if state ~= nil and state > 0 then
982
983 if object ~= spec.mountedSaplingPallet then
984
985 local distance = calcDistanceFrom(refNode, object.rootNode)
986 if distance < nearestDistance then
987 local validPallet = false
988
989 local fillUnits = object:getFillUnits()
990 for fillUnitIndex, _ in pairs(fillUnits) do
991 local filltype = object:getFillUnitFillType(fillUnitIndex)
992 if filltype ~= FillType.UNKNOWN then
993 if self:getFillUnitSupportsFillType(spec.fillUnitIndex, filltype) then
994 if object:getFillUnitFillLevel(fillUnitIndex) > 0 then
995 validPallet = true
996 break
997 end
998 end
999 end
1000 end
1001
1002 if validPallet then
1003 nearestSaplingPallet = object
1004 end
1005 end
1006
1007 end
1008 end
1009 end
1010 return nearestSaplingPallet
1011end

getWearMultiplier

Description
Returns current wear multiplier
Definition
getWearMultiplier()
Return Values
floatdirtMultipliercurrent wear multiplier
Code
811function TreePlanter:getWearMultiplier(superFunc)
812 local multiplier = superFunc(self)
813
814 local spec = self.spec_treePlanter
815 if spec.hasGroundContact then
816 multiplier = multiplier + self:getWorkWearMultiplier() * self:getLastSpeed() / self.speedLimit
817 end
818
819 return multiplier
820end

initSpecialization

Description
Definition
initSpecialization()
Code
43function TreePlanter.initSpecialization()
44 local schema = Vehicle.xmlSchema
45 schema:setXMLSpecializationType("TreePlanter")
46
47 schema:register(XMLValueType.NODE_INDEX, "vehicle.treePlanter#node", "Node index")
48 schema:register(XMLValueType.FLOAT, "vehicle.treePlanter#minDistance", "Min. distance between trees", 20)
49 schema:register(XMLValueType.NODE_INDEX, "vehicle.treePlanter#palletTrigger", "Pallet trigger")
50 schema:register(XMLValueType.INT, "vehicle.treePlanter#refNodeIndex", "Ground reference node index", 1)
51 schema:register(XMLValueType.NODE_INDEX, "vehicle.treePlanter#saplingPalletGrabNode", "Sapling pallet grab node")
52 schema:register(XMLValueType.NODE_INDEX, "vehicle.treePlanter#saplingPalletMountNode", "Sapling pallet mount node")
53 schema:register(XMLValueType.INT, "vehicle.treePlanter#fillUnitIndex", "Fill unit index")
54 schema:register(XMLValueType.FLOAT, "vehicle.treePlanter#palletMountingRange", "Min. distance from saplingPalletGrabNode to pallet to mount it", 6)
55
56 SoundManager.registerSampleXMLPaths(schema, "vehicle.treePlanter.sounds", "work")
57 AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.treePlanter.animationNodes")
58
59 schema:setXMLSpecializationType()
60
61 local schemaSavegame = Vehicle.xmlSchemaSavegame
62 schemaSavegame:register(XMLValueType.VECTOR_TRANS, "vehicles.vehicle(?).treePlanter#lastTreePos", "Position of last tree")
63 schemaSavegame:register(XMLValueType.BOOL, "vehicles.vehicle(?).treePlanter#palletHadBeenMounted", "Pallet is mounted")
64end

loadPallet

Description
Called on loading
Definition
loadPallet(table savegame)
Arguments
tablesavegamesavegame
Code
786function TreePlanter:loadPallet(palletObjectId, noEventSend)
787 local spec = self.spec_treePlanter
788
789 TreePlanterLoadPalletEvent.sendEvent(self, palletObjectId, noEventSend)
790
791 spec.palletIdToMount = palletObjectId
792end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
195function TreePlanter:onDelete()
196 local spec = self.spec_treePlanter
197
198 g_soundManager:deleteSamples(spec.samples)
199 g_animationManager:deleteAnimations(spec.animationNodes)
200
201 if spec.activatable ~= nil then
202 g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable)
203 end
204
205 if spec.mountedSaplingPallet ~= nil then
206 spec.mountedSaplingPallet:unmount()
207 spec.mountedSaplingPallet = nil
208 end
209
210 if spec.palletTrigger ~= nil then
211 removeTrigger(spec.palletTrigger)
212 end
213end

onDeleteTreePlanterObject

Description
Definition
onDeleteTreePlanterObject()
Code
866function TreePlanter:onDeleteTreePlanterObject(object)
867 local spec = self.spec_treePlanter
868 if spec.mountedSaplingPallet == object then
869 spec.mountedSaplingPallet = nil
870 end
871
872 spec.palletsInTrigger[object] = nil
873end

onDraw

Description
Called on draw
Definition
onDraw(boolean isActiveForInput, boolean isSelected)
Arguments
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
544function TreePlanter:onDraw(isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
545 local spec = self.spec_treePlanter
546
547 if isActiveForInputIgnoreSelection then
548 if self:getFillUnitFillLevel(spec.fillUnitIndex) <= 0 then
549 g_currentMission:addExtraPrintText(g_i18n:getText("info_firstFillTheTool"))
550 end
551 end
552
553 if spec.showFieldNotOwnedWarning then
554 g_currentMission:showBlinkingWarning(g_i18n:getText("warning_youDontHaveAccessToThisLand"))
555 end
556
557 if spec.showRestrictedZoneWarning then
558 g_currentMission:showBlinkingWarning(g_i18n:getText("warning_actionNotAllowedHere"))
559 end
560
561 if spec.showTooManyTreesWarning then
562 g_currentMission:showBlinkingWarning(g_i18n:getText("warning_tooManyTrees"))
563 end
564
565 if spec.showWrongPlantingTimeWarning then
566 g_currentMission:showBlinkingWarning(string.format(g_i18n:getText("warning_theSelectedFruitTypeCantBePlantedInThisPeriod"), g_i18n:formatPeriod()), 100)
567 end
568end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
121function TreePlanter:onLoad(savegame)
122 local spec = self.spec_treePlanter
123
124 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.treePlanterSound", "vehicle.treePlanter.sounds.work") --FS17 to FS19
125 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnedOnRotationNodes.turnedOnRotationNode(0)", "vehicle.treePlanter.animationNodes.animationNode") --FS17 to FS19
126
127 local baseKey = "vehicle.treePlanter"
128
129 if self.isClient then
130 spec.samples = {}
131 spec.samples.work = g_soundManager:loadSampleFromXML(self.xmlFile, baseKey..".sounds", "work", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
132 spec.isWorkSamplePlaying = false
133
134 spec.animationNodes = g_animationManager:loadAnimations(self.xmlFile, baseKey..".animationNodes", self.components, self, self.i3dMappings)
135 end
136
137 spec.node = self.xmlFile:getValue( baseKey.."#node", nil, self.components, self.i3dMappings)
138 spec.minDistance = self.xmlFile:getValue( baseKey.."#minDistance", 20) -- distance to next tree
139
140 spec.palletTrigger = self.xmlFile:getValue( baseKey.."#palletTrigger", nil, self.components, self.i3dMappings)
141 if spec.palletTrigger ~= nil then
142 addTrigger(spec.palletTrigger, "palletTriggerCallback", self)
143 else
144 Logging.xmlWarning(self.xmlFile, "TreePlanter requires a palletTrigger!")
145 end
146 spec.palletsInTrigger = {}
147
148 local refNodeIndex = self.xmlFile:getValue( baseKey.."#refNodeIndex", 1)
149 spec.groundReferenceNode = self:getGroundReferenceNodeFromIndex(refNodeIndex)
150 if spec.groundReferenceNode == nil then
151 Logging.xmlWarning(self.xmlFile, "No groundReferenceNode specified or invalid groundReferenceNode index in '%s'", baseKey.."#refNodeIndex")
152 end
153
154 spec.activatable = TreePlanterActivatable.new(self)
155
156 spec.saplingPalletGrabNode = self.xmlFile:getValue(baseKey.."#saplingPalletGrabNode", self.rootNode, self.components, self.i3dMappings)
157 spec.saplingPalletMountNode = self.xmlFile:getValue(baseKey.."#saplingPalletMountNode", self.rootNode, self.components, self.i3dMappings)
158 spec.mountedSaplingPallet = nil
159
160 spec.fillUnitIndex = self.xmlFile:getValue( baseKey.."#fillUnitIndex", 1)
161 spec.nearestPalletDistance = self.xmlFile:getValue( baseKey.."#palletMountingRange", 6.0)
162
163 spec.currentTree = 1
164 spec.lastTreePos = nil
165
166 spec.showFieldNotOwnedWarning = false
167 spec.showRestrictedZoneWarning = false
168 spec.showTooManyTreesWarning = false
169 spec.hasGroundContact = false
170 spec.showWrongPlantingTimeWarning = false
171
172 spec.limitToField = true
173 spec.forceLimitToField = false
174
175 -- attributes for AI
176 if self.addAIGroundTypeRequirements ~= nil then
177 self:addAIGroundTypeRequirements(TreePlanter.AI_REQUIRED_GROUND_TYPES)
178
179 if self.setAIFruitProhibitions ~= nil then
180 self:setAIFruitProhibitions(FruitType.POPLAR, 1, 5)
181 end
182 end
183
184 spec.dirtyFlag = self:getNextDirtyFlag()
185
186 if savegame ~= nil and not savegame.resetVehicles then
187 spec.lastTreePos = savegame.xmlFile:getValue(savegame.key..".treePlanter#lastTreePos", nil, true)
188
189 spec.palletHadBeenMounted = savegame.xmlFile:getValue(savegame.key .. ".treePlanter#palletHadBeenMounted")
190 end
191end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
245function TreePlanter:onReadStream(streamId, connection)
246 if streamReadBool(streamId) then
247 local spec = self.spec_treePlanter
248 spec.palletIdToMount = NetworkUtil.readNodeObjectId(streamId)
249 end
250end

onReadUpdateStream

Description
Called on on update
Definition
onReadUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
270function TreePlanter:onReadUpdateStream(streamId, timestamp, connection)
271 if connection:getIsServer() then
272 local spec = self.spec_treePlanter
273 if streamReadBool(streamId) then
274 spec.hasGroundContact = streamReadBool(streamId)
275 spec.showFieldNotOwnedWarning = streamReadBool(streamId)
276 spec.showRestrictedZoneWarning = streamReadBool(streamId)
277 end
278 end
279end

onRegisterActionEvents

Description
Definition
onRegisterActionEvents()
Code
945function TreePlanter:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
946 if self.isClient then
947 local spec = self.spec_treePlanter
948 self:clearActionEventsTable(spec.actionEvents)
949
950 if isActiveForInputIgnoreSelection and not spec.forceLimitToField then
951 local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.IMPLEMENT_EXTRA3, self, TreePlanter.actionEventToggleTreePlanterFieldLimitation, false, true, false, true, nil)
952 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL)
953 end
954 end
955end

onTurnedOff

Description
Called on turn off
Definition
onTurnedOff(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
583function TreePlanter:onTurnedOff()
584 if self.isClient then
585 local spec = self.spec_treePlanter
586 g_animationManager:stopAnimations(spec.animationNodes)
587 g_soundManager:stopSamples(spec.samples)
588 spec.isWorkSamplePlaying = false
589 end
590end

onTurnedOn

Description
Called on turn off
Definition
onTurnedOn(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
573function TreePlanter:onTurnedOn()
574 if self.isClient then
575 local spec = self.spec_treePlanter
576 g_animationManager:startAnimations(spec.animationNodes)
577 end
578end

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
302function TreePlanter:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
303 local spec = self.spec_treePlanter
304
305 if self.finishedFirstUpdate then
306 local pallet
307 if spec.palletIdToMount ~= nil then
308 pallet = NetworkUtil.getObject(spec.palletIdToMount)
309 elseif spec.palletHadBeenMounted then
310 spec.palletHadBeenMounted = nil
311 pallet = TreePlanter.getSaplingPalletInRange(self, spec.saplingPalletMountNode, spec.palletsInTrigger)
312 end
313
314 if pallet ~= nil then
315 pallet:mount(self, spec.saplingPalletMountNode, 0,0,0, 0,0,0)
316 spec.mountedSaplingPallet = pallet
317 g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable)
318 spec.palletIdToMount = nil
319 end
320 end
321
322 if self.isClient then
323 local nearestSaplingPallet = nil
324 if spec.mountedSaplingPallet == nil then
325 nearestSaplingPallet = TreePlanter.getSaplingPalletInRange(self, spec.saplingPalletGrabNode, spec.palletsInTrigger)
326 end
327
328 if spec.nearestSaplingPallet ~= nearestSaplingPallet then
329 spec.nearestSaplingPallet = nearestSaplingPallet
330
331 if nearestSaplingPallet ~= nil then
332 g_currentMission.activatableObjectsSystem:addActivatable(spec.activatable)
333 else
334 g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable)
335 end
336 end
337 end
338
339 if spec.mountedSaplingPallet ~= nil then
340 if spec.mountedSaplingPallet.isDeleted then
341 spec.palletsInTrigger[spec.mountedSaplingPallet] = nil
342 spec.mountedSaplingPallet = nil
343 else
344 spec.mountedSaplingPallet:raiseActive()
345 end
346 end
347end

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
354function TreePlanter:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
355 local spec = self.spec_treePlanter
356
357 spec.showTooManyTreesWarning = false
358 local showFieldNotOwnedWarning = false
359 local showRestrictedZoneWarning = false
360
361 if self.isServer then
362 local hasGroundContact = false
363 if spec.groundReferenceNode ~= nil then
364 hasGroundContact = self:getIsGroundReferenceNodeActive(spec.groundReferenceNode)
365 end
366
367 if spec.hasGroundContact ~= hasGroundContact then
368 self:raiseDirtyFlags(spec.dirtyFlag)
369 spec.hasGroundContact = hasGroundContact
370 end
371 end
372
373 if self:getIsAIActive() then
374 if not g_currentMission.missionInfo.helperBuySeeds then
375 if spec.mountedSaplingPallet == nil then
376 local rootVehicle = self.rootVehicle
377 rootVehicle:stopCurrentAIJob(AIMessageErrorOutOfFill.new())
378 end
379 end
380 end
381
382 spec.showWrongPlantingTimeWarning = false
383
384 if spec.hasGroundContact then
385 if self:getIsTurnedOn() then
386 local isPlantingSeason = true
387 if not self:getCanPlantOutsideSeason() then
388 local fillType = self:getFillUnitFillType(spec.fillUnitIndex)
389
390 local fruitType = g_fruitTypeManager:getFruitTypeIndexByFillTypeIndex(fillType)
391 isPlantingSeason = fruitType == nil or g_currentMission.growthSystem:canFruitBePlanted(fruitType)
392 end
393 spec.showWrongPlantingTimeWarning = not isPlantingSeason
394
395 if self.isServer and isPlantingSeason then
396 local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
397 local fillType = self:getFillUnitFillType(spec.fillUnitIndex)
398
399 if g_currentMission.missionInfo.helperBuySeeds then
400 if self:getIsAIActive() then
401 if spec.mountedSaplingPallet ~= nil then
402 fillType = spec.mountedSaplingPallet:getFillUnitFillType(1)
403 else
404 fillType = FillType.POPLAR
405 end
406 end
407 end
408
409 if fillLevel == 0 and (not self:getIsAIActive() or not g_currentMission.missionInfo.helperBuySeeds) then
410 fillType = FillType.UNKNOWN
411 end
412
413 if fillType == FillType.TREESAPLINGS then
414 if self:getLastSpeed() > 1 then
415 local x,y,z = getWorldTranslation(spec.node)
416 if g_currentMission.accessHandler:canFarmAccessLand(self:getActiveFarm(), x, z) then
417 if not PlacementUtil.isInsideRestrictedZone(g_currentMission.restrictedZones, x, y, z, true) then
418 if spec.lastTreePos ~= nil then
419 local distance = MathUtil.vector3Length(x-spec.lastTreePos[1], y-spec.lastTreePos[2], z-spec.lastTreePos[3])
420 if distance > spec.minDistance then
421 self:createTree()
422 end
423 else
424 self:createTree()
425 end
426 else
427 showRestrictedZoneWarning = true
428 end
429 else
430 showFieldNotOwnedWarning = true
431 end
432 end
433 elseif fillType ~= FillType.UNKNOWN then
434 local x,_,z = getWorldTranslation(spec.node)
435 if g_currentMission.accessHandler:canFarmAccessLand(self:getActiveFarm(), x, z) then
436 local width = math.sqrt( g_currentMission:getFruitPixelsToSqm() ) * 0.5
437
438 local sx,_,sz = localToWorld(spec.node, -width,0,width)
439 local wx,_,wz = localToWorld(spec.node, width,0,width)
440 local hx,_,hz = localToWorld(spec.node, -width,0,3*width)
441
442 local fruitType = g_fruitTypeManager:getFruitTypeIndexByFillTypeIndex(fillType)
443 local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitType)
444
445 local dx,_,dz = localDirectionToWorld(spec.node, 0, 0, 1)
446 local angleRad = MathUtil.getYRotationFromDirection(dx, dz)
447 if fruitDesc ~= nil and fruitDesc.directionSnapAngle ~= 0 then
448 angleRad = math.floor(angleRad / fruitDesc.directionSnapAngle + 0.5) * fruitDesc.directionSnapAngle
449 end
450 local angle = FSDensityMapUtil.convertToDensityMapAngle(angleRad, g_currentMission.fieldGroundSystem:getGroundAngleMaxValue())
451
452 -- cultivate
453 local limitToField = spec.limitToField or spec.forceLimitToField
454 local limitFruitDestructionToField = spec.limitToField or spec.forceLimitToField
455 FSDensityMapUtil.updateCultivatorArea(sx,sz, wx,wz, hx,hz, not limitToField, limitFruitDestructionToField, angle, nil)
456 FSDensityMapUtil.eraseTireTrack(sx,sz, wx,wz, hx,hz)
457
458 -- plant, shift area
459 sx,_,sz = localToWorld(spec.node, -width,0,-3*width)
460 wx,_,wz = localToWorld(spec.node, width,0,-3*width)
461 hx,_,hz = localToWorld(spec.node, -width,0,-width)
462
463 local sowingValue = g_currentMission.fieldGroundSystem:getFieldGroundValue(FieldGroundType.SOWN)
464 local area, _ = FSDensityMapUtil.updateSowingArea(fruitType, sx,sz, wx,wz, hx,hz, sowingValue, angle, 2)
465
466 local usage = fruitDesc.seedUsagePerSqm * area
467
468 local stats = g_farmManager:getFarmById(self:getActiveFarm()).stats
469 if self:getIsAIActive() and g_currentMission.missionInfo.helperBuySeeds then
470 local price = usage * g_currentMission.economyManager:getCostPerLiter(FillType.SEEDS, false) * 1.5 -- increase price if AI is active to reward the player's manual work
471 stats:updateStats("expenses", price)
472 g_currentMission:addMoney(-price, self:getActiveFarm(), MoneyType.PURCHASE_SEEDS)
473 else
474 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -usage, fillType, ToolType.UNDEFINED)
475 end
476
477 local lastHa = MathUtil.areaToHa(area, g_currentMission:getFruitPixelsToSqm())
478 stats:updateStats("seedUsage", usage)
479 stats:updateStats("sownHectares", lastHa)
480 stats:updateStats("sownTime", dt/(1000*60))
481
482 self:updateLastWorkedArea(area)
483 else
484 showFieldNotOwnedWarning = true
485 end
486 end
487 end
488 end
489 end
490
491 if self.isServer then
492 if spec.showFieldNotOwnedWarning ~= showFieldNotOwnedWarning or spec.showRestrictedZoneWarning ~= showRestrictedZoneWarning then
493 spec.showFieldNotOwnedWarning = showFieldNotOwnedWarning
494 spec.showRestrictedZoneWarning = showRestrictedZoneWarning
495 self:raiseDirtyFlags(spec.dirtyFlag)
496 end
497 end
498
499 if self.isClient then
500 if self:getIsTurnedOn() and spec.hasGroundContact and self:getLastSpeed() > 1 then
501 if not spec.isWorkSamplePlaying then
502 g_soundManager:playSample(spec.samples.work)
503 spec.isWorkSamplePlaying = true
504 end
505 else
506 if spec.isWorkSamplePlaying then
507 g_soundManager:stopSample(spec.samples.work)
508 spec.isWorkSamplePlaying = false
509 end
510 end
511
512 local actionEvent = spec.actionEvents[InputAction.IMPLEMENT_EXTRA3]
513 if actionEvent ~= nil then
514 local showAction = false
515
516 if isActiveForInputIgnoreSelection then
517 local fillType = self:getFillUnitFillType(spec.fillUnitIndex)
518 if fillType ~= FillType.UNKNOWN and fillType ~= FillType.TREESAPLINGS then
519 if g_currentMission:getHasPlayerPermission("createFields", self:getOwner()) then
520 if not spec.forceLimitToField then
521 showAction = true
522 end
523 end
524 end
525
526 if showAction then
527 if spec.limitToField then
528 g_inputBinding:setActionEventText(actionEvent.actionEventId, g_i18n:getText("action_allowCreateFields"))
529 else
530 g_inputBinding:setActionEventText(actionEvent.actionEventId, g_i18n:getText("action_limitToFields"))
531 end
532 end
533 end
534
535 g_inputBinding:setActionEventActive(actionEvent.actionEventId, showAction)
536 end
537 end
538end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
256function TreePlanter:onWriteStream(streamId, connection)
257 local spec = self.spec_treePlanter
258 streamWriteBool(streamId, spec.mountedSaplingPallet ~= nil)
259 if spec.mountedSaplingPallet ~= nil then
260 local palletId = NetworkUtil.getObjectId(spec.mountedSaplingPallet)
261 NetworkUtil.writeNodeObjectId(streamId, palletId)
262 end
263end

onWriteUpdateStream

Description
Called on on update
Definition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
286function TreePlanter:onWriteUpdateStream(streamId, connection, dirtyMask)
287 if not connection:getIsServer() then
288 local spec = self.spec_treePlanter
289 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
290 streamWriteBool(streamId, spec.hasGroundContact)
291 streamWriteBool(streamId, spec.showFieldNotOwnedWarning)
292 streamWriteBool(streamId, spec.showRestrictedZoneWarning)
293 end
294 end
295end

palletTriggerCallback

Description
Definition
palletTriggerCallback()
Code
914function TreePlanter:palletTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
915 local spec = self.spec_treePlanter
916
917 if otherId ~= 0 then
918 local object = g_currentMission:getNodeObject(otherId)
919 if object ~= nil and object.isa ~= nil then
920 if object:isa(Vehicle) then
921 if object.isPallet and g_currentMission.accessHandler:canFarmAccess(self:getActiveFarm(), object) then
922 local currentValue = Utils.getNoNil(spec.palletsInTrigger[object], 0)
923
924 if onEnter then
925 spec.palletsInTrigger[object] = currentValue + 1
926
927 if currentValue == 0 and object.addDeleteListener ~= nil then
928 object:addDeleteListener(self, "onDeleteTreePlanterObject")
929 end
930 elseif onLeave then
931 spec.palletsInTrigger[object] = math.max(currentValue - 1, 0)
932 end
933
934 if spec.palletsInTrigger[object] == 0 then
935 spec.palletsInTrigger[object] = nil
936 end
937 end
938 end
939 end
940 end
941end

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
35function TreePlanter.prerequisitesPresent(specializations)
36 return SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations)
37 and SpecializationUtil.hasSpecialization(FillUnit, specializations)
38 and SpecializationUtil.hasSpecialization(GroundReference, specializations)
39end

registerEventListeners

Description
Definition
registerEventListeners()
Code
103function TreePlanter.registerEventListeners(vehicleType)
104 SpecializationUtil.registerEventListener(vehicleType, "onLoad", TreePlanter)
105 SpecializationUtil.registerEventListener(vehicleType, "onDelete", TreePlanter)
106 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", TreePlanter)
107 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", TreePlanter)
108 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", TreePlanter)
109 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", TreePlanter)
110 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", TreePlanter)
111 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", TreePlanter)
112 SpecializationUtil.registerEventListener(vehicleType, "onDraw", TreePlanter)
113 SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", TreePlanter)
114 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", TreePlanter)
115 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", TreePlanter)
116end

registerFunctions

Description
Definition
registerFunctions()
Code
68function TreePlanter.registerFunctions(vehicleType)
69 SpecializationUtil.registerFunction(vehicleType, "removeMountedObject", TreePlanter.removeMountedObject)
70 SpecializationUtil.registerFunction(vehicleType, "setPlantLimitToField", TreePlanter.setPlantLimitToField)
71 SpecializationUtil.registerFunction(vehicleType, "createTree", TreePlanter.createTree)
72 SpecializationUtil.registerFunction(vehicleType, "loadPallet", TreePlanter.loadPallet)
73 SpecializationUtil.registerFunction(vehicleType, "palletTriggerCallback", TreePlanter.palletTriggerCallback)
74 SpecializationUtil.registerFunction(vehicleType, "onDeleteTreePlanterObject", TreePlanter.onDeleteTreePlanterObject)
75 SpecializationUtil.registerFunction(vehicleType, "getCanPlantOutsideSeason", TreePlanter.getCanPlantOutsideSeason)
76end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
80function TreePlanter.registerOverwrittenFunctions(vehicleType)
81 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDirtMultiplier", TreePlanter.getDirtMultiplier)
82 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getWearMultiplier", TreePlanter.getWearMultiplier)
83 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsSpeedRotatingPartActive", TreePlanter.getIsSpeedRotatingPartActive)
84 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsWorkAreaActive", TreePlanter.getIsWorkAreaActive)
85 SpecializationUtil.registerOverwrittenFunction(vehicleType, "doCheckSpeedLimit", TreePlanter.doCheckSpeedLimit)
86 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeSelected", TreePlanter.getCanBeSelected)
87 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsOnField", TreePlanter.getIsOnField)
88 SpecializationUtil.registerOverwrittenFunction(vehicleType, "addNodeObjectMapping", TreePlanter.addNodeObjectMapping)
89 SpecializationUtil.registerOverwrittenFunction(vehicleType, "removeNodeObjectMapping", TreePlanter.removeNodeObjectMapping)
90
91 SpecializationUtil.registerOverwrittenFunction(vehicleType, "addFillUnitFillLevel", TreePlanter.addFillUnitFillLevel)
92 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitFillLevel", TreePlanter.getFillUnitFillLevel)
93 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitFillLevelPercentage", TreePlanter.getFillUnitFillLevelPercentage)
94 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitFillType", TreePlanter.getFillUnitFillType)
95 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitCapacity", TreePlanter.getFillUnitCapacity)
96 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitAllowsFillType", TreePlanter.getFillUnitAllowsFillType)
97 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitFreeCapacity", TreePlanter.getFillUnitFreeCapacity)
98 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillLevelInformation", TreePlanter.getFillLevelInformation)
99end

removeMountedObject

Description
Remove mounted object
Definition
removeMountedObject(integer object, boolean isDeleting)
Arguments
integerobjectobject to remove
booleanisDeletingcalled on delete
Code
232function TreePlanter:removeMountedObject(object, isDeleting)
233 local spec = self.spec_treePlanter
234
235 if spec.mountedSaplingPallet == object then
236 spec.mountedSaplingPallet:unmount()
237 spec.mountedSaplingPallet = nil
238 end
239end

removeNodeObjectMapping

Description
Definition
removeNodeObjectMapping()
Code
903function TreePlanter:removeNodeObjectMapping(superFunc, list)
904 superFunc(self, list)
905
906 local spec = self.spec_treePlanter
907 if spec.palletTrigger ~= nil then
908 list[spec.palletTrigger] = nil
909 end
910end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
217function TreePlanter:saveToXMLFile(xmlFile, key, usedModNames)
218 local spec = self.spec_treePlanter
219
220 if spec.lastTreePos ~= nil then
221 xmlFile:setValue(key.."#lastTreePos", unpack(spec.lastTreePos))
222 end
223 if spec.mountedSaplingPallet ~= nil then
224 xmlFile:setValue(key.."#palletHadBeenMounted", true)
225 end
226end

setPlantLimitToField

Description
Set plant limit to field state
Definition
setPlantLimitToField(boolean plantLimitToField, boolean noEventSend)
Arguments
booleanplantLimitToFieldplant limit to field state
booleannoEventSendno event send
Code
720function TreePlanter:setPlantLimitToField(plantLimitToField, noEventSend)
721 local spec = self.spec_treePlanter
722
723 if spec.limitToField ~= plantLimitToField then
724 spec.limitToField = plantLimitToField
725
726 PlantLimitToFieldEvent.sendEvent(self, plantLimitToField, noEventSend)
727 end
728end