LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

Combine

Description
Specialization for combines providing threshing, effects, chopper and swath functionality
Functions

actionEventToggleChopper

Description
Definition
actionEventToggleChopper()
Code
1314function Combine.actionEventToggleChopper(self, actionName, inputValue, callbackState, isAnalog)
1315 local spec = self.spec_combine
1316
1317 if spec.swath.isAvailable then
1318 local fruitType = g_fruitTypeManager:getFruitTypeIndexByFillTypeIndex(self:getFillUnitFillType(spec.fillUnitIndex))
1319 if fruitType ~= nil and fruitType ~= FruitType.UNKNOWN then
1320 local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitType)
1321 if fruitDesc.hasWindrow then
1322 self:setIsSwathActive(not spec.isSwathActive)
1323 else
1324 g_currentMission:showBlinkingWarning(g_i18n:getText("warning_couldNotToggleChopper"), 2000)
1325 end
1326 else
1327 self:setIsSwathActive(not spec.isSwathActive)
1328 end
1329 end
1330end

addCutterArea

Description
Definition
addCutterArea()
Code
865function Combine:addCutterArea(area, realArea, inputFruitType, outputFillType, strawRatio, farmId)
866 local spec = self.spec_combine
867
868 if area > 0 and (spec.lastCuttersFruitType == FruitType.UNKNOWN or spec.lastCuttersArea == 0 or spec.lastCuttersOutputFillType == outputFillType) then
869 spec.lastCuttersArea = spec.lastCuttersArea + area
870 spec.lastCuttersOutputFillType = outputFillType
871 spec.lastCuttersInputFruitType = inputFruitType
872 spec.lastCuttersAreaTime = g_currentMission.time
873
874 if not spec.swath.isAvailable then
875 local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(inputFruitType)
876 spec.isSwathActive = not fruitDesc.hasWindrow
877 end
878
879 local litersPerSqm = 60
880 local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(inputFruitType)
881 if fruitDesc.windrowLiterPerSqm ~= nil then
882 litersPerSqm = fruitDesc.windrowLiterPerSqm
883 end
884
885 local liters = (realArea * g_currentMission:getFruitPixelsToSqm() * litersPerSqm) * strawRatio
886 local inputBuffer = spec.processing.inputBuffer
887 local slot = inputBuffer.buffer[inputBuffer.fillIndex]
888 slot.area = slot.area + area
889 slot.realArea = slot.realArea + realArea
890 slot.liters = slot.liters + liters
891 slot.inputLiters = slot.inputLiters + liters
892 slot.strawRatio = strawRatio
893
894 if spec.fillEnableTime == nil then
895 spec.fillEnableTime = g_currentMission.time + spec.processing.toggleTime
896 end
897
898 -- 8000/1200 = 6.66 liter/meter
899 -- 8000/1200 / 6 = 1.111 liter/m^2
900 -- 8000/1200 / 6 / 2^2 = 0.277777 liter / density pixel (density is 4096^2, on a area of 2048m^2
901 local pixelToSqm = g_currentMission:getFruitPixelsToSqm() -- 4096px are mapped to 2048m
902 local literPerSqm = 1
903 if (inputFruitType ~= FruitType.UNKNOWN) then
904 fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(inputFruitType)
905 literPerSqm = fruitDesc.literPerSqm
906 end
907 local sqm = realArea*pixelToSqm
908 local deltaFillLevel = sqm*literPerSqm*spec.threshingScale
909 local fillType = outputFillType
910
911 self:setWorkedHectars(spec.workedHectars + MathUtil.areaToHa(realArea, g_currentMission:getFruitPixelsToSqm()))
912
913 if farmId ~= AccessHandler.EVERYONE then
914 local damage = self:getVehicleDamage()
915 if damage > 0 then
916 deltaFillLevel = deltaFillLevel * (1 - damage * Combine.DAMAGED_YIELD_REDUCTION)
917 end
918 end
919
920 -- buffer only the set time in the xml, after that we do not add more to the fill unit
921 if self:getFillUnitCapacity(spec.fillUnitIndex) == math.huge and self:getFillUnitFillLevel(spec.fillUnitIndex) > 0.001 then
922 if spec.lastDischargeTime + spec.fillLevelBufferTime < g_time then
923 return deltaFillLevel
924 end
925 end
926
927 local loadInfo = self:getFillVolumeLoadInfo(spec.loadInfoIndex)
928 return self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, deltaFillLevel, fillType, ToolType.UNDEFINED, loadInfo)
929 end
930
931 return 0
932end

addCutterToCombine

Description
Definition
addCutterToCombine()
Code
831function Combine:addCutterToCombine(cutter)
832 local spec = self.spec_combine
833
834 if spec.attachedCutters[cutter] == nil then
835 spec.attachedCutters[cutter] = cutter
836 spec.numAttachedCutters = spec.numAttachedCutters + 1
837 end
838end

getCanBeSelected

Description
Definition
getCanBeSelected()
Code
1101function Combine:getCanBeSelected(superFunc)
1102 return true
1103end

getCanBeTurnedOn

Description
Returns if turn on is allowed
Definition
getCanBeTurnedOn()
Return Values
booleanallowallow turn on
Code
1036function Combine:getCanBeTurnedOn(superFunc)
1037 local spec = self.spec_combine
1038
1039 if spec.numAttachedCutters <= 0 then
1040 return false
1041 end
1042
1043 for cutter, _ in pairs(spec.attachedCutters) do
1044 if cutter ~= self then
1045 if cutter.getCanBeTurnedOn ~= nil and not cutter:getCanBeTurnedOn() then
1046 return false
1047 end
1048 end
1049 end
1050
1051 return superFunc(self)
1052end

getCombineLoadPercentage

Description
Definition
getCombineLoadPercentage()
Code
1013function Combine:getCombineLoadPercentage()
1014 local spec = self.spec_combine
1015 if spec ~= nil then
1016 if spec.numAttachedCutters > 0 then
1017 local loadSum = 0
1018 for cutter, _ in pairs(spec.attachedCutters) do
1019 if cutter.getCutterLoad ~= nil then
1020 loadSum = loadSum + cutter:getCutterLoad()
1021 end
1022 end
1023
1024 return loadSum / spec.numAttachedCutters
1025 end
1026 end
1027
1028 return 0
1029end

getFillLevelDependentSpeed

Description
Definition
getFillLevelDependentSpeed()
Code
997function Combine:getFillLevelDependentSpeed()
998 local spec = self.spec_combine
999 if spec.rotationNodesSpeedReverseFillLevel ~= nil then
1000 local fillLevelPct = self:getFillUnitFillLevel(spec.fillUnitIndex) / self:getFillUnitCapacity(spec.fillUnitIndex)
1001 if fillLevelPct > spec.rotationNodesSpeedReverseFillLevel then
1002 return -1
1003 else
1004 return 1
1005 end
1006 else
1007 return 1
1008 end
1009end

getIsBufferCombine

Description
Definition
getIsBufferCombine()
Code
991function Combine:getIsBufferCombine()
992 return self:getFillUnitCapacity(self.spec_combine.fillUnitIndex) == math.huge
993end

getIsFoldAllowed

Description
Returns if fold is allowed
Definition
getIsFoldAllowed()
Return Values
booleanallowsFoldallows folding
Code
1084function Combine:getIsFoldAllowed(superFunc, direction, onAiTurnOn)
1085 local spec = self.spec_combine
1086
1087 if not self.allowFoldWhileThreshing and self:getIsTurnedOn() then
1088 return false
1089 end
1090
1091 local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
1092 if direction == spec.foldDirection and (fillLevel > spec.foldFillLevelThreshold and self:getFillUnitCapacity(spec.fillUnitIndex) ~= math.huge) then
1093 return false
1094 end
1095
1096 return superFunc(self, direction, onAiTurnOn)
1097end

getIsThreshingAllowed

Description
Returns if threshing is allowed
Definition
getIsThreshingAllowed(boolean earlyWarning)
Arguments
booleanearlyWarningearly warning
Return Values
booleanallowsallows threshing
Code
938function Combine:getIsThreshingAllowed(earlyWarning)
939 local spec = self.spec_combine
940
941 if spec.allowThreshingDuringRain then
942 return true
943 end
944
945 local rainScale = g_currentMission.environment.weather:getRainFallScale()
946 local timeSinceLastRain = g_currentMission.environment.weather:getTimeSinceLastRain()
947 if earlyWarning ~= nil and earlyWarning == true then
948 if rainScale <= 0.02 and timeSinceLastRain > 20 then
949 return true
950 end
951 else
952 if rainScale <= 0.1 and timeSinceLastRain > 20 then
953 return true
954 end
955 end
956
957 return false
958end

getTurnedOnNotAllowedWarning

Description
Returns turn on not allowed warning text
Definition
getTurnedOnNotAllowedWarning()
Return Values
stringwarningTextturn on not allowed warning text
Code
1057function Combine:getTurnedOnNotAllowedWarning(superFunc)
1058 if self:getIsActiveForInput(true) then
1059 local spec = self.spec_combine
1060 if not self:getCanBeTurnedOn() then
1061 if spec.numAttachedCutters == 0 then
1062 return spec.noCutterWarning
1063 else
1064 for cutter, _ in pairs(spec.attachedCutters) do
1065 if cutter ~= self then
1066 if cutter.getTurnedOnNotAllowedWarning ~= nil then
1067 local warning = cutter:getTurnedOnNotAllowedWarning()
1068 if warning ~= nil then
1069 return warning
1070 end
1071 end
1072 end
1073 end
1074 end
1075 end
1076 end
1077
1078 return superFunc(self)
1079end

initSpecialization

Description
Definition
initSpecialization()
Code
18function Combine.initSpecialization()
19 g_workAreaTypeManager:addWorkAreaType("combineChopper", false)
20 g_workAreaTypeManager:addWorkAreaType("combineSwath", false)
21end

loadCombineEffects

Description
Definition
loadCombineEffects()
Code
534function Combine:loadCombineEffects(xmlFile, baseKey, entry)
535 if self.isClient then
536 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, baseKey .. ".chopperParticleSystems", baseKey..".chopperEffect") --FS17 to FS19
537 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, baseKey .. ".strawParticleSystems", baseKey..".strawEffect") --FS17 to FS19
538 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, baseKey .. ".threshingFillParticleSystems", baseKey..".fillEffect") --FS17 to FS19
539
540 entry.chopperEffects = g_effectManager:loadEffect(self.xmlFile, baseKey .. ".chopperEffect", self.components, self, self.i3dMappings)
541 entry.strawEffects = g_effectManager:loadEffect(self.xmlFile, baseKey .. ".strawEffect", self.components, self, self.i3dMappings)
542 entry.fillEffects = g_effectManager:loadEffect(self.xmlFile, baseKey .. ".fillEffect", self.components, self, self.i3dMappings)
543
544 entry.strawPSenabled = false
545 entry.chopperPSenabled = false
546 entry.isFilling = false
547
548 entry.fillEnableTime = nil
549 entry.fillDisableTime = nil
550 end
551end

loadCombineRotationNodes

Description
Definition
loadCombineRotationNodes()
Code
556function Combine:loadCombineRotationNodes(xmlFile, baseKey, entry)
557 if self.isClient then
558 entry.animationNodes = g_animationManager:loadAnimations(xmlFile, baseKey..".animationNodes", self.components, self, self.i3dMappings)
559 entry.fillingAnimationNodes = g_animationManager:loadAnimations(xmlFile, baseKey..".fillingAnimationNodes", self.components, self, self.i3dMappings)
560 entry.rotationNodesSpeedReverseFillLevel = getXMLFloat(xmlFile, baseKey .. ".animationNodes#speedReverseFillLevel")
561 end
562end

loadCombineSamples

Description
Definition
loadCombineSamples()
Code
567function Combine:loadCombineSamples(xmlFile, key, entry)
568 if self.isClient then
569 entry.samples = {}
570 entry.samples.start = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "start", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
571 entry.samples.stop = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "stop", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self)
572 entry.samples.work = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "work", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
573 end
574end

loadCombineSetup

Description
Definition
loadCombineSetup()
Code
451function Combine:loadCombineSetup(xmlFile, baseKey, entry)
452 entry.allowThreshingDuringRain = Utils.getNoNil(getXMLBool(xmlFile, baseKey .. "#allowThreshingDuringRain"), false)
453
454 entry.fillUnitIndex = Utils.getNoNil(getXMLInt(xmlFile, baseKey .. "#fillUnitIndex"), 1)
455 entry.loadInfoIndex = Utils.getNoNil(getXMLInt(xmlFile, baseKey .. "#loadInfoIndex"), 1)
456
457 -- swath
458 entry.swath = {}
459 entry.swath.isAvailable = Utils.getNoNil(getXMLBool(xmlFile, baseKey .. ".swath#available"), false)
460 local isDefaultActive = Utils.getNoNil(getXMLBool(xmlFile, baseKey .. ".swath#isDefaultActive"), entry.swath.isAvailable)
461 if entry.swath.isAvailable then
462 entry.swath.workAreaIndex = getXMLInt(xmlFile, baseKey .. ".swath#workAreaIndex")
463 if entry.swath.workAreaIndex == nil then
464 entry.swath.isAvailable = false
465 g_logManager:xmlWarning(self.configFileName, "Missing 'swath#workAreaIndex' for combine swath function!")
466 end
467 entry.warningTime = 0
468 end
469
470 -- chopper
471 entry.chopper = {}
472 entry.chopper.isAvailable = Utils.getNoNil(getXMLBool(xmlFile, baseKey .. ".chopper#available"), false)
473 if entry.chopper.isAvailable then
474 entry.chopper.workAreaIndex = getXMLInt(xmlFile, baseKey .. ".chopper#workAreaIndex")
475 if entry.chopper.workAreaIndex == nil then
476 entry.chopper.isAvailable = false
477 g_logManager:xmlWarning(self.configFileName, "Missing 'chopper#workAreaIndex' for combine chopper function!")
478 end
479
480 entry.chopper.animName = getXMLString(xmlFile, baseKey .. ".chopper#animName")
481 entry.chopper.animSpeedScale = getXMLFloat(xmlFile, baseKey .. ".chopper#animSpeedScale")
482 end
483
484 entry.isSwathActive = isDefaultActive
485
486 --ladder
487 entry.ladder = {}
488 entry.ladder.animName = getXMLString(xmlFile, baseKey .. ".ladder#animName")
489 entry.ladder.animSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, baseKey .. ".ladder#animSpeedScale"), 1)
490 entry.ladder.foldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, baseKey .. ".ladder#foldMinLimit"), 0.99)
491 entry.ladder.foldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, baseKey .. ".ladder#foldMaxLimit"), 1)
492 entry.ladder.foldDirection = Utils.getNoNil(getXMLFloat(xmlFile, baseKey .. ".ladder#foldDirection"), MathUtil.sign(entry.ladder.animSpeedScale))
493
494 -- processing buffer
495 entry.processing = {}
496 local toggleTime = getXMLFloat(xmlFile, baseKey .. ".processing#toggleTime")
497 if toggleTime == nil and entry.chopper.animName ~= nil then
498 toggleTime = self:getAnimationDurection(entry.chopper.animName)
499 if toggleTime ~= nil then
500 toggleTime = toggleTime / 1000
501 end
502 end
503 entry.processing.toggleTime = Utils.getNoNil(toggleTime, 0) * 1000
504
505 local inputBuffer = {}
506 local slotDuration = 300
507 local slotCount = MathUtil.clamp(math.ceil(entry.processing.toggleTime / slotDuration), 2, 20)
508 inputBuffer.slotCount = slotCount
509 inputBuffer.slotDuration = math.ceil( entry.processing.toggleTime / inputBuffer.slotCount )
510 inputBuffer.fillIndex = 1
511 inputBuffer.dropIndex = inputBuffer.fillIndex + 1
512 inputBuffer.slotTimer = inputBuffer.slotDuration
513 inputBuffer.activeTimeout = inputBuffer.slotDuration * (inputBuffer.slotCount + 2)
514 inputBuffer.activeTimer = inputBuffer.activeTimeout
515 inputBuffer.buffer = {}
516 for i=1, inputBuffer.slotCount do
517 table.insert(inputBuffer.buffer, {realArea = 0, area = 0, liters = 0, inputLiters = 0, strawRatio = 0} )
518 end
519 entry.processing.inputBuffer = inputBuffer
520
521 -- threhsing start animation
522 entry.threshingStartAnimation = getXMLString(xmlFile, baseKey .. ".threshingStartAnimation#name")
523 entry.threshingStartAnimationSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, baseKey .. ".threshingStartAnimation#speedScale"), 1)
524 entry.threshingStartAnimationInitialIsStarted = Utils.getNoNil(getXMLBool(xmlFile, baseKey .. ".threshingStartAnimation#initialIsStarted"), false)
525
526 entry.foldFillLevelThreshold = Utils.getNoNil(getXMLFloat(xmlFile, baseKey .. ".folding#fillLevelThreshold"), (self:getFillUnitCapacity(entry.fillUnitIndex) or 0.04) * 0.15)
527 entry.foldDirection = Utils.getNoNil(getXMLInt(xmlFile, baseKey .. ".folding#direction"), 1)
528 entry.allowFoldWhileThreshing = Utils.getNoNil(getXMLBool(xmlFile, baseKey .. ".folding#allowWhileThreshing"), false)
529end

loadWorkAreaFromXML

Description
Definition
loadWorkAreaFromXML()
Code
1107function Combine:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key)
1108 if not superFunc(self, workArea, xmlFile, key) then
1109 return false
1110 end
1111
1112 if workArea.type == WorkAreaType.COMBINECHOPPER or workArea.type == WorkAreaType.COMBINESWATH then
1113 if getXMLBool(xmlFile, key .. "#requiresOwnedFarmland") == nil then
1114 workArea.requiresOwnedFarmland = false
1115 end
1116 if getXMLBool(xmlFile, key .. "#needsSetIsTurnedOn") == nil then
1117 workArea.needsSetIsTurnedOn = false
1118 end
1119 end
1120
1121 return true
1122end

onChangedFillType

Description
Definition
onChangedFillType()
Code
1173function Combine:onChangedFillType(fillUnitIndex, fillTypeIndex)
1174 local spec = self.spec_combine
1175 if fillUnitIndex == spec.fillUnitIndex then
1176 if spec.chopperPSenabled then
1177 self:setChopperPSEnabled(true, true, true)
1178 end
1179 if spec.strawPSenabled then
1180 self:setStrawPSEnabled(true, true, true)
1181 end
1182 if spec.isFilling then
1183 self:setCombineIsFilling(true, true, true)
1184 end
1185 end
1186end

onDeactivate

Description
Called on deactivate
Definition
onDeactivate()
Code
1190function Combine:onDeactivate()
1191 local spec = self.spec_combine
1192
1193 self:setChopperPSEnabled(false, false, true)
1194 self:setStrawPSEnabled(false, false, true)
1195 self:setCombineIsFilling(false, false, true)
1196 spec.fillEnableTime = nil
1197 spec.fillDisableTime = nil
1198end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
200function Combine:onDelete()
201 if self.isClient then
202 local spec = self.spec_combine
203
204 g_effectManager:deleteEffects(spec.fillEffects)
205 g_effectManager:deleteEffects(spec.strawEffects)
206 g_effectManager:deleteEffects(spec.chopperEffects)
207
208 g_animationManager:deleteAnimations(spec.animationNodes)
209
210 g_soundManager:deleteSamples(spec.samples)
211 end
212end

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
443function Combine:onDraw(isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
444 if self:getIsTurnedOn() and not self:getIsThreshingAllowed(false) then
445 g_currentMission:showBlinkingWarning(g_i18n:getText("warning_doNotThreshDuringRainOrHail"), 2000)
446 end
447end

onEndWorkAreaProcessing

Description
Definition
onEndWorkAreaProcessing()
Code
1165function Combine:onEndWorkAreaProcessing(dt, hasProcessed)
1166 local spec = self.spec_combine
1167 local inputBuffer = spec.processing.inputBuffer
1168 inputBuffer.buffer[inputBuffer.dropIndex].liters = math.max(0, inputBuffer.buffer[inputBuffer.dropIndex].liters - spec.workAreaParameters.droppedLiters)
1169end

onEnterVehicle

Description
Definition
onEnterVehicle()
Code
1255function Combine:onEnterVehicle()
1256 local ladder = self.spec_combine.ladder
1257 if ladder.animName ~= nil then
1258 local fold = true
1259 if self.getFoldAnimTime ~= nil then
1260 local foldAnimTime = self:getFoldAnimTime()
1261 if foldAnimTime > ladder.foldMaxLimit or foldAnimTime < ladder.foldMinLimit then
1262 fold = false
1263 end
1264 end
1265
1266 if fold then
1267 self:playAnimation(ladder.animName, -ladder.animSpeedScale, self:getAnimationTime(ladder.animName), true)
1268 end
1269 end
1270end

onFillUnitFillLevelChanged

Description
Definition
onFillUnitFillLevelChanged()
Code
1302function Combine:onFillUnitFillLevelChanged(fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData, appliedDelta)
1303 local spec = self.spec_combine
1304
1305 if fillUnitIndex == spec.fillUnitIndex then
1306 if fillLevelDelta < 0 then
1307 spec.lastDischargeTime = g_time
1308 end
1309 end
1310end

onFoldStateChanged

Description
Definition
onFoldStateChanged()
Code
1293function Combine:onFoldStateChanged(direction, moveToMiddle)
1294 local ladder = self.spec_combine.ladder
1295 if ladder.animName ~= nil and direction ~= 0 and not moveToMiddle then
1296 self:playAnimation(ladder.animName, direction*ladder.animSpeedScale*ladder.foldDirection, self:getAnimationTime(ladder.animName), true)
1297 end
1298end

onLeaveVehicle

Description
Definition
onLeaveVehicle()
Code
1274function Combine:onLeaveVehicle()
1275 local ladder = self.spec_combine.ladder
1276 if ladder.animName ~= nil then
1277 local fold = true
1278 if self.getFoldAnimTime ~= nil then
1279 local foldAnimTime = self:getFoldAnimTime()
1280 if foldAnimTime > ladder.foldMaxLimit or foldAnimTime < ladder.foldMinLimit then
1281 fold = false
1282 end
1283 end
1284
1285 if fold then
1286 self:playAnimation(ladder.animName, ladder.animSpeedScale, self:getAnimationTime(ladder.animName), true)
1287 end
1288 end
1289end

onLoad

Description
Definition
onLoad()
Code
106function Combine:onLoad(savegame)
107 local spec = self.spec_combine
108
109 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.combine.chopperSwitch", "vehicle.combine.swath and vehicle.combine.chopper") --FS17 to FS19
110 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.turnedOnRotationNodes.turnedOnRotationNode#type", "vehicle.combine.rotationNodes.rotationNode", "combine") --FS17 to FS19
111 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, "vehicle.indoorHud.workedHectars", "vehicle.combine.dashboards.dashboard with valueType 'workedHectars'") --FS17 to FS19
112
113 self:loadCombineSetup(self.xmlFile, "vehicle.combine", spec)
114 self:loadCombineEffects(self.xmlFile, "vehicle.combine", spec)
115 self:loadCombineRotationNodes(self.xmlFile, "vehicle.combine", spec)
116 self:loadCombineSamples(self.xmlFile, "vehicle.combine", spec)
117
118 spec.attachedCutters = {}
119 spec.numAttachedCutters = 0
120
121 spec.noCutterWarning = g_i18n:convertText(Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.combine.warning#noCutter"), "$l10n_warning_noCuttersAttached"), self.customEnvironment)
122
123 spec.lastArea = 0
124 spec.lastAreaZeroTime = 0
125 spec.lastAreaNonZeroTime = -1000000
126 spec.lastCuttersArea = 0
127 spec.lastCuttersAreaTime = -10000
128 spec.lastInputFruitType = FruitType.UNKNOWN
129 spec.lastValidInputFruitType = FruitType.UNKNOWN
130 spec.lastCuttersFruitType = FruitType.UNKNOWN
131 spec.lastCuttersInputFruitType = FruitType.UNKNOWN
132 spec.lastDischargeTime = 0
133 spec.lastChargeTime = 0
134 spec.fillLevelBufferTime = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.combine#fillLevelBufferTime"), 2000) -- time the fill level buffer is filled without unloading
135
136 spec.workedHectars = 0
137 spec.workedHectarsSent = 0
138 if self.loadDashboardsFromXML ~= nil then
139 local dashboardData = {valueTypeToLoad = "workedHectars",
140 valueObject = spec,
141 valueFunc = "workedHectars"}
142
143 self:loadDashboardsFromXML(self.xmlFile, "vehicle.combine.dashboards", dashboardData)
144 end
145
146 spec.threshingScale = 1
147 spec.lastLostFillLevel = 0
148
149 spec.workAreaParameters = {}
150 spec.workAreaParameters.lastRealArea = 0
151 spec.workAreaParameters.lastArea = 0
152 spec.workAreaParameters.litersToDrop = 0
153 spec.workAreaParameters.droppedLiters = 0
154 spec.workAreaParameters.isChopperEffectEnabled = 0
155 spec.workAreaParameters.isStrawEffectEnabled = 0
156
157 spec.dirtyFlag = self:getNextDirtyFlag()
158end

onPostAttachImplement

Description
Called on attaching a implement
Definition
onPostAttachImplement(table implement)
Arguments
tableimplementimplement to attach
Code
1203function Combine:onPostAttachImplement(attachable, inputJointDescIndex, jointDescIndex)
1204 local spec = self.spec_combine
1205
1206 local attacherJoint = attachable:getActiveInputAttacherJoint()
1207 if attacherJoint ~= nil then
1208 if attacherJoint.jointType == AttacherJoints.JOINTTYPE_CUTTER or attacherJoint.jointType == AttacherJoints.JOINTTYPE_CUTTERHARVESTER then
1209 self:addCutterToCombine(attachable)
1210 end
1211 end
1212end

onPostDetachImplement

Description
Called on detaching a implement
Definition
onPostDetachImplement(integer implementIndex)
Arguments
integerimplementIndexindex of implement to detach
Code
1217function Combine:onPostDetachImplement(implementIndex)
1218 local spec = self.spec_combine
1219
1220 local object = self:getObjectFromImplementIndex(implementIndex)
1221 if object ~= nil then
1222 local attacherJoint = object:getActiveInputAttacherJoint()
1223 if attacherJoint ~= nil then
1224 if attacherJoint.jointType == AttacherJoints.JOINTTYPE_CUTTER or attacherJoint.jointType == AttacherJoints.JOINTTYPE_CUTTERHARVESTER then
1225 self:removeCutterFromCombine(object)
1226 end
1227 end
1228 end
1229end

onPostLoad

Description
Called after loading
Definition
onPostLoad(table savegame)
Arguments
tablesavegamesavegame
Code
163function Combine:onPostLoad(savegame)
164 local spec = self.spec_combine
165
166 if savegame ~= nil then
167 if spec.swath.isAvailable then
168 local isSwathActive = Utils.getNoNil(getXMLBool(savegame.xmlFile, savegame.key .. ".combine#isSwathActive"), spec.isSwathActive)
169 self:setIsSwathActive(isSwathActive, true, true)
170 end
171 self:setWorkedHectars(Utils.getNoNil(getXMLFloat(savegame.xmlFile, savegame.key .. ".combine#workedHectars"), spec.workedHectars))
172 else
173 self:setIsSwathActive(spec.isSwathActive, true, true)
174 end
175
176 local ladder = spec.ladder
177 if ladder.animName ~= nil then
178 local time = 0
179 if self.getFoldAnimTime ~= nil then
180 local foldAnimTime = self:getFoldAnimTime()
181 if foldAnimTime > ladder.foldMaxLimit or foldAnimTime < ladder.foldMinLimit then
182 time = 1
183 end
184 end
185
186 if ladder.foldDirection ~= 1 then
187 time = 1 - time
188 end
189
190 self:setAnimationTime(ladder.animName, time, true)
191 end
192
193 if self:getFillUnitCapacity(spec.fillUnitIndex) == 0 then
194 g_logManager:xmlWarning(self.configFileName, "Capacity of fill unit '%d' for combine needs to be set greater 0 or not defined! (not defined = infinity)", spec.fillUnitIndex)
195 end
196end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
229function Combine:onReadStream(streamId, connection)
230 local spec = self.spec_combine
231
232 spec.lastValidInputFruitType = streamReadUIntN(streamId, FruitTypeManager.SEND_NUM_BITS)
233 local combineIsFilling = streamReadBool(streamId)
234 local chopperPSenabled = streamReadBool(streamId)
235 local strawPSenabled = streamReadBool(streamId)
236
237 self:setCombineIsFilling(combineIsFilling, false, true)
238 self:setChopperPSEnabled(chopperPSenabled, false, true)
239 self:setStrawPSEnabled(strawPSenabled, false, true)
240
241 local isSwathActive = streamReadBool(streamId)
242 self:setIsSwathActive(isSwathActive, true)
243
244 local workedHectars = streamReadFloat32(streamId)
245 self:setWorkedHectars(workedHectars)
246end

onReadUpdateStream

Description
Called on on update
Definition
onReadUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
269function Combine:onReadUpdateStream(streamId, timestamp, connection)
270 if connection:getIsServer() then
271 if streamReadBool(streamId) then
272 local spec = self.spec_combine
273 spec.lastValidInputFruitType = streamReadUIntN(streamId, FruitTypeManager.SEND_NUM_BITS)
274
275 local combineIsFilling = streamReadBool(streamId)
276 local chopperPSenabled = streamReadBool(streamId)
277 local strawPSenabled = streamReadBool(streamId)
278 self:setCombineIsFilling(combineIsFilling, false, true)
279 self:setChopperPSEnabled(chopperPSenabled, false, true)
280 self:setStrawPSEnabled(strawPSenabled, false, true)
281
282 local workedHectars = streamReadFloat32(streamId)
283 self:setWorkedHectars(workedHectars)
284 end
285 end
286end

onRegisterActionEvents

Description
Definition
onRegisterActionEvents()
Code
1126function Combine:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
1127 if self.isClient then
1128
1129 local spec = self.spec_combine
1130 self:clearActionEventsTable(spec.actionEvents)
1131
1132 if isActiveForInputIgnoreSelection and spec.swath.isAvailable and spec.chopper.isAvailable then
1133 local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_CHOPPER, self, Combine.actionEventToggleChopper, false, true, false, true, nil)
1134 g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL)
1135 Combine.updateToggleStrawText(self)
1136 end
1137 end
1138end

onStartWorkAreaProcessing

Description
Definition
onStartWorkAreaProcessing()
Code
1142function Combine:onStartWorkAreaProcessing(dt)
1143 local spec = self.spec_combine
1144
1145 spec.workAreaParameters.droppedLiters = 0
1146 spec.workAreaParameters.litersToDrop = 0
1147 spec.workAreaParameters.strawRatio = 0
1148 spec.workAreaParameters.dropFillType = FillType.UNKNOWN
1149
1150 local lastValidFillType = self:getFillUnitLastValidFillType(spec.fillUnitIndex)
1151 if lastValidFillType ~= FillType.UNKNOWN then
1152 local inputBuffer = spec.processing.inputBuffer
1153 local inputLiters = inputBuffer.buffer[inputBuffer.dropIndex].inputLiters
1154 spec.workAreaParameters.litersToDrop = math.min(inputBuffer.buffer[inputBuffer.dropIndex].liters, (dt / inputBuffer.slotDuration) * inputLiters)
1155 spec.workAreaParameters.strawRatio = inputBuffer.buffer[inputBuffer.dropIndex].strawRatio
1156 spec.workAreaParameters.dropFillType = lastValidFillType
1157 end
1158
1159 spec.workAreaParameters.lastRealArea = 0
1160 spec.workAreaParameters.lastArea = 0
1161end

onTurnedOff

Description
Called on turn off
Definition
onTurnedOff(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
1245function Combine:onTurnedOff()
1246 self:stopThreshing()
1247 if self.isClient then
1248 local spec = self.spec_combine
1249 g_animationManager:stopAnimations(spec.animationNodes)
1250 end
1251end

onTurnedOn

Description
Called on turn on
Definition
onTurnedOn(boolean noEventSend)
Arguments
booleannoEventSendno event send
Code
1234function Combine:onTurnedOn()
1235 self:startThreshing()
1236 if self.isClient then
1237 local spec = self.spec_combine
1238 g_animationManager:startAnimations(spec.animationNodes)
1239 end
1240end

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
313function Combine:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
314 local spec = self.spec_combine
315
316 local isTurnedOn = self:getIsTurnedOn()
317 if isTurnedOn then
318 if self.isServer and spec.swath.isAvailable then
319 -- check for changes while threshing, e.g. activated straw swath and then start threshing canola (has no windrow)
320 local fruitType = g_fruitTypeManager:getFruitTypeIndexByFillTypeIndex(self:getFillUnitFillType(spec.fillUnitIndex))
321 if spec.isSwathActive and fruitType ~= nil and fruitType ~= FruitType.UNKNOWN then
322 local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitType)
323 if not fruitDesc.hasWindrow then
324 self:setIsSwathActive(false)
325 end
326 else
327 -- if the combine does not support chopper but it was forced by the last fill type
328 -- if the new fill type supports swath again we change it back
329 if not spec.chopper.isAvailable then
330 if not spec.isSwathActive and fruitType ~= nil and fruitType ~= FruitType.UNKNOWN then
331 local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitType)
332 if fruitDesc.hasWindrow then
333 self:setIsSwathActive(true)
334 end
335 end
336 end
337 end
338 end
339 end
340
341 if self.isServer then
342 if self:getFillUnitFillLevel(spec.fillUnitIndex) < 0.0001 then
343 spec.lastDischargeTime = g_time
344 end
345 end
346end

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
353function Combine:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
354 local spec = self.spec_combine
355
356 if self.isServer then
357 spec.lastArea = spec.lastCuttersArea
358 spec.lastAreaZeroTime = spec.lastAreaZeroTime + dt
359 if spec.lastArea > 0 then
360 spec.lastAreaZeroTime = 0
361 spec.lastAreaNonZeroTime = g_currentMission.time
362 end
363 spec.lastInputFruitType = spec.lastCuttersInputFruitType
364 spec.lastCuttersArea = 0
365 spec.lastCuttersInputFruitType = FruitType.UNKNOWN
366 spec.lastCuttersFruitType = FruitType.UNKNOWN
367
368 if spec.lastInputFruitType ~= FruitType.UNKNOWN then
369 spec.lastValidInputFruitType = spec.lastInputFruitType
370 end
371
372 local inputBuffer = spec.processing.inputBuffer
373
374 if spec.lastAreaZeroTime > 500 then
375 if spec.fillDisableTime == nil then
376 spec.fillDisableTime = g_currentMission.time + spec.processing.toggleTime
377 end
378 end
379 if spec.fillEnableTime ~= nil and spec.fillEnableTime <= g_currentMission.time then
380 self:setCombineIsFilling(true, false, false)
381 spec.fillEnableTime = nil
382 end
383 if spec.fillDisableTime ~= nil and spec.fillDisableTime <= g_currentMission.time then
384 self:setCombineIsFilling(false, false, false)
385 spec.fillDisableTime = nil
386 end
387
388 spec.workAreaParameters.isChopperEffectEnabled = math.max(spec.workAreaParameters.isChopperEffectEnabled - dt, 0)
389 spec.workAreaParameters.isStrawEffectEnabled = math.max(spec.workAreaParameters.isStrawEffectEnabled - dt, 0)
390
391 local chopperPSActive = spec.workAreaParameters.isChopperEffectEnabled > 0
392 local strawPSActive = spec.workAreaParameters.isStrawEffectEnabled > 0
393 self:setChopperPSEnabled(chopperPSActive, false, false)
394 self:setStrawPSEnabled(strawPSActive, false, false)
395
396 if chopperPSActive or strawPSActive then
397 self:raiseActive()
398 end
399
400 if self:getIsTurnedOn() then
401 local stats = g_currentMission:farmStats(self:getOwnerFarmId())
402 stats:updateStats("threshedTime", dt / (1000 * 60))
403 stats:updateStats("workedTime", dt / (1000 * 60))
404 end
405
406 inputBuffer.slotTimer = inputBuffer.slotTimer - dt
407 if inputBuffer.slotTimer < 0 then
408 inputBuffer.slotTimer = inputBuffer.slotDuration
409
410 inputBuffer.fillIndex = inputBuffer.fillIndex + 1
411 if inputBuffer.fillIndex > inputBuffer.slotCount then
412 inputBuffer.fillIndex = 1
413 end
414
415 local lastDropIndex = inputBuffer.dropIndex
416 inputBuffer.dropIndex = inputBuffer.dropIndex + 1
417 if inputBuffer.dropIndex > inputBuffer.slotCount then
418 inputBuffer.dropIndex = 1
419 end
420
421 inputBuffer.buffer[inputBuffer.dropIndex].liters = inputBuffer.buffer[inputBuffer.dropIndex].liters + inputBuffer.buffer[lastDropIndex].liters
422 inputBuffer.buffer[inputBuffer.dropIndex].inputLiters = inputBuffer.buffer[inputBuffer.dropIndex].inputLiters + inputBuffer.buffer[lastDropIndex].liters --inputLiters
423
424 inputBuffer.buffer[lastDropIndex].area = 0
425 inputBuffer.buffer[lastDropIndex].realArea = 0
426 inputBuffer.buffer[lastDropIndex].liters = 0
427 inputBuffer.buffer[lastDropIndex].inputLiters = 0
428 end
429
430 if spec.isFilling ~= spec.sentIsFilling or spec.chopperPSenabled ~= spec.sentChopperPSenabled or spec.strawPSenabled ~= spec.sentStrawPSenabled then
431 self:raiseDirtyFlags(spec.dirtyFlag)
432 spec.sentIsFilling = spec.isFilling
433 spec.sentChopperPSenabled = spec.chopperPSenabled
434 spec.sentStrawPSenabled = spec.strawPSenabled
435 end
436 end
437end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
252function Combine:onWriteStream(streamId, connection)
253 local spec = self.spec_combine
254
255 streamWriteUIntN(streamId, spec.lastValidInputFruitType, FruitTypeManager.SEND_NUM_BITS)
256 streamWriteBool(streamId, spec.isFilling)
257 streamWriteBool(streamId, spec.chopperPSenabled)
258 streamWriteBool(streamId, spec.strawPSenabled)
259 streamWriteBool(streamId, spec.isSwathActive)
260
261 streamWriteFloat32(streamId, spec.workedHectars)
262end

onWriteUpdateStream

Description
Called on on update
Definition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
293function Combine:onWriteUpdateStream(streamId, connection, dirtyMask)
294 if not connection:getIsServer() then
295 local spec = self.spec_combine
296
297 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
298 streamWriteUIntN(streamId, spec.lastValidInputFruitType, FruitTypeManager.SEND_NUM_BITS)
299 streamWriteBool(streamId, spec.isFilling)
300 streamWriteBool(streamId, spec.chopperPSenabled)
301 streamWriteBool(streamId, spec.strawPSenabled)
302
303 streamWriteFloat32(streamId, spec.workedHectars)
304 end
305 end
306end

prerequisitesPresent

Description
Definition
prerequisitesPresent()
Code
25function Combine.prerequisitesPresent(specializations)
26 return SpecializationUtil.hasSpecialization(WorkArea, specializations) and
27 SpecializationUtil.hasSpecialization(FillUnit, specializations) and
28 (SpecializationUtil.hasSpecialization(Drivable, specializations) or SpecializationUtil.hasSpecialization(Attachable, specializations)) and
29 SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations) and
30 SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations)
31end

processCombineChopperArea

Description
Definition
processCombineChopperArea()
Code
607function Combine:processCombineChopperArea(workArea)
608 local spec = self.spec_combine
609
610 if not spec.isSwathActive then
611 local litersToDrop = spec.workAreaParameters.litersToDrop
612 local strawRatio = spec.workAreaParameters.strawRatio
613 spec.workAreaParameters.droppedLiters = litersToDrop
614
615 if litersToDrop > 0 and strawRatio > 0 then
616 local xs,_,zs = getWorldTranslation(workArea.start)
617 local xw,_,zw = getWorldTranslation(workArea.width)
618 local xh,_,zh = getWorldTranslation(workArea.height)
619
620 FSDensityMapUtil.setGroundTypeLayerArea(xs, zs, xw, zw, xh, zh, g_currentMission.chopperGroundLayerType)
621
622 -- raise active until litersToDrop is 0
623 self:raiseActive()
624 spec.workAreaParameters.isChopperEffectEnabled = 500
625 end
626 end
627
628 return spec.workAreaParameters.lastRealArea, spec.workAreaParameters.lastArea
629end

processCombineSwathArea

Description
Definition
processCombineSwathArea()
Code
633function Combine:processCombineSwathArea(workArea)
634 local spec = self.spec_combine
635 local litersToDrop = spec.workAreaParameters.litersToDrop
636
637 if spec.isSwathActive then
638 if litersToDrop > 0 then
639 local droppedLiters = 0
640 local fruitDesc = g_fruitTypeManager:getFruitTypeByFillTypeIndex(spec.workAreaParameters.dropFillType)
641 if fruitDesc ~= nil and fruitDesc.windrowLiterPerSqm ~= nil then
642 local windrowFillType = g_fruitTypeManager:getWindrowFillTypeIndexByFruitTypeIndex(fruitDesc.index)
643 if windrowFillType ~= nil then
644 local sx,sy,sz,ex,ey,ez = DensityMapHeightUtil.getLineByArea(workArea.start, workArea.width, workArea.height)
645 local dropped, lineOffset = DensityMapHeightUtil.tipToGroundAroundLine(self, litersToDrop, windrowFillType, sx, sy, sz, ex, ey, ez, 0, nil, workArea.lineOffset, false, nil, false)
646 droppedLiters = dropped
647 workArea.lineOffset = lineOffset
648 end
649 end
650 if droppedLiters > 0 then
651 spec.workAreaParameters.isStrawEffectEnabled = 500
652 end
653 spec.workAreaParameters.droppedLiters = droppedLiters
654 end
655 end
656
657 return spec.workAreaParameters.lastRealArea, spec.workAreaParameters.lastArea
658end

registerEventListeners

Description
Definition
registerEventListeners()
Code
77function Combine.registerEventListeners(vehicleType)
78 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Combine)
79 SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", Combine)
80 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Combine)
81 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Combine)
82 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Combine)
83 SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Combine)
84 SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Combine)
85 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Combine)
86 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Combine)
87 SpecializationUtil.registerEventListener(vehicleType, "onDraw", Combine)
88 SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", Combine)
89 SpecializationUtil.registerEventListener(vehicleType, "onStartWorkAreaProcessing", Combine)
90 SpecializationUtil.registerEventListener(vehicleType, "onEndWorkAreaProcessing", Combine)
91 SpecializationUtil.registerEventListener(vehicleType, "onChangedFillType", Combine)
92 SpecializationUtil.registerEventListener(vehicleType, "onDeactivate", Combine)
93 SpecializationUtil.registerEventListener(vehicleType, "onPostAttachImplement", Combine)
94 SpecializationUtil.registerEventListener(vehicleType, "onPostDetachImplement", Combine)
95 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", Combine)
96 SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", Combine)
97 SpecializationUtil.registerEventListener(vehicleType, "onEnterVehicle", Combine)
98 SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", Combine)
99 SpecializationUtil.registerEventListener(vehicleType, "onFoldStateChanged", Combine)
100 SpecializationUtil.registerEventListener(vehicleType, "onFillUnitFillLevelChanged", Combine)
101end

registerEvents

Description
Definition
registerEvents()
Code
35function Combine.registerEvents(vehicleType)
36 SpecializationUtil.registerEvent(vehicleType, "onStartThreshing")
37 SpecializationUtil.registerEvent(vehicleType, "onStopThreshing")
38end

registerFunctions

Description
Definition
registerFunctions()
Code
42function Combine.registerFunctions(vehicleType)
43 SpecializationUtil.registerFunction(vehicleType, "loadCombineSetup", Combine.loadCombineSetup)
44 SpecializationUtil.registerFunction(vehicleType, "loadCombineEffects", Combine.loadCombineEffects)
45 SpecializationUtil.registerFunction(vehicleType, "loadCombineRotationNodes", Combine.loadCombineRotationNodes)
46 SpecializationUtil.registerFunction(vehicleType, "loadCombineSamples", Combine.loadCombineSamples)
47 SpecializationUtil.registerFunction(vehicleType, "setIsSwathActive", Combine.setIsSwathActive)
48 SpecializationUtil.registerFunction(vehicleType, "processCombineChopperArea", Combine.processCombineChopperArea)
49 SpecializationUtil.registerFunction(vehicleType, "processCombineSwathArea", Combine.processCombineSwathArea)
50 SpecializationUtil.registerFunction(vehicleType, "setChopperPSEnabled", Combine.setChopperPSEnabled)
51 SpecializationUtil.registerFunction(vehicleType, "setStrawPSEnabled", Combine.setStrawPSEnabled)
52 SpecializationUtil.registerFunction(vehicleType, "setCombineIsFilling", Combine.setCombineIsFilling)
53 SpecializationUtil.registerFunction(vehicleType, "startThreshing", Combine.startThreshing)
54 SpecializationUtil.registerFunction(vehicleType, "stopThreshing", Combine.stopThreshing)
55 SpecializationUtil.registerFunction(vehicleType, "setWorkedHectars", Combine.setWorkedHectars)
56 SpecializationUtil.registerFunction(vehicleType, "addCutterToCombine", Combine.addCutterToCombine)
57 SpecializationUtil.registerFunction(vehicleType, "removeCutterFromCombine", Combine.removeCutterFromCombine)
58 SpecializationUtil.registerFunction(vehicleType, "addCutterArea", Combine.addCutterArea)
59 SpecializationUtil.registerFunction(vehicleType, "getIsThreshingAllowed", Combine.getIsThreshingAllowed)
60 SpecializationUtil.registerFunction(vehicleType, "verifyCombine", Combine.verifyCombine)
61 SpecializationUtil.registerFunction(vehicleType, "getIsBufferCombine", Combine.getIsBufferCombine)
62 SpecializationUtil.registerFunction(vehicleType, "getFillLevelDependentSpeed", Combine.getFillLevelDependentSpeed)
63end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
67function Combine.registerOverwrittenFunctions(vehicleType)
68 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeTurnedOn", Combine.getCanBeTurnedOn)
69 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getTurnedOnNotAllowedWarning", Combine.getTurnedOnNotAllowedWarning)
70 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsFoldAllowed", Combine.getIsFoldAllowed)
71 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeSelected", Combine.getCanBeSelected)
72 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadWorkAreaFromXML", Combine.loadWorkAreaFromXML)
73end

removeCutterFromCombine

Description
Definition
removeCutterFromCombine()
Code
842function Combine:removeCutterFromCombine(cutter)
843 local spec = self.spec_combine
844
845 if spec.attachedCutters[cutter] ~= nil then
846 spec.numAttachedCutters = spec.numAttachedCutters - 1
847 if spec.numAttachedCutters == 0 then
848 self:setIsTurnedOn(false, true)
849 -- if its a buffered combine -> clear the "invisible" tank on cutter detach
850 if self:getIsBufferCombine() then
851 local currentFillType = self:getFillUnitFillType(spec.fillUnitIndex)
852 if currentFillType ~= FillType.UNKNOWN then
853 if self:getIsBufferCombine() then
854 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -math.huge, currentFillType, ToolType.UNDEFINED, nil)
855 end
856 end
857 end
858 end
859 spec.attachedCutters[cutter] = nil
860 end
861end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
216function Combine:saveToXMLFile(xmlFile, key, usedModNames)
217 local spec = self.spec_combine
218
219 if spec.swath.isAvailable then
220 setXMLBool(xmlFile, key.."#isSwathActive", spec.isSwathActive)
221 setXMLFloat(xmlFile, key.."#workedHectars", spec.workedHectars)
222 end
223end

setChopperPSEnabled

Description
Set chopper PS enabled
Definition
setChopperPSEnabled(boolean chopperPSenabled, boolean fruitTypeChanged, boolean isSynchronized)
Arguments
booleanchopperPSenabledset enabled
booleanfruitTypeChangedfruit type has changed
booleanisSynchronizedfilling is synchronized
Code
665function Combine:setChopperPSEnabled(chopperPSenabled, fruitTypeChanged, isSynchronized)
666 local spec = self.spec_combine
667
668 if spec.chopperPSenabled ~= chopperPSenabled or fruitTypeChanged then
669 if spec.chopperEffects ~= nil and (not chopperPSenabled or fruitTypeChanged) then
670 g_effectManager:stopEffects(spec.chopperEffects)
671 end
672
673 spec.chopperPSenabled = chopperPSenabled
674 if self.isServer and isSynchronized then
675 spec.sentChopperPSenabled = chopperPSenabled
676 end
677 if chopperPSenabled and self.isClient then
678 if spec.chopperEffects ~= nil then
679 g_effectManager:setFillType(spec.chopperEffects, self:getFillUnitLastValidFillType(spec.fillUnitIndex))
680 g_effectManager:startEffects(spec.chopperEffects)
681 end
682 end
683 end
684end

setCombineIsFilling

Description
Set combine is filling
Definition
setCombineIsFilling(boolean isFilling, boolean fruitTypeChanged, boolean isSynchronized)
Arguments
booleanisFillingcombine is filling
booleanfruitTypeChangedfruit type has changed
booleanisSynchronizedfilling is synchronized
Code
720function Combine:setCombineIsFilling(isFilling, fruitTypeChanged, isSynchronized)
721 local spec = self.spec_combine
722
723 if spec.isFilling ~= isFilling or fruitTypeChanged then
724 spec.isFilling = isFilling
725
726 if isFilling then
727 g_animationManager:startAnimations(spec.fillingAnimationNodes)
728 else
729 g_animationManager:stopAnimations(spec.fillingAnimationNodes)
730 end
731
732 g_animationManager:setFillType(spec.fillingAnimationNodes, self:getFillUnitLastValidFillType(spec.fillUnitIndex))
733
734 if self.isServer and isSynchronized then
735 spec.sentIsFilling = isFilling
736 end
737
738 if spec.fillEffects ~= nil and (not isFilling or fruitTypeChanged) then
739 g_effectManager:stopEffects(spec.fillEffects)
740 end
741
742 if isFilling then
743 if spec.fillEffects ~= nil then
744 g_effectManager:setFillType(spec.fillEffects, self:getFillUnitLastValidFillType(spec.fillUnitIndex))
745 g_effectManager:startEffects(spec.fillEffects)
746 end
747 end
748 end
749end

setIsSwathActive

Description
Set is straw enabled
Definition
setIsSwathActive(boolean isSwathActive, boolean noEventSend, boolean force)
Arguments
booleanisSwathActivenew state
booleannoEventSendno event send
booleanforceforce action
Code
581function Combine:setIsSwathActive(isSwathActive, noEventSend, force)
582 local spec = self.spec_combine
583
584 if isSwathActive ~= spec.isSwathActive or force then
585 CombineStrawEnableEvent.sendEvent(self, isSwathActive, noEventSend)
586 spec.isSwathActive = isSwathActive
587
588 local anim = spec.chopper.animName
589 if self.playAnimation ~= nil and anim ~= nil then
590 local dir = 1
591 if isSwathActive then
592 dir = -1
593 end
594 self:playAnimation(anim, dir, self:getAnimationTime(anim), true)
595
596 if force then
597 AnimatedVehicle.updateAnimationByName(self, anim, 9999999)
598 end
599 end
600
601 Combine.updateToggleStrawText(self)
602 end
603end

setStrawPSEnabled

Description
Set straw PS enabled
Definition
setStrawPSEnabled(boolean strawPSenabled, boolean fruitTypeChanged, boolean isSynchronized)
Arguments
booleanstrawPSenabledset enabled
booleanfruitTypeChangedfruit type has changed
booleanisSynchronizedfilling is synchronized
Code
691function Combine:setStrawPSEnabled(strawPSenabled, fruitTypeChanged, isSynchronized)
692 local spec = self.spec_combine
693
694 if spec.strawPSenabled ~= strawPSenabled or fruitTypeChanged then
695 if spec.strawEffects ~= nil and (not strawPSenabled or fruitTypeChanged) then
696 g_effectManager:stopEffects(spec.strawEffects)
697 end
698
699 spec.strawPSenabled = strawPSenabled
700 if self.isServer and isSynchronized then
701 spec.sentStrawPSenabled = strawPSenabled
702 end
703 if not strawPSenabled then
704 spec.strawToDrop = 0
705 end
706 if strawPSenabled and self.isClient then
707 if spec.strawEffects ~= nil then
708 g_effectManager:setFillType(spec.strawEffects, self:getFillUnitLastValidFillType(spec.fillUnitIndex))
709 g_effectManager:startEffects(spec.strawEffects)
710 end
711 end
712 end
713end

setWorkedHectars

Description
Set worked hectars value and updated hud
Definition
setWorkedHectars(float hectars)
Arguments
floathectarsnew hectars value
Code
816function Combine:setWorkedHectars(hectars)
817 local spec = self.spec_combine
818
819 spec.workedHectars = hectars
820
821 if self.isServer then
822 if math.abs(spec.workedHectars-spec.workedHectarsSent) > 0.01 then
823 self:raiseDirtyFlags(spec.dirtyFlag)
824 spec.workedHectarsSent = spec.workedHectars
825 end
826 end
827end

startThreshing

Description
Start threshing
Definition
startThreshing()
Code
753function Combine:startThreshing()
754 local spec = self.spec_combine
755
756 if spec.numAttachedCutters > 0 then
757 -- do not lower the cutter if the combine is turned on during headland (happens if ai was blocked during headland)
758 local allowLowering = not self:getIsAIActive() or not self:getRootVehicle():getAIIsTurning()
759
760 for _,cutter in pairs(spec.attachedCutters) do
761 if allowLowering then
762 if cutter ~= self then
763 local jointDescIndex = self:getAttacherJointIndexFromObject(cutter)
764 self:setJointMoveDown(jointDescIndex, true, true)
765 end
766 end
767
768 cutter:setIsTurnedOn(true, true)
769 end
770
771 if spec.threshingStartAnimation ~= nil and self.playAnimation ~= nil then
772 self:playAnimation(spec.threshingStartAnimation, spec.threshingStartAnimationSpeedScale, self:getAnimationTime(spec.threshingStartAnimation), true)
773 end
774
775 if self.isClient then
776 g_soundManager:stopSamples(spec.samples)
777 g_soundManager:playSample(spec.samples.start)
778 g_soundManager:playSample(spec.samples.work, 0, spec.samples.start)
779 end
780
781 SpecializationUtil.raiseEvent(self, "onStartThreshing")
782 end
783end

stopThreshing

Description
Stop threshing
Definition
stopThreshing()
Code
787function Combine:stopThreshing()
788 local spec = self.spec_combine
789
790 if self.isClient then
791 g_soundManager:stopSamples(spec.samples)
792 g_soundManager:playSample(spec.samples.stop)
793 end
794
795 self:setCombineIsFilling(false, false, true)
796
797 for cutter,_ in pairs(spec.attachedCutters) do
798 if cutter ~= self then
799 local jointDescIndex = self:getAttacherJointIndexFromObject(cutter)
800 self:setJointMoveDown(jointDescIndex, false, true)
801 end
802
803 cutter:setIsTurnedOn(false, true)
804 end
805
806 if spec.threshingStartAnimation ~= nil and spec.playAnimation ~= nil then
807 self:playAnimation(spec.threshingStartAnimation, -spec.threshingStartAnimationSpeedScale, self:getAnimationTime(spec.threshingStartAnimation), true)
808 end
809
810 SpecializationUtil.raiseEvent(self, "onStopThreshing")
811end

updateToggleStrawText

Description
Definition
updateToggleStrawText()
Code
1334function Combine.updateToggleStrawText(self)
1335 local spec = self.spec_combine
1336 local actionEvent = spec.actionEvents[InputAction.TOGGLE_CHOPPER]
1337 if actionEvent ~= nil and actionEvent.actionEventId ~= nil then
1338 local text
1339 if spec.isSwathActive then
1340 text = g_i18n:getText("action_disableStrawSwath")
1341 else
1342 text = g_i18n:getText("action_enableStrawSwath")
1343 end
1344
1345 g_inputBinding:setActionEventText(actionEvent.actionEventId, text)
1346 end
1347end

verifyCombine

Description
Definition
verifyCombine()
Code
962function Combine:verifyCombine(fruitType, outputFillType)
963 local spec = self.spec_combine
964
965 if self:getFillUnitFillLevel(spec.fillUnitIndex) > self:getFillTypeChangeThreshold() * self:getFillUnitCapacity(spec.fillUnitIndex) then
966 local currentFillType = self:getFillUnitFillType(spec.fillUnitIndex)
967 if currentFillType ~= FillType.UNKNOWN and fruitType ~= FruitType.UNKNOWN and currentFillType ~= outputFillType then
968 -- if we are a combine harvester without a "real" fill unit we empty the buffer if a new fill type comes from the cutter
969 if self:getIsBufferCombine() then
970 self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -math.huge, currentFillType, ToolType.UNDEFINED, nil)
971 return self
972 end
973
974 return nil
975 end
976 end
977
978 if not self:getIsThreshingAllowed() then
979 return nil
980 end
981
982 if self:getFillUnitFreeCapacity(spec.fillUnitIndex) == 0 then
983 return nil
984 end
985
986 return self
987end