Script v1_7_1_0
- AI
- Animals
- Collections
- Contracts
- Debug
- Economy
- Elements
- EnvironmentalScore
- Errors
- Events
- GUI
- Handtools
- Hud
- I3d
- Input
- Jobs
- Maps
- Materials
- Misc
- Objects
- Parameters
- Placeables
- Placement
- Player
- Shop
- Sounds
- Specialization
- Specializations
- AIConveyorBelt
- AIDrivable
- AIFieldWorker
- AIImplement
- AIJobVehicle
- AIVehicle
- AIVehicleObstacle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- AutoLoader
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BigBag
- BunkerSiloCompacter
- BunkerSiloInteractor
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- CropSensor
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- ExtendedAIVehicle
- ExtendedCombine
- ExtendedMotorized
- ExtendedMower
- ExtendedSowingMachine
- ExtendedSprayer
- ExtendedWearable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- HeadlandAnimation
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- InlineWrapper
- JigglingParts
- Leveler
- LicensePlates
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- ManureSensor
- MixerWagon
- Motorized
- Mountable
- Mower
- Mulcher
- MultipleItemPurchase
- Pallet
- Pickup
- Pipe
- PlaceableAI
- PlaceableAnimatedObjects
- PlaceableBeehive
- PlaceableBeehivePalletSpa...
- PlaceableBunkerSilo
- PlaceableBuyingStation
- PlaceableCartridgePlayer
- PlaceableChargingStation
- PlaceableClearAreas
- PlaceableColorable
- PlaceableDeletedNodes
- PlaceableDoghouse
- PlaceableDynamicallyLoade...
- PlaceableFarmhouse
- PlaceableFence
- PlaceableFoliageAreas
- PlaceableGreenhouse
- PlaceableHighPressureWash...
- PlaceableHotspots
- PlaceableHusbandry
- PlaceableHusbandryAnimals
- PlaceableHusbandryFeeding...
- PlaceableHusbandryFence
- PlaceableHusbandryFood
- PlaceableHusbandryLiquidM...
- PlaceableHusbandryMilk
- PlaceableHusbandryPallets
- PlaceableHusbandryStraw
- PlaceableHusbandryWater
- PlaceableIncomePerHour
- PlaceableIndoorAreas
- PlaceableInfoTrigger
- PlaceableLeveling
- PlaceableLights
- PlaceableManureHeap
- PlaceablePlacement
- PlaceableProductionPoint
- PlaceableSellingStation
- PlaceableSilo
- PlaceableSiloExtension
- PlaceableSolarPanels
- PlaceableTipOcclusionArea...
- PlaceableTrainSystem
- PlaceableTriggerMarkers
- PlaceableVine
- PlaceableWardrobe
- PlaceableWeatherStation
- PlaceableWeighingStation
- PlaceableWindTurbine
- PlaceableWorkshop
- Plow
- PlowPacker
- PowerConsumer
- PowerTakeOffs
- PrecisionFarmingStatistic
- PushHandTool
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- RTKStation
- SaltSpreader
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SoilSampler
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StonePicker
- StrawBlower
- StumpCutter
- SupportVehicle
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TestAreas
- TipOccluder
- Trailer
- TreePlanter
- TreeSaplingPallet
- TreeSaw
- TurnOnVehicle
- VariableWorkWidth
- VehicleSettings
- VineCutter
- VineDetector
- VinePrepruner
- Washable
- WaterTrailer
- Wearable
- Weeder
- WeedSpotSpray
- Wheels
- WindBending
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- StateMachine
- Statistics
- Tasks
- Triggers
- Utils
- Vehicles
Engine v1_7_1_0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- general
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- NoteNode
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- VoiceChat
- XML
Foundation Reference
Combine
DescriptionSpecialization for combines providing threshing, effects, chopper and swath functionalityFunctions
- actionEventToggleChopper
- addCutterArea
- addCutterToCombine
- getAreControlledActionsAllowed
- getCanBeSelected
- getCanBeTurnedOn
- getCombineLastValidFillType
- getCombineLoadPercentage
- getDirtMultiplier
- getFillLevelDependentSpeed
- getIsCutterCompatible
- getIsFoldAllowed
- getIsThreshingDuringRain
- getIsTurnedOnAnimationActive
- getTurnedOnNotAllowedWarning
- getWearMultiplier
- initSpecialization
- loadCombineEffects
- loadCombineRotationNodes
- loadCombineSamples
- loadCombineSetup
- loadTurnedOnAnimationFromXML
- loadWorkAreaFromXML
- onChangedFillType
- onDeactivate
- onDelete
- onDraw
- onEndWorkAreaProcessing
- onEnterVehicle
- onFillUnitFillLevelChanged
- onFoldStateChanged
- onLeaveVehicle
- onLoad
- onPostAttachImplement
- onPostDetachImplement
- onPostLoad
- onReadStream
- onReadUpdateStream
- onRegisterActionEvents
- onStartWorkAreaProcessing
- onTurnedOff
- onTurnedOn
- onUpdate
- onUpdateTick
- onWriteStream
- onWriteUpdateStream
- prerequisitesPresent
- processCombineChopperArea
- processCombineSwathArea
- registerEventListeners
- registerEvents
- registerFunctions
- registerOverwrittenFunctions
- removeCutterFromCombine
- saveToXMLFile
- setChopperPSEnabled
- setCombineIsFilling
- setIsSwathActive
- setStrawPSEnabled
- setWorkedHectars
- startThreshing
- stopThreshing
- updateToggleStrawText
- verifyCombine
actionEventToggleChopper
DescriptionDefinitionactionEventToggleChopper()Code
1950 | function Combine.actionEventToggleChopper(self, actionName, inputValue, callbackState, isAnalog) |
1951 | local spec = self.spec_combine |
1952 | |
1953 | if spec.swath.isAvailable then |
1954 | local fillUnitIndex = spec.bufferFillUnitIndex or spec.fillUnitIndex |
1955 | local fruitType = g_fruitTypeManager:getFruitTypeIndexByFillTypeIndex(self:getFillUnitFillType(fillUnitIndex)) |
1956 | if fruitType ~= nil and fruitType ~= FruitType.UNKNOWN then |
1957 | local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitType) |
1958 | if fruitDesc.hasWindrow then |
1959 | self:setIsSwathActive(not spec.isSwathActive) |
1960 | else |
1961 | g_currentMission:showBlinkingWarning(g_i18n:getText("warning_couldNotToggleChopper"), 2000) |
1962 | end |
1963 | else |
1964 | self:setIsSwathActive(not spec.isSwathActive) |
1965 | end |
1966 | end |
1967 | end |
addCutterArea
DescriptionDefinitionaddCutterArea()Code
1264 | function Combine:addCutterArea(area, realArea, inputFruitType, outputFillType, strawRatio, strawGroundType, farmId, cutterLoad) |
1265 | local spec = self.spec_combine |
1266 | |
1267 | if area > 0 and (spec.lastCuttersFruitType == FruitType.UNKNOWN or spec.lastCuttersArea == 0 or spec.lastCuttersOutputFillType == outputFillType) then |
1268 | spec.lastCuttersArea = spec.lastCuttersArea + area |
1269 | spec.lastCuttersOutputFillType = outputFillType |
1270 | spec.lastCuttersInputFruitType = inputFruitType |
1271 | spec.lastCuttersAreaTime = g_currentMission.time |
1272 | |
1273 | if not spec.swath.isAvailable then |
1274 | local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(inputFruitType) |
1275 | spec.isSwathActive = not fruitDesc.hasWindrow |
1276 | end |
1277 | |
1278 | local litersPerSqm = 60 |
1279 | local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(inputFruitType) |
1280 | if fruitDesc.windrowLiterPerSqm ~= nil then |
1281 | litersPerSqm = fruitDesc.windrowLiterPerSqm |
1282 | end |
1283 | |
1284 | if self:getIsThreshingDuringRain() and self.propertyState ~= Vehicle.PROPERTY_STATE_MISSION then |
1285 | realArea = realArea * (1-Combine.RAIN_YIELD_REDUCTION) |
1286 | end |
1287 | |
1288 | -- only add straw to buffer if the fill type that is loaded is picked up |
1289 | if self:getFillUnitLastValidFillType(spec.fillUnitIndex) == outputFillType or self:getFillUnitLastValidFillType(spec.bufferFillUnitIndex) == outputFillType then |
1290 | local liters = (realArea * g_currentMission:getFruitPixelsToSqm() * litersPerSqm) * strawRatio |
1291 | if liters > 0 then |
1292 | local inputBuffer = spec.processing.inputBuffer |
1293 | local slot = inputBuffer.buffer[inputBuffer.fillIndex] |
1294 | slot.area = slot.area + area |
1295 | slot.realArea = slot.realArea + realArea |
1296 | slot.liters = slot.liters + liters |
1297 | slot.inputLiters = slot.inputLiters + liters |
1298 | slot.strawRatio = strawRatio |
1299 | slot.strawGroundType = strawGroundType |
1300 | slot.effectDensity = cutterLoad * strawRatio * 0.8 + 0.2 |
1301 | end |
1302 | end |
1303 | |
1304 | if spec.fillEnableTime == nil then |
1305 | spec.fillEnableTime = g_currentMission.time + spec.processing.toggleTime |
1306 | end |
1307 | |
1308 | -- 8000/1200 = 6.66 liter/meter |
1309 | -- 8000/1200 / 6 = 1.111 liter/m^2 |
1310 | -- 8000/1200 / 6 / 2^2 = 0.277777 liter / density pixel (density is 4096^2, on a area of 2048m^2 |
1311 | local pixelToSqm = g_currentMission:getFruitPixelsToSqm() -- 4096px are mapped to 2048m |
1312 | local literPerSqm = 1 |
1313 | if (inputFruitType ~= FruitType.UNKNOWN) then |
1314 | fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(inputFruitType) |
1315 | literPerSqm = fruitDesc.literPerSqm |
1316 | end |
1317 | local sqm = realArea*pixelToSqm |
1318 | local deltaFillLevel = sqm*literPerSqm*spec.threshingScale |
1319 | local fillType = outputFillType |
1320 | |
1321 | if spec.additives.available then |
1322 | local fillTypeSupported = false |
1323 | for i=1, #spec.additives.fillTypes do |
1324 | if fillType == spec.additives.fillTypes[i] then |
1325 | fillTypeSupported = true |
1326 | break |
1327 | end |
1328 | end |
1329 | |
1330 | if fillTypeSupported then |
1331 | local additivesFillLevel = self:getFillUnitFillLevel(spec.additives.fillUnitIndex) |
1332 | if additivesFillLevel > 0 then |
1333 | local usage = spec.additives.usage * deltaFillLevel |
1334 | if usage > 0 then |
1335 | local availableUsage = math.min(additivesFillLevel / usage, 1) |
1336 | |
1337 | deltaFillLevel = deltaFillLevel * (1 + 0.05 * availableUsage) |
1338 | |
1339 | self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.additives.fillUnitIndex, -usage, self:getFillUnitFillType(spec.additives.fillUnitIndex), ToolType.UNDEFINED) |
1340 | end |
1341 | end |
1342 | end |
1343 | end |
1344 | |
1345 | self:setWorkedHectars(spec.workedHectars + MathUtil.areaToHa(realArea, g_currentMission:getFruitPixelsToSqm())) |
1346 | |
1347 | if farmId ~= AccessHandler.EVERYONE then |
1348 | local damage = self:getVehicleDamage() |
1349 | if damage > 0 then |
1350 | deltaFillLevel = deltaFillLevel * (1 - damage * Combine.DAMAGED_YIELD_REDUCTION) |
1351 | end |
1352 | end |
1353 | |
1354 | -- buffer only the set time in the xml, after that we do not add more to the fill unit |
1355 | if self:getFillUnitCapacity(spec.fillUnitIndex) == math.huge and self:getFillUnitFillLevel(spec.fillUnitIndex) > 0.001 then |
1356 | if spec.lastDischargeTime + spec.fillLevelBufferTime < g_time then |
1357 | return deltaFillLevel |
1358 | end |
1359 | end |
1360 | |
1361 | local fillUnitIndex = spec.fillUnitIndex |
1362 | if spec.bufferFillUnitIndex ~= nil then |
1363 | if self:getFillUnitFreeCapacity(spec.bufferFillUnitIndex) > 0 then |
1364 | fillUnitIndex = spec.bufferFillUnitIndex |
1365 | end |
1366 | end |
1367 | |
1368 | if spec.loadingDelay > 0 then |
1369 | for i=1, #spec.loadingDelaySlots do |
1370 | if not spec.loadingDelaySlots[i].valid then |
1371 | spec.loadingDelaySlots[i].valid = true |
1372 | spec.loadingDelaySlots[i].fillLevelDelta = deltaFillLevel |
1373 | spec.loadingDelaySlots[i].fillType = fillType |
1374 | |
1375 | if spec.loadingDelaySlotsDelayedInsert then |
1376 | spec.loadingDelaySlots[i].time = g_time |
1377 | else |
1378 | spec.loadingDelaySlots[i].time = g_time + (spec.unloadingDelay - spec.loadingDelay) |
1379 | end |
1380 | |
1381 | spec.loadingDelaySlotsDelayedInsert = not spec.loadingDelaySlotsDelayedInsert |
1382 | |
1383 | break |
1384 | end |
1385 | end |
1386 | |
1387 | return deltaFillLevel |
1388 | end |
1389 | |
1390 | local loadInfo = self:getFillVolumeLoadInfo(spec.loadInfoIndex) |
1391 | return self:addFillUnitFillLevel(self:getOwnerFarmId(), fillUnitIndex, deltaFillLevel, fillType, ToolType.UNDEFINED, loadInfo) |
1392 | end |
1393 | |
1394 | return 0 |
1395 | end |
addCutterToCombine
DescriptionDefinitionaddCutterToCombine()Code
1210 | function Combine:addCutterToCombine(cutter) |
1211 | local spec = self.spec_combine |
1212 | |
1213 | if spec.attachedCutters[cutter] == nil then |
1214 | spec.attachedCutters[cutter] = cutter |
1215 | spec.numAttachedCutters = spec.numAttachedCutters + 1 |
1216 | |
1217 | local ladder = self.spec_combine.ladder |
1218 | if ladder.unfoldWhileCutterAttached and ladder.animName ~= nil then |
1219 | if self:getAnimationTime(ladder.animName) < 1 then |
1220 | self:playAnimation(ladder.animName, ladder.animSpeedScale, self:getAnimationTime(ladder.animName), true) |
1221 | end |
1222 | end |
1223 | end |
1224 | end |
getAreControlledActionsAllowed
DescriptionReturns if controlled actions are allowedDefinition
getAreControlledActionsAllowed()Return Values
boolean | allow | allow controlled actions |
string | warning | not allowed warning |
1594 | function Combine:getAreControlledActionsAllowed(superFunc) |
1595 | local spec = self.spec_combine |
1596 | |
1597 | if spec.numAttachedCutters <= 0 then |
1598 | return false, spec.texts.warningNoCutter |
1599 | end |
1600 | |
1601 | return superFunc(self) |
1602 | end |
getCanBeSelected
DescriptionDefinitiongetCanBeSelected()Code
1624 | function Combine:getCanBeSelected(superFunc) |
1625 | return true |
1626 | end |
getCanBeTurnedOn
DescriptionReturns if turn on is allowedDefinition
getCanBeTurnedOn()Return Values
boolean | allow | allow turn on |
1545 | function Combine:getCanBeTurnedOn(superFunc) |
1546 | local spec = self.spec_combine |
1547 | |
1548 | if spec.numAttachedCutters <= 0 then |
1549 | return false |
1550 | end |
1551 | |
1552 | for cutter, _ in pairs(spec.attachedCutters) do |
1553 | if cutter ~= self then |
1554 | if cutter.getCanBeTurnedOn ~= nil and not cutter:getCanBeTurnedOn() then |
1555 | return false |
1556 | end |
1557 | end |
1558 | end |
1559 | |
1560 | return superFunc(self) |
1561 | end |
getCombineLastValidFillType
DescriptionReturns last valid fill type from fill unit or buffer unitDefinition
getCombineLastValidFillType()Return Values
integer | fillUnitIndex | fill unit index |
1490 | function Combine:getCombineLastValidFillType() |
1491 | local spec = self.spec_combine |
1492 | |
1493 | local fillType = FillType.UNKNOWN |
1494 | if spec.bufferFillUnitIndex ~= nil then |
1495 | fillType = self:getFillUnitLastValidFillType(spec.bufferFillUnitIndex) |
1496 | end |
1497 | |
1498 | if fillType == FillType.UNKNOWN then |
1499 | fillType = self:getFillUnitLastValidFillType(spec.fillUnitIndex) |
1500 | end |
1501 | |
1502 | if fillType == FillType.UNKNOWN then |
1503 | if spec.loadingDelay > 0 then |
1504 | for i=1, #spec.loadingDelaySlots do |
1505 | if spec.loadingDelaySlots[i].valid then |
1506 | fillType = spec.loadingDelaySlots[i].fillType |
1507 | break |
1508 | end |
1509 | end |
1510 | end |
1511 | end |
1512 | |
1513 | if fillType == FillType.UNKNOWN then |
1514 | fillType = spec.lastValidInputFillType |
1515 | end |
1516 | |
1517 | return fillType |
1518 | end |
getCombineLoadPercentage
DescriptionDefinitiongetCombineLoadPercentage()Code
1522 | function Combine:getCombineLoadPercentage() |
1523 | local spec = self.spec_combine |
1524 | if spec ~= nil then |
1525 | if spec.numAttachedCutters > 0 then |
1526 | local loadSum = 0 |
1527 | for cutter, _ in pairs(spec.attachedCutters) do |
1528 | if cutter.getCutterLoad ~= nil then |
1529 | loadSum = loadSum + cutter:getCutterLoad() |
1530 | end |
1531 | end |
1532 | |
1533 | return loadSum / spec.numAttachedCutters |
1534 | end |
1535 | end |
1536 | |
1537 | return 0 |
1538 | end |
getDirtMultiplier
DescriptionDefinitiongetDirtMultiplier()Code
1649 | function Combine:getDirtMultiplier(superFunc) |
1650 | local spec = self.spec_combine |
1651 | |
1652 | for cutter, _ in pairs(spec.attachedCutters) do |
1653 | if cutter.spec_cutter ~= nil then |
1654 | if cutter.spec_cutter.isWorking then |
1655 | return superFunc(self) + self:getWorkDirtMultiplier() * self:getLastSpeed() / cutter.speedLimit |
1656 | end |
1657 | end |
1658 | end |
1659 | |
1660 | return superFunc(self) |
1661 | end |
getFillLevelDependentSpeed
DescriptionDefinitiongetFillLevelDependentSpeed()Code
1453 | function Combine:getFillLevelDependentSpeed() |
1454 | local spec = self.spec_combine |
1455 | if spec.rotationNodesSpeedReverseFillLevel ~= nil then |
1456 | local fillLevelPct = self:getFillUnitFillLevel(spec.fillUnitIndex) / self:getFillUnitCapacity(spec.fillUnitIndex) |
1457 | if fillLevelPct > spec.rotationNodesSpeedReverseFillLevel then |
1458 | return -1 |
1459 | else |
1460 | return 1 |
1461 | end |
1462 | else |
1463 | return 1 |
1464 | end |
1465 | end |
getIsCutterCompatible
DescriptionReturns if given attributes are compatible with combineDefinition
getIsCutterCompatible(table fillTypes)Arguments
table | fillTypes | fill types |
boolean | isCompatible | is compatible with combine |
1471 | function Combine:getIsCutterCompatible(fillTypes) |
1472 | local spec = self.spec_combine |
1473 | local supportedTypes = self:getFillUnitSupportedFillTypes(spec.fillUnitIndex) |
1474 | |
1475 | for i=1, #fillTypes do |
1476 | local fillType = fillTypes[i] |
1477 | for supportedType, _ in pairs(supportedTypes) do |
1478 | if fillType == supportedType then |
1479 | return true |
1480 | end |
1481 | end |
1482 | end |
1483 | |
1484 | return false |
1485 | end |
getIsFoldAllowed
DescriptionReturns if fold is allowedDefinition
getIsFoldAllowed()Return Values
boolean | allowsFold | allows folding |
1607 | function Combine:getIsFoldAllowed(superFunc, direction, onAiTurnOn) |
1608 | local spec = self.spec_combine |
1609 | |
1610 | if not spec.allowFoldWhileThreshing and self:getIsTurnedOn() then |
1611 | return false, spec.texts.warningFoldingTurnedOn |
1612 | end |
1613 | |
1614 | local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex) |
1615 | if direction == spec.foldDirection and (fillLevel > spec.foldFillLevelThreshold and self:getFillUnitCapacity(spec.fillUnitIndex) ~= math.huge) then |
1616 | return false, spec.texts.warningFoldingWhileFilled |
1617 | end |
1618 | |
1619 | return superFunc(self, direction, onAiTurnOn) |
1620 | end |
getIsThreshingDuringRain
DescriptionReturns if combine is currently threshing during rainDefinition
getIsThreshingDuringRain(boolean earlyWarning)Arguments
boolean | earlyWarning | early warning |
boolean | isThreshingDuringRain | is threshing during rain |
1401 | function Combine:getIsThreshingDuringRain(earlyWarning) |
1402 | local spec = self.spec_combine |
1403 | |
1404 | if not spec.allowThreshingDuringRain then |
1405 | local rainScale = g_currentMission.environment.weather:getRainFallScale() |
1406 | local timeSinceLastRain = g_currentMission.environment.weather:getTimeSinceLastRain() |
1407 | if earlyWarning ~= nil and earlyWarning == true then |
1408 | if rainScale >= 0.02 and timeSinceLastRain < 20 then |
1409 | return true |
1410 | end |
1411 | else |
1412 | if rainScale >= 0.1 and timeSinceLastRain < 20 then |
1413 | return true |
1414 | end |
1415 | end |
1416 | end |
1417 | |
1418 | return false |
1419 | end |
getIsTurnedOnAnimationActive
DescriptionDefinitiongetIsTurnedOnAnimationActive()Code
1693 | function Combine:getIsTurnedOnAnimationActive(superFunc, turnedOnAnimation) |
1694 | local spec = self.spec_combine |
1695 | if (not turnedOnAnimation.activeChopper and not spec.isSwathActive) |
1696 | or (not turnedOnAnimation.activeStrawDrop and spec.isSwathActive) then |
1697 | return false |
1698 | end |
1699 | |
1700 | if turnedOnAnimation.waitForStraw then |
1701 | return superFunc(self, turnedOnAnimation) or spec.workAreaParameters.isChopperEffectEnabled > 0 |
1702 | end |
1703 | |
1704 | return superFunc(self, turnedOnAnimation) |
1705 | end |
getTurnedOnNotAllowedWarning
DescriptionReturns turn on not allowed warning textDefinition
getTurnedOnNotAllowedWarning()Return Values
string | warningText | turn on not allowed warning text |
1566 | function Combine:getTurnedOnNotAllowedWarning(superFunc) |
1567 | if self:getIsActiveForInput(true) then |
1568 | local spec = self.spec_combine |
1569 | if not self:getCanBeTurnedOn() then |
1570 | if spec.numAttachedCutters == 0 then |
1571 | return spec.texts.warningNoCutter |
1572 | else |
1573 | for cutter, _ in pairs(spec.attachedCutters) do |
1574 | if cutter ~= self then |
1575 | if cutter.getTurnedOnNotAllowedWarning ~= nil then |
1576 | local warning = cutter:getTurnedOnNotAllowedWarning() |
1577 | if warning ~= nil then |
1578 | return warning |
1579 | end |
1580 | end |
1581 | end |
1582 | end |
1583 | end |
1584 | end |
1585 | end |
1586 | |
1587 | return superFunc(self) |
1588 | end |
getWearMultiplier
DescriptionDefinitiongetWearMultiplier()Code
1665 | function Combine:getWearMultiplier(superFunc) |
1666 | local spec = self.spec_combine |
1667 | |
1668 | for cutter, _ in pairs(spec.attachedCutters) do |
1669 | if cutter.spec_cutter ~= nil then |
1670 | if cutter.spec_cutter.isWorking then |
1671 | local stoneMultiplier = cutter:getCutterStoneMultiplier() |
1672 | return superFunc(self) + self:getWorkWearMultiplier() * self:getLastSpeed() / cutter.speedLimit * stoneMultiplier |
1673 | end |
1674 | end |
1675 | end |
1676 | |
1677 | return superFunc(self) |
1678 | end |
initSpecialization
DescriptionDefinitioninitSpecialization()Code
19 | function Combine.initSpecialization() |
20 | g_workAreaTypeManager:addWorkAreaType("combineChopper", false) |
21 | g_workAreaTypeManager:addWorkAreaType("combineSwath", false) |
22 | |
23 | local schema = Vehicle.xmlSchema |
24 | schema:setXMLSpecializationType("Combine") |
25 | |
26 | schema:register(XMLValueType.L10N_STRING, "vehicle.combine.warning#noCutter", "No cutter warning", "$l10n_warning_noCuttersAttached") |
27 | schema:register(XMLValueType.FLOAT, "vehicle.combine#fillLevelBufferTime", "Fill level buffer time for forage harvesters", 2000) |
28 | |
29 | schema:register(XMLValueType.BOOL, "vehicle.combine#allowThreshingDuringRain", "Allow threshing during rain", false) |
30 | schema:register(XMLValueType.INT, "vehicle.combine#fillUnitIndex", "Fill unit index", 1) |
31 | schema:register(XMLValueType.INT, "vehicle.combine.buffer#fillUnitIndex", "Buffer fill unit index (This fill unit will be filled first until it's full. Will be emptied if stopped to harvest)") |
32 | schema:register(XMLValueType.TIME, "vehicle.combine.buffer#unloadingTime", "Buffer unloading speed", 0) |
33 | schema:register(XMLValueType.INT, "vehicle.combine#loadInfoIndex", "Load info index", 1) |
34 | |
35 | schema:register(XMLValueType.TIME, "vehicle.combine.buffer#loadingDelay", "Time until the crops from the cutter are added to the tank", 0) |
36 | schema:register(XMLValueType.TIME, "vehicle.combine.buffer#unloadingDelay", "Time until the crops are not longer added to the tank after the cutting has been stopped", "same as #loadingDelay") |
37 | |
38 | schema:register(XMLValueType.BOOL, "vehicle.combine.swath#available", "Swath is available", false) |
39 | schema:register(XMLValueType.BOOL, "vehicle.combine.swath#isDefaultActive", "Swath is default active", "true if available") |
40 | schema:register(XMLValueType.INT, "vehicle.combine.swath#workAreaIndex", "Swath work area index") |
41 | |
42 | schema:register(XMLValueType.BOOL, "vehicle.combine.chopper#available", "Chopper is available", false) |
43 | schema:register(XMLValueType.BOOL, "vehicle.combine.chopper#isPowered", "Vehicle needs to be powered to switch chopper", true) |
44 | schema:register(XMLValueType.INT, "vehicle.combine.chopper#workAreaIndex", "Chopper work area index") |
45 | schema:register(XMLValueType.STRING, "vehicle.combine.chopper#animName", "Chopper toggle animation name") |
46 | schema:register(XMLValueType.FLOAT, "vehicle.combine.chopper#animSpeedScale", "Chopper toggle animation speed", 1) |
47 | |
48 | schema:register(XMLValueType.STRING, "vehicle.combine.ladder#animName", "Ladder animation name") |
49 | schema:register(XMLValueType.FLOAT, "vehicle.combine.ladder#animSpeedScale", "Ladder animation speed scale", 1) |
50 | schema:register(XMLValueType.FLOAT, "vehicle.combine.ladder#foldMinLimit", "Min. folding time to fold ladder", 0.99) |
51 | schema:register(XMLValueType.FLOAT, "vehicle.combine.ladder#foldMaxLimit", "Max. folding time to fold ladder", 1) |
52 | schema:register(XMLValueType.INT, "vehicle.combine.ladder#foldDirection", "Fold direction to unfold ladder", "signed animation speed") |
53 | schema:register(XMLValueType.BOOL, "vehicle.combine.ladder#unfoldWhileCutterAttached", "Unfold ladder while a cutter is attached", false) |
54 | |
55 | schema:register(XMLValueType.TIME, "vehicle.combine#fillTimeThreshold", "After receiving no input for this threshold time we stop the fill effects", 0.5) |
56 | |
57 | schema:register(XMLValueType.FLOAT, "vehicle.combine.processing#toggleTime", "Time from crop cutting to dropping straw", 0) |
58 | |
59 | schema:register(XMLValueType.STRING, "vehicle.combine.threshingStartAnimation#name", "Threshing start animation") |
60 | schema:register(XMLValueType.FLOAT, "vehicle.combine.threshingStartAnimation#speedScale", "Threshing start animation speed scale") |
61 | schema:register(XMLValueType.BOOL, "vehicle.combine.threshingStartAnimation#initialIsStarted", "Threshing start animation is initial started") |
62 | |
63 | schema:register(XMLValueType.INT, "vehicle.combine.additives#fillUnitIndex", "Additives fill unit index") |
64 | schema:register(XMLValueType.FLOAT, "vehicle.combine.additives#usage", "Usage per picked up liter", 2) |
65 | schema:register(XMLValueType.STRING, "vehicle.combine.additives#fillTypes", "Fill types to apply additives", "CHAFF GRASS_WINDROW") |
66 | |
67 | schema:register(XMLValueType.NODE_INDEX, "vehicle.combine.automaticTilt.automaticTiltNode(?)#node", "Automatic tilt node") |
68 | schema:register(XMLValueType.ANGLE, "vehicle.combine.automaticTilt.automaticTiltNode(?)#minAngle", "Min. angle", -5) |
69 | schema:register(XMLValueType.ANGLE, "vehicle.combine.automaticTilt.automaticTiltNode(?)#maxAngle", "Max. angle", 5) |
70 | schema:register(XMLValueType.ANGLE, "vehicle.combine.automaticTilt.automaticTiltNode(?)#maxSpeed", "Max. angle change per second", 2) |
71 | schema:register(XMLValueType.BOOL, "vehicle.combine.automaticTilt.automaticTiltNode(?)#updateAttacherJoint", "Update cutter attacher joint") |
72 | schema:register(XMLValueType.STRING, "vehicle.combine.automaticTilt.automaticTiltNode(?)#dependentAnimation", "Animation that is updated depending on tilt state") |
73 | |
74 | schema:register(XMLValueType.FLOAT, "vehicle.combine.folding#fillLevelThresholdPct", "Max. fill level to be folded (percetange between 0 and 1)", 0.15) |
75 | schema:register(XMLValueType.INT, "vehicle.combine.folding#direction", "Folding direction", 1) |
76 | schema:register(XMLValueType.BOOL, "vehicle.combine.folding#allowWhileThreshing", "Allow folding while combine is threshing", false) |
77 | |
78 | EffectManager.registerEffectXMLPaths(schema, "vehicle.combine.chopperEffect") |
79 | EffectManager.registerEffectXMLPaths(schema, "vehicle.combine.strawEffect") |
80 | EffectManager.registerEffectXMLPaths(schema, "vehicle.combine.fillEffect") |
81 | EffectManager.registerEffectXMLPaths(schema, "vehicle.combine.effect") |
82 | |
83 | AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.combine.animationNodes") |
84 | AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.combine.chopperAnimationNodes") |
85 | AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.combine.strawDropAnimationNodes") |
86 | AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.combine.fillingAnimationNodes") |
87 | schema:register(XMLValueType.FLOAT, "vehicle.combine.animationNodes#speedReverseFillLevel", "If fill level is above the animation nodes will be reversed (Percent 0-1)") |
88 | |
89 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "start") |
90 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "stop") |
91 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "work") |
92 | |
93 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "chopperStart") |
94 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "chopperStop") |
95 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "chopperWork") |
96 | |
97 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "chopStraw") |
98 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "dropStraw") |
99 | |
100 | SoundManager.registerSampleXMLPaths(schema, "vehicle.combine.sounds", "fill") |
101 | |
102 | Dashboard.registerDashboardXMLPaths(schema, "vehicle.combine.dashboards", "workedHectars") |
103 | |
104 | schema:register(XMLValueType.BOOL, TurnOnVehicle.TURNED_ON_ANIMATION_XML_PATH .. "#activeChopper", "Animation is active while chopper is active", true) |
105 | schema:register(XMLValueType.BOOL, TurnOnVehicle.TURNED_ON_ANIMATION_XML_PATH .. "#activeStrawDrop", "Animation is active while straw drop is active", true) |
106 | schema:register(XMLValueType.BOOL, TurnOnVehicle.TURNED_ON_ANIMATION_XML_PATH .. "#waitForStraw", "Animation is active as long as straw is dropped", true) |
107 | |
108 | schema:setXMLSpecializationType() |
109 | |
110 | local schemaSavegame = Vehicle.xmlSchemaSavegame |
111 | schemaSavegame:register(XMLValueType.BOOL, "vehicles.vehicle(?).combine#isSwathActive", "Swath is active") |
112 | schemaSavegame:register(XMLValueType.FLOAT, "vehicles.vehicle(?).combine#workedHectars", "Worked hectars") |
113 | schemaSavegame:register(XMLValueType.INT, "vehicles.vehicle(?).combine#numAttachedCutters", "Number of last attached cutters") |
114 | end |
loadCombineEffects
DescriptionDefinitionloadCombineEffects()Code
828 | function Combine:loadCombineEffects(xmlFile, baseKey, entry) |
829 | if self.isClient then |
830 | XMLUtil.checkDeprecatedXMLElements(xmlFile, baseKey .. ".chopperParticleSystems", baseKey..".chopperEffect") --FS17 to FS19 |
831 | XMLUtil.checkDeprecatedXMLElements(xmlFile, baseKey .. ".strawParticleSystems", baseKey..".strawEffect") --FS17 to FS19 |
832 | XMLUtil.checkDeprecatedXMLElements(xmlFile, baseKey .. ".threshingFillParticleSystems", baseKey..".fillEffect") --FS17 to FS19 |
833 | |
834 | entry.chopperEffects = g_effectManager:loadEffect(xmlFile, baseKey .. ".chopperEffect", self.components, self, self.i3dMappings) |
835 | entry.strawEffects = g_effectManager:loadEffect(xmlFile, baseKey .. ".strawEffect", self.components, self, self.i3dMappings) |
836 | entry.fillEffects = g_effectManager:loadEffect(xmlFile, baseKey .. ".fillEffect", self.components, self, self.i3dMappings) |
837 | entry.effects = g_effectManager:loadEffect(xmlFile, baseKey .. ".effect", self.components, self, self.i3dMappings) |
838 | |
839 | entry.strawPSenabled = false |
840 | entry.chopperPSenabled = false |
841 | entry.isFilling = false |
842 | |
843 | entry.fillEnableTime = nil |
844 | entry.fillDisableTime = nil |
845 | |
846 | entry.lastEffectFillType = FillType.UNKNOWN |
847 | end |
848 | end |
loadCombineRotationNodes
DescriptionDefinitionloadCombineRotationNodes()Code
853 | function Combine:loadCombineRotationNodes(xmlFile, baseKey, entry) |
854 | if self.isClient then |
855 | entry.animationNodes = g_animationManager:loadAnimations(xmlFile, baseKey..".animationNodes", self.components, self, self.i3dMappings) |
856 | entry.chopperAnimationNodes = g_animationManager:loadAnimations(xmlFile, baseKey..".chopperAnimationNodes", self.components, self, self.i3dMappings) |
857 | entry.strawDropAnimationNodes = g_animationManager:loadAnimations(xmlFile, baseKey..".strawDropAnimationNodes", self.components, self, self.i3dMappings) |
858 | entry.fillingAnimationNodes = g_animationManager:loadAnimations(xmlFile, baseKey..".fillingAnimationNodes", self.components, self, self.i3dMappings) |
859 | entry.rotationNodesSpeedReverseFillLevel = xmlFile:getValue(baseKey .. ".animationNodes#speedReverseFillLevel") |
860 | end |
861 | end |
loadCombineSamples
DescriptionDefinitionloadCombineSamples()Code
866 | function Combine:loadCombineSamples(xmlFile, key, entry) |
867 | if self.isClient then |
868 | entry.samples = {} |
869 | entry.samples.start = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "start", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
870 | entry.samples.stop = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "stop", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
871 | entry.samples.work = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "work", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
872 | |
873 | entry.samples.chopperStart = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "chopperStart", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
874 | entry.samples.chopperStop = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "chopperStop", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
875 | entry.samples.chopperWork = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "chopperWork", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
876 | |
877 | entry.samples.chopStraw = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "chopStraw", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
878 | entry.samples.dropStraw = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "dropStraw", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
879 | |
880 | entry.samples.fill = g_soundManager:loadSampleFromXML(xmlFile, key .. ".sounds", "fill", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
881 | end |
882 | end |
loadCombineSetup
DescriptionDefinitionloadCombineSetup()Code
699 | function Combine:loadCombineSetup(xmlFile, baseKey, entry) |
700 | entry.allowThreshingDuringRain = xmlFile:getValue(baseKey .. "#allowThreshingDuringRain", false) |
701 | |
702 | entry.fillUnitIndex = xmlFile:getValue(baseKey .. "#fillUnitIndex", 1) |
703 | entry.bufferFillUnitIndex = xmlFile:getValue(baseKey .. ".buffer#fillUnitIndex") |
704 | entry.bufferUnloadingTime = xmlFile:getValue(baseKey .. ".buffer#unloadingTime", 0) |
705 | entry.loadInfoIndex = xmlFile:getValue(baseKey .. "#loadInfoIndex", 1) |
706 | |
707 | entry.loadingDelay = xmlFile:getValue(baseKey .. ".buffer#loadingDelay", 0) |
708 | if entry.loadingDelay > 0 then |
709 | entry.unloadingDelay = xmlFile:getValue(baseKey .. ".buffer#unloadingDelay", entry.loadingDelay / 1000) |
710 | entry.loadingDelaySlotsDelayedInsert = false |
711 | |
712 | entry.loadingDelaySlots = {} |
713 | for i=1, entry.loadingDelay / 1000 * 60 + 1 do -- max if we fill at 60FPS every frame |
714 | entry.loadingDelaySlots[i] = {time=-math.huge, fillLevelDelta=0, fillType=0, valid=false} |
715 | end |
716 | end |
717 | |
718 | -- swath |
719 | entry.swath = {} |
720 | entry.swath.isAvailable = xmlFile:getValue(baseKey .. ".swath#available", false) |
721 | local isDefaultActive = xmlFile:getValue(baseKey .. ".swath#isDefaultActive", entry.swath.isAvailable) |
722 | if entry.swath.isAvailable then |
723 | entry.swath.workAreaIndex = xmlFile:getValue(baseKey .. ".swath#workAreaIndex") |
724 | if entry.swath.workAreaIndex == nil then |
725 | entry.swath.isAvailable = false |
726 | Logging.xmlWarning(xmlFile, "Missing 'swath#workAreaIndex' for combine swath function!") |
727 | end |
728 | entry.warningTime = 0 |
729 | end |
730 | |
731 | -- chopper |
732 | entry.chopper = {} |
733 | entry.chopper.isAvailable = xmlFile:getValue(baseKey .. ".chopper#available", false) |
734 | entry.chopper.isPowered = xmlFile:getValue(baseKey .. ".chopper#isPowered", true) |
735 | if entry.chopper.isAvailable then |
736 | entry.chopper.workAreaIndex = xmlFile:getValue(baseKey .. ".chopper#workAreaIndex") |
737 | if entry.chopper.workAreaIndex == nil then |
738 | entry.chopper.isAvailable = false |
739 | Logging.xmlWarning(xmlFile, "Missing 'chopper#workAreaIndex' for combine chopper function!") |
740 | end |
741 | |
742 | entry.chopper.animName = xmlFile:getValue(baseKey .. ".chopper#animName") |
743 | entry.chopper.animSpeedScale = xmlFile:getValue(baseKey .. ".chopper#animSpeedScale", 1) |
744 | end |
745 | |
746 | entry.automatedChopperSwitch = GS_IS_MOBILE_VERSION |
747 | |
748 | entry.isSwathActive = isDefaultActive |
749 | |
750 | --ladder |
751 | entry.ladder = {} |
752 | entry.ladder.animName = xmlFile:getValue(baseKey .. ".ladder#animName") |
753 | entry.ladder.animSpeedScale = xmlFile:getValue(baseKey .. ".ladder#animSpeedScale", 1) |
754 | entry.ladder.foldMinLimit = xmlFile:getValue(baseKey .. ".ladder#foldMinLimit", 0.99) |
755 | entry.ladder.foldMaxLimit = xmlFile:getValue(baseKey .. ".ladder#foldMaxLimit", 1) |
756 | entry.ladder.foldDirection = xmlFile:getValue(baseKey .. ".ladder#foldDirection", MathUtil.sign(entry.ladder.animSpeedScale)) |
757 | entry.ladder.unfoldWhileCutterAttached = xmlFile:getValue(baseKey .. ".ladder#unfoldWhileCutterAttached", false) |
758 | |
759 | entry.fillTimeThreshold = xmlFile:getValue(baseKey .. "#fillTimeThreshold", 0.5) |
760 | |
761 | -- processing buffer |
762 | entry.processing = {} |
763 | local toggleTime = xmlFile:getValue(baseKey .. ".processing#toggleTime") |
764 | if toggleTime == nil and entry.chopper.animName ~= nil then |
765 | toggleTime = self:getAnimationDurection(entry.chopper.animName) |
766 | if toggleTime ~= nil then |
767 | toggleTime = toggleTime / 1000 |
768 | end |
769 | end |
770 | entry.processing.toggleTime = Utils.getNoNil(toggleTime, 0) * 1000 |
771 | |
772 | local inputBuffer = {} |
773 | local slotDuration = 300 |
774 | local slotCount = MathUtil.clamp(math.ceil(entry.processing.toggleTime / slotDuration), 2, 20) |
775 | inputBuffer.slotCount = slotCount |
776 | inputBuffer.slotDuration = math.ceil( entry.processing.toggleTime / inputBuffer.slotCount ) |
777 | inputBuffer.fillIndex = 1 |
778 | inputBuffer.dropIndex = inputBuffer.fillIndex + 1 |
779 | inputBuffer.slotTimer = inputBuffer.slotDuration |
780 | inputBuffer.activeTimeout = inputBuffer.slotDuration * (inputBuffer.slotCount + 2) |
781 | inputBuffer.activeTimer = inputBuffer.activeTimeout |
782 | inputBuffer.buffer = {} |
783 | for _=1, inputBuffer.slotCount do |
784 | table.insert(inputBuffer.buffer, {realArea = 0, area = 0, liters = 0, inputLiters = 0, strawRatio = 0, effectDensity = 0.2} ) |
785 | end |
786 | entry.processing.inputBuffer = inputBuffer |
787 | |
788 | -- threhsing start animation |
789 | entry.threshingStartAnimation = xmlFile:getValue(baseKey .. ".threshingStartAnimation#name") |
790 | entry.threshingStartAnimationSpeedScale = xmlFile:getValue(baseKey .. ".threshingStartAnimation#speedScale", 1) |
791 | entry.threshingStartAnimationInitialIsStarted = xmlFile:getValue(baseKey .. ".threshingStartAnimation#initialIsStarted", false) |
792 | |
793 | entry.foldFillLevelThreshold = xmlFile:getValue(baseKey .. ".folding#fillLevelThresholdPct", 0.15) * (self:getFillUnitCapacity(entry.fillUnitIndex) or 0.04) |
794 | entry.foldDirection = xmlFile:getValue(baseKey .. ".folding#direction", 1) |
795 | entry.allowFoldWhileThreshing = xmlFile:getValue(baseKey .. ".folding#allowWhileThreshing", false) |
796 | |
797 | entry.additives = {} |
798 | entry.additives.fillUnitIndex = xmlFile:getValue(baseKey .. ".additives#fillUnitIndex") |
799 | entry.additives.available = self:getFillUnitByIndex(entry.additives.fillUnitIndex) ~= nil |
800 | entry.additives.usage = xmlFile:getValue(baseKey .. ".additives#usage", 0.0) |
801 | local additivesFillTypeNames = xmlFile:getValue(baseKey .. ".additives#fillTypes", "CHAFF GRASS_WINDROW") |
802 | entry.additives.fillTypes = g_fillTypeManager:getFillTypesByNames(additivesFillTypeNames, "Warning: '"..xmlFile:getFilename().. "' has invalid fillType '%s'.") |
803 | |
804 | -- automatic tilt |
805 | entry.automaticTilt = {} |
806 | entry.automaticTilt.nodes = {} |
807 | xmlFile:iterate(baseKey .. ".automaticTilt.automaticTiltNode", function(index, key) |
808 | local automaticTiltNode = {} |
809 | automaticTiltNode.node = xmlFile:getValue(key .. "#node", nil, self.components, self.i3dMappings) |
810 | if automaticTiltNode.node ~= nil then |
811 | automaticTiltNode.minAngle = xmlFile:getValue(key .. "#minAngle", -5) |
812 | automaticTiltNode.maxAngle = xmlFile:getValue(key .. "#maxAngle", 5) |
813 | |
814 | automaticTiltNode.maxSpeed = xmlFile:getValue(key .. "#maxSpeed", 2) / 1000 |
815 | automaticTiltNode.updateAttacherJoint = xmlFile:getValue(key .. "#updateAttacherJoint") |
816 | automaticTiltNode.dependentAnimation = xmlFile:getValue(key .. "#dependentAnimation") |
817 | automaticTiltNode.lastJointUpdateRot = 0 |
818 | |
819 | table.insert(entry.automaticTilt.nodes, automaticTiltNode) |
820 | end |
821 | end) |
822 | |
823 | entry.automaticTilt.hasNodes = #entry.automaticTilt.nodes > 0 |
824 | end |
loadTurnedOnAnimationFromXML
DescriptionDefinitionloadTurnedOnAnimationFromXML()Code
1682 | function Combine:loadTurnedOnAnimationFromXML(superFunc, xmlFile, key, turnedOnAnimation) |
1683 | turnedOnAnimation.activeChopper = xmlFile:getValue(key.."#activeChopper", true) |
1684 | turnedOnAnimation.activeStrawDrop = xmlFile:getValue(key.."#activeStrawDrop", true) |
1685 | turnedOnAnimation.waitForStraw = xmlFile:getValue(key.."#waitForStraw", false) |
1686 | |
1687 | return superFunc(self, xmlFile, key, turnedOnAnimation) |
1688 | end |
loadWorkAreaFromXML
DescriptionDefinitionloadWorkAreaFromXML()Code
1630 | function Combine:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key) |
1631 | if not superFunc(self, workArea, xmlFile, key) then |
1632 | return false |
1633 | end |
1634 | |
1635 | if workArea.type == WorkAreaType.COMBINECHOPPER or workArea.type == WorkAreaType.COMBINESWATH then |
1636 | if xmlFile:getValue(key .. "#requiresOwnedFarmland") == nil then |
1637 | workArea.requiresOwnedFarmland = false |
1638 | end |
1639 | if xmlFile:getValue(key .. "#needsSetIsTurnedOn") == nil then |
1640 | workArea.needsSetIsTurnedOn = false |
1641 | end |
1642 | end |
1643 | |
1644 | return true |
1645 | end |
onChangedFillType
DescriptionDefinitiononChangedFillType()Code
1764 | function Combine:onChangedFillType(fillUnitIndex, fillTypeIndex) |
1765 | local spec = self.spec_combine |
1766 | if spec.bufferFillUnitIndex ~= nil and fillUnitIndex == spec.bufferFillUnitIndex or fillUnitIndex == spec.fillUnitIndex then |
1767 | if fillTypeIndex ~= FillType.UNKNOWN then |
1768 | if fillTypeIndex ~= spec.lastEffectFillType then |
1769 | if spec.chopperPSenabled then |
1770 | self:setChopperPSEnabled(true, true, 0, true) |
1771 | end |
1772 | if spec.strawPSenabled then |
1773 | self:setStrawPSEnabled(true, true, 0, true) |
1774 | end |
1775 | if spec.isFilling then |
1776 | self:setCombineIsFilling(true, true, true) |
1777 | end |
1778 | end |
1779 | |
1780 | spec.lastEffectFillType = fillTypeIndex |
1781 | end |
1782 | end |
1783 | end |
onDeactivate
DescriptionCalled on deactivateDefinition
onDeactivate()Code
1787 | function Combine:onDeactivate() |
1788 | local spec = self.spec_combine |
1789 | |
1790 | self:setChopperPSEnabled(false, false, 0, true) |
1791 | self:setStrawPSEnabled(false, false, 0, true) |
1792 | self:setCombineIsFilling(false, false, true) |
1793 | spec.fillEnableTime = nil |
1794 | spec.fillDisableTime = nil |
1795 | end |
onDelete
DescriptionCalled on deletingDefinition
onDelete()Code
337 | function Combine:onDelete() |
338 | local spec = self.spec_combine |
339 | |
340 | g_effectManager:deleteEffects(spec.effects) |
341 | g_effectManager:deleteEffects(spec.fillEffects) |
342 | g_effectManager:deleteEffects(spec.strawEffects) |
343 | g_effectManager:deleteEffects(spec.chopperEffects) |
344 | |
345 | g_animationManager:deleteAnimations(spec.animationNodes) |
346 | g_animationManager:deleteAnimations(spec.chopperAnimationNodes) |
347 | g_animationManager:deleteAnimations(spec.strawDropAnimationNodes) |
348 | g_animationManager:deleteAnimations(spec.fillingAnimationNodes) |
349 | |
350 | g_soundManager:deleteSamples(spec.samples) |
351 | end |
onDraw
DescriptionCalled on drawDefinition
onDraw(boolean isActiveForInput, boolean isSelected)Arguments
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
685 | function Combine:onDraw(isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
686 | local spec = self.spec_combine |
687 | if self:getIsTurnedOn() and self:getIsThreshingDuringRain(false) then |
688 | if not spec.threshingDuringRainWarningDisplayed then |
689 | g_currentMission:showBlinkingWarning(spec.texts.warningRainReducesYield, 4000) |
690 | spec.threshingDuringRainWarningDisplayed = true |
691 | end |
692 | else |
693 | spec.threshingDuringRainWarningDisplayed = false |
694 | end |
695 | end |
onEndWorkAreaProcessing
DescriptionDefinitiononEndWorkAreaProcessing()Code
1756 | function Combine:onEndWorkAreaProcessing(dt, hasProcessed) |
1757 | local spec = self.spec_combine |
1758 | local inputBuffer = spec.processing.inputBuffer |
1759 | inputBuffer.buffer[inputBuffer.dropIndex].liters = math.max(0, inputBuffer.buffer[inputBuffer.dropIndex].liters - spec.workAreaParameters.droppedLiters) |
1760 | end |
onEnterVehicle
DescriptionDefinitiononEnterVehicle()Code
1870 | function Combine:onEnterVehicle() |
1871 | local ladder = self.spec_combine.ladder |
1872 | if ladder.animName ~= nil then |
1873 | local fold = true |
1874 | if self.getFoldAnimTime ~= nil then |
1875 | local foldAnimTime = self:getFoldAnimTime() |
1876 | if foldAnimTime > ladder.foldMaxLimit or foldAnimTime < ladder.foldMinLimit then |
1877 | fold = false |
1878 | end |
1879 | end |
1880 | |
1881 | if ladder.unfoldWhileCutterAttached then |
1882 | if self.spec_combine.numAttachedCutters > 0 then |
1883 | fold = false |
1884 | end |
1885 | end |
1886 | |
1887 | if fold then |
1888 | self:playAnimation(ladder.animName, -ladder.animSpeedScale, self:getAnimationTime(ladder.animName), true) |
1889 | end |
1890 | end |
1891 | end |
onFillUnitFillLevelChanged
DescriptionDefinitiononFillUnitFillLevelChanged()Code
1938 | function Combine:onFillUnitFillLevelChanged(fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData, appliedDelta) |
1939 | local spec = self.spec_combine |
1940 | |
1941 | if fillUnitIndex == spec.fillUnitIndex then |
1942 | if fillLevelDelta < 0 then |
1943 | spec.lastDischargeTime = g_time |
1944 | end |
1945 | end |
1946 | end |
onFoldStateChanged
DescriptionDefinitiononFoldStateChanged()Code
1920 | function Combine:onFoldStateChanged(direction, moveToMiddle) |
1921 | local ladder = self.spec_combine.ladder |
1922 | if ladder.animName ~= nil and direction ~= 0 and not moveToMiddle then |
1923 | local fold = true |
1924 | if ladder.unfoldWhileCutterAttached then |
1925 | if self.spec_combine.numAttachedCutters > 0 then |
1926 | fold = false |
1927 | end |
1928 | end |
1929 | |
1930 | if fold then |
1931 | self:playAnimation(ladder.animName, direction*ladder.animSpeedScale*ladder.foldDirection, self:getAnimationTime(ladder.animName), true) |
1932 | end |
1933 | end |
1934 | end |
onLeaveVehicle
DescriptionDefinitiononLeaveVehicle()Code
1895 | function Combine:onLeaveVehicle() |
1896 | local ladder = self.spec_combine.ladder |
1897 | if ladder.animName ~= nil then |
1898 | local fold = true |
1899 | if self.getFoldAnimTime ~= nil then |
1900 | local foldAnimTime = self:getFoldAnimTime() |
1901 | if foldAnimTime > ladder.foldMaxLimit or foldAnimTime < ladder.foldMinLimit then |
1902 | fold = false |
1903 | end |
1904 | end |
1905 | |
1906 | if ladder.unfoldWhileCutterAttached then |
1907 | if self.spec_combine.numAttachedCutters > 0 then |
1908 | fold = false |
1909 | end |
1910 | end |
1911 | |
1912 | if fold then |
1913 | self:playAnimation(ladder.animName, ladder.animSpeedScale, self:getAnimationTime(ladder.animName), true) |
1914 | end |
1915 | end |
1916 | end |
onLoad
DescriptionDefinitiononLoad()Code
205 | function Combine:onLoad(savegame) |
206 | local spec = self.spec_combine |
207 | |
208 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.combine.chopperSwitch", "vehicle.combine.swath and vehicle.combine.chopper") --FS17 to FS19 |
209 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnedOnRotationNodes.turnedOnRotationNode#type", "vehicle.combine.rotationNodes.rotationNode", "combine") --FS17 to FS19 |
210 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.indoorHud.workedHectars", "vehicle.combine.dashboards.dashboard with valueType 'workedHectars'") --FS17 to FS19 |
211 | |
212 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.combine.folding#fillLevelThreshold", "vehicle.combine.folding#fillLevelThresholdPct") --FS19 to FS22 |
213 | |
214 | self:loadCombineSetup(self.xmlFile, "vehicle.combine", spec) |
215 | self:loadCombineEffects(self.xmlFile, "vehicle.combine", spec) |
216 | self:loadCombineRotationNodes(self.xmlFile, "vehicle.combine", spec) |
217 | self:loadCombineSamples(self.xmlFile, "vehicle.combine", spec) |
218 | |
219 | spec.attachedCutters = {} |
220 | spec.numAttachedCutters = 0 |
221 | |
222 | spec.texts = {} |
223 | spec.texts.warningFoldingTurnedOn = g_i18n:getText("warning_foldingNotWhileTurnedOn") |
224 | spec.texts.warningFoldingWhileFilled = g_i18n:getText("warning_foldingNotWhileFilled") |
225 | spec.texts.warningRainReducesYield = g_i18n:getText("warning_rainReducesYield") |
226 | spec.texts.warningNoCutter = self.xmlFile:getValue("vehicle.combine.warning#noCutter", g_i18n:getText("warning_noCuttersAttached"), self.customEnvironment) |
227 | |
228 | spec.threshingDuringRainWarningDisplayed = false |
229 | |
230 | spec.lastArea = 0 |
231 | spec.lastAreaZeroTime = 0 |
232 | spec.lastAreaNonZeroTime = -1000000 |
233 | spec.lastCuttersArea = 0 |
234 | spec.lastCuttersAreaTime = -10000 |
235 | spec.lastInputFruitType = FruitType.UNKNOWN |
236 | spec.lastValidInputFruitType = FruitType.UNKNOWN |
237 | spec.lastCuttersFruitType = FruitType.UNKNOWN |
238 | spec.lastCuttersInputFruitType = FruitType.UNKNOWN |
239 | spec.lastValidInputFillType = FillType.UNKNOWN |
240 | spec.lastDischargeTime = 0 |
241 | spec.lastChargeTime = 0 |
242 | spec.fillLevelBufferTime = self.xmlFile:getValue("vehicle.combine#fillLevelBufferTime", 2000) -- time the fill level buffer is filled without unloading |
243 | |
244 | spec.workedHectars = 0 |
245 | spec.workedHectarsSent = 0 |
246 | if self.loadDashboardsFromXML ~= nil then |
247 | local dashboardData = {valueTypeToLoad = "workedHectars", |
248 | valueObject = spec, |
249 | valueFunc = "workedHectars"} |
250 | |
251 | self:loadDashboardsFromXML(self.xmlFile, "vehicle.combine.dashboards", dashboardData) |
252 | end |
253 | |
254 | spec.threshingScale = 1 |
255 | spec.lastLostFillLevel = 0 |
256 | |
257 | spec.workAreaParameters = {} |
258 | spec.workAreaParameters.lastRealArea = 0 |
259 | spec.workAreaParameters.lastArea = 0 |
260 | spec.workAreaParameters.litersToDrop = 0 |
261 | spec.workAreaParameters.droppedLiters = 0 |
262 | spec.workAreaParameters.isChopperEffectEnabled = 0 |
263 | spec.workAreaParameters.isStrawEffectEnabled = 0 |
264 | spec.workAreaParameters.effectDensity = 0.2 |
265 | spec.workAreaParameters.effectDensitySent = 0.2 |
266 | |
267 | spec.dirtyFlag = self:getNextDirtyFlag() |
268 | spec.effectDirtyFlag = self:getNextDirtyFlag() |
269 | end |
onPostAttachImplement
DescriptionCalled on attaching a implementDefinition
onPostAttachImplement(table implement)Arguments
table | implement | implement to attach |
1800 | function Combine:onPostAttachImplement(attachable, inputJointDescIndex, jointDescIndex) |
1801 | local attacherJoint = attachable:getActiveInputAttacherJoint() |
1802 | if attacherJoint ~= nil then |
1803 | if attacherJoint.jointType == AttacherJoints.JOINTTYPE_CUTTER or attacherJoint.jointType == AttacherJoints.JOINTTYPE_CUTTERHARVESTER then |
1804 | self:addCutterToCombine(attachable) |
1805 | end |
1806 | end |
1807 | end |
onPostDetachImplement
DescriptionCalled on detaching a implementDefinition
onPostDetachImplement(integer implementIndex)Arguments
integer | implementIndex | index of implement to detach |
1812 | function Combine:onPostDetachImplement(implementIndex) |
1813 | local object = self:getObjectFromImplementIndex(implementIndex) |
1814 | if object ~= nil then |
1815 | local attacherJoint = object:getActiveInputAttacherJoint() |
1816 | if attacherJoint ~= nil then |
1817 | if attacherJoint.jointType == AttacherJoints.JOINTTYPE_CUTTER or attacherJoint.jointType == AttacherJoints.JOINTTYPE_CUTTERHARVESTER then |
1818 | self:removeCutterFromCombine(object) |
1819 | end |
1820 | end |
1821 | end |
1822 | end |
onPostLoad
DescriptionCalled after loadingDefinition
onPostLoad(table savegame)Arguments
table | savegame | savegame |
274 | function Combine:onPostLoad(savegame) |
275 | local spec = self.spec_combine |
276 | |
277 | if savegame ~= nil then |
278 | if spec.swath.isAvailable then |
279 | local isSwathActive = savegame.xmlFile:getValue(savegame.key .. ".combine#isSwathActive", spec.isSwathActive) |
280 | self:setIsSwathActive(isSwathActive, true, true) |
281 | end |
282 | self:setWorkedHectars(savegame.xmlFile:getValue(savegame.key .. ".combine#workedHectars", spec.workedHectars)) |
283 | else |
284 | self:setIsSwathActive(spec.isSwathActive, true, true) |
285 | end |
286 | |
287 | spec.isBufferCombine = self:getFillUnitCapacity(self.spec_combine.fillUnitIndex) == math.huge |
288 | if spec.isBufferCombine then |
289 | local fillUnit = self:getFillUnitByIndex(self.spec_combine.fillUnitIndex) |
290 | if fillUnit.showOnInfoHud then |
291 | Logging.xmlWarning(self.xmlFile, "Buffer combine fill unit is displayed in info hud! Add showOnInfoHud='false' to the fill unit.") |
292 | end |
293 | end |
294 | |
295 | local ladder = spec.ladder |
296 | if ladder.animName ~= nil then |
297 | local time = 0 |
298 | if self.getFoldAnimTime ~= nil then |
299 | local foldAnimTime = self:getFoldAnimTime() |
300 | if foldAnimTime > ladder.foldMaxLimit or foldAnimTime < ladder.foldMinLimit then |
301 | time = 1 |
302 | end |
303 | end |
304 | |
305 | if ladder.unfoldWhileCutterAttached then |
306 | if savegame ~= nil and not savegame.resetVehicles then |
307 | local numAttachedCutters = savegame.xmlFile:getValue(savegame.key .. ".combine#numAttachedCutters", 0) |
308 | if numAttachedCutters > 0 then |
309 | time = 1 |
310 | end |
311 | end |
312 | end |
313 | |
314 | if ladder.foldDirection ~= 1 then |
315 | time = 1 - time |
316 | end |
317 | |
318 | self:setAnimationTime(ladder.animName, time, true) |
319 | end |
320 | |
321 | if spec.bufferFillUnitIndex ~= nil then |
322 | local fillUnit = self:getFillUnitByIndex(spec.fillUnitIndex) |
323 | local bufferUnit = self:getFillUnitByIndex(spec.bufferFillUnitIndex) |
324 | if fillUnit ~= nil and bufferUnit ~= nil then |
325 | bufferUnit.parentUnitOnHud = spec.fillUnitIndex |
326 | fillUnit.childUnitOnHud = spec.bufferFillUnitIndex |
327 | end |
328 | end |
329 | |
330 | if self:getFillUnitCapacity(spec.fillUnitIndex) == 0 then |
331 | Logging.xmlWarning(self.xmlFile, "Capacity of fill unit '%d' for combine needs to be set greater 0 or not defined! (not defined = infinity)", spec.fillUnitIndex) |
332 | end |
333 | end |
onReadStream
DescriptionCalled on client side on joinDefinition
onReadStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
370 | function Combine:onReadStream(streamId, connection) |
371 | local spec = self.spec_combine |
372 | |
373 | spec.lastValidInputFruitType = streamReadUIntN(streamId, FruitTypeManager.SEND_NUM_BITS) |
374 | local combineIsFilling = streamReadBool(streamId) |
375 | local chopperPSenabled = streamReadBool(streamId) |
376 | local strawPSenabled = streamReadBool(streamId) |
377 | spec.lastValidInputFillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS) |
378 | |
379 | self:setCombineIsFilling(combineIsFilling, false, true) |
380 | self:setChopperPSEnabled(chopperPSenabled, false, 1, true) |
381 | self:setStrawPSEnabled(strawPSenabled, false, 1, true) |
382 | |
383 | local isSwathActive = streamReadBool(streamId) |
384 | self:setIsSwathActive(isSwathActive, true) |
385 | |
386 | local workedHectars = streamReadFloat32(streamId) |
387 | self:setWorkedHectars(workedHectars) |
388 | end |
onReadUpdateStream
DescriptionCalled on on updateDefinition
onReadUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | stream ID |
integer | timestamp | timestamp |
table | connection | connection |
412 | function Combine:onReadUpdateStream(streamId, timestamp, connection) |
413 | if connection:getIsServer() then |
414 | local spec = self.spec_combine |
415 | if streamReadBool(streamId) then |
416 | spec.lastValidInputFruitType = streamReadUIntN(streamId, FruitTypeManager.SEND_NUM_BITS) |
417 | |
418 | local workedHectars = streamReadFloat32(streamId) |
419 | self:setWorkedHectars(workedHectars) |
420 | end |
421 | |
422 | if streamReadBool(streamId) then |
423 | local combineIsFilling = streamReadBool(streamId) |
424 | local chopperPSenabled = streamReadBool(streamId) |
425 | local strawPSenabled = streamReadBool(streamId) |
426 | local effectDensity = streamReadUIntN(streamId, 5) |
427 | effectDensity = effectDensity / (2^5 - 1) |
428 | |
429 | spec.lastValidInputFillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS) |
430 | |
431 | self:setCombineIsFilling(combineIsFilling, false, true) |
432 | self:setChopperPSEnabled(chopperPSenabled, false, effectDensity, true) |
433 | self:setStrawPSEnabled(strawPSenabled, false, effectDensity, true) |
434 | end |
435 | end |
436 | end |
onRegisterActionEvents
DescriptionDefinitiononRegisterActionEvents()Code
1709 | function Combine:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
1710 | if self.isClient then |
1711 | |
1712 | local spec = self.spec_combine |
1713 | self:clearActionEventsTable(spec.actionEvents) |
1714 | |
1715 | if isActiveForInputIgnoreSelection and spec.swath.isAvailable and spec.chopper.isAvailable then |
1716 | local func = self.addActionEvent |
1717 | if spec.chopper.isPowered then |
1718 | func = self.addPoweredActionEvent |
1719 | end |
1720 | |
1721 | local _, actionEventId = func(self, spec.actionEvents, InputAction.TOGGLE_CHOPPER, self, Combine.actionEventToggleChopper, false, true, false, true, nil) |
1722 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL) |
1723 | Combine.updateToggleStrawText(self) |
1724 | end |
1725 | end |
1726 | end |
onStartWorkAreaProcessing
DescriptionDefinitiononStartWorkAreaProcessing()Code
1730 | function Combine:onStartWorkAreaProcessing(dt) |
1731 | local spec = self.spec_combine |
1732 | |
1733 | spec.workAreaParameters.droppedLiters = 0 |
1734 | spec.workAreaParameters.litersToDrop = 0 |
1735 | spec.workAreaParameters.strawRatio = 0 |
1736 | spec.workAreaParameters.dropFillType = FillType.UNKNOWN |
1737 | |
1738 | local fillUnitIndex = spec.bufferFillUnitIndex or spec.fillUnitIndex |
1739 | local lastValidFillType = self:getFillUnitLastValidFillType(fillUnitIndex) |
1740 | if lastValidFillType ~= FillType.UNKNOWN then |
1741 | local inputBuffer = spec.processing.inputBuffer |
1742 | local inputLiters = inputBuffer.buffer[inputBuffer.dropIndex].inputLiters |
1743 | spec.workAreaParameters.litersToDrop = math.min(inputBuffer.buffer[inputBuffer.dropIndex].liters, (dt / inputBuffer.slotDuration) * inputLiters) |
1744 | spec.workAreaParameters.strawRatio = inputBuffer.buffer[inputBuffer.dropIndex].strawRatio |
1745 | spec.workAreaParameters.strawGroundType = inputBuffer.buffer[inputBuffer.dropIndex].strawGroundType |
1746 | spec.workAreaParameters.effectDensity = inputBuffer.buffer[inputBuffer.dropIndex].effectDensity |
1747 | spec.workAreaParameters.dropFillType = lastValidFillType |
1748 | end |
1749 | |
1750 | spec.workAreaParameters.lastRealArea = 0 |
1751 | spec.workAreaParameters.lastArea = 0 |
1752 | end |
onTurnedOff
DescriptionCalled on turn offDefinition
onTurnedOff(boolean noEventSend)Arguments
boolean | noEventSend | no event send |
1851 | function Combine:onTurnedOff() |
1852 | self:stopThreshing() |
1853 | if self.isClient then |
1854 | local spec = self.spec_combine |
1855 | g_animationManager:stopAnimations(spec.animationNodes) |
1856 | g_animationManager:stopAnimations(spec.chopperAnimationNodes) |
1857 | g_animationManager:stopAnimations(spec.strawDropAnimationNodes) |
1858 | |
1859 | g_effectManager:stopEffects(spec.effects) |
1860 | |
1861 | if g_soundManager:getIsSamplePlaying(spec.samples.chopperWork) then |
1862 | g_soundManager:stopSample(spec.samples.chopperWork) |
1863 | g_soundManager:playSample(spec.samples.chopperStop) |
1864 | end |
1865 | end |
1866 | end |
onTurnedOn
DescriptionCalled on turn onDefinition
onTurnedOn(boolean noEventSend)Arguments
boolean | noEventSend | no event send |
1827 | function Combine:onTurnedOn() |
1828 | self:startThreshing() |
1829 | if self.isClient then |
1830 | local spec = self.spec_combine |
1831 | g_animationManager:startAnimations(spec.animationNodes) |
1832 | |
1833 | if spec.isSwathActive then |
1834 | g_animationManager:startAnimations(spec.strawDropAnimationNodes) |
1835 | else |
1836 | g_animationManager:startAnimations(spec.chopperAnimationNodes) |
1837 | |
1838 | g_soundManager:stopSample(spec.samples.chopperStop) |
1839 | g_soundManager:playSample(spec.samples.chopperStart) |
1840 | g_soundManager:playSample(spec.samples.chopperWork, 0, spec.samples.chopperStart) |
1841 | end |
1842 | |
1843 | g_effectManager:setFillType(spec.effects, self:getCombineLastValidFillType()) |
1844 | g_effectManager:startEffects(spec.effects) |
1845 | end |
1846 | end |
onUpdate
DescriptionCalled on updateDefinition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)Arguments
float | dt | time since last call in ms |
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
469 | function Combine:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
470 | local spec = self.spec_combine |
471 | |
472 | local isTurnedOn = self:getIsTurnedOn() |
473 | if isTurnedOn then |
474 | if self.isServer and spec.swath.isAvailable then |
475 | -- check for changes while threshing, e.g. activated straw swath and then start threshing canola (has no windrow) |
476 | local fillUnitIndex = spec.bufferFillUnitIndex or spec.fillUnitIndex |
477 | local fruitType = g_fruitTypeManager:getFruitTypeIndexByFillTypeIndex(self:getFillUnitFillType(fillUnitIndex)) |
478 | if spec.isSwathActive and fruitType ~= nil and fruitType ~= FruitType.UNKNOWN then |
479 | local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitType) |
480 | if not fruitDesc.hasWindrow then |
481 | self:setIsSwathActive(false) |
482 | end |
483 | else |
484 | -- if the combine does not support chopper but it was forced by the last fill type |
485 | -- if the new fill type supports swath again we change it back |
486 | if not spec.chopper.isAvailable or spec.automatedChopperSwitch then |
487 | if not spec.isSwathActive and fruitType ~= nil and fruitType ~= FruitType.UNKNOWN then |
488 | local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitType) |
489 | if fruitDesc.hasWindrow then |
490 | self:setIsSwathActive(true) |
491 | |
492 | -- empty input buffer to prevent dropping of wrong fill type windrow |
493 | local inputBuffer = spec.processing.inputBuffer |
494 | for i=1, #inputBuffer.buffer do |
495 | inputBuffer.buffer[i].area = 0 |
496 | inputBuffer.buffer[i].realArea = 0 |
497 | inputBuffer.buffer[i].liters = 0 |
498 | inputBuffer.buffer[i].inputLiters = 0 |
499 | end |
500 | end |
501 | end |
502 | end |
503 | end |
504 | end |
505 | end |
506 | |
507 | if self.isServer then |
508 | if self:getFillUnitFillLevel(spec.fillUnitIndex) < 0.0001 then |
509 | spec.lastDischargeTime = g_time |
510 | end |
511 | end |
512 | |
513 | if spec.automaticTilt.hasNodes then |
514 | local currentDelta, isActive, doReset = 0, false, false |
515 | |
516 | local _, cutter = next(spec.attachedCutters) |
517 | if cutter ~= nil and cutter:getCutterTiltIsAvailable() then |
518 | currentDelta, isActive, doReset = cutter:getCutterTiltDelta() |
519 | end |
520 | |
521 | for i=1, #spec.automaticTilt.nodes do |
522 | local automaticTiltNode = spec.automaticTilt.nodes[i] |
523 | |
524 | local _, _, curZ = getRotation(automaticTiltNode.node) |
525 | if not isActive and doReset then |
526 | currentDelta = -curZ -- return to idle if not active |
527 | end |
528 | |
529 | if math.abs(currentDelta) > 0.00001 then |
530 | local speedScale = math.min(math.pow(math.abs(currentDelta) / 0.01745, 2), 1) * MathUtil.sign(currentDelta) |
531 | if not isActive and doReset then |
532 | speedScale = speedScale * 0.5 |
533 | end |
534 | |
535 | local rotSpeed = speedScale * automaticTiltNode.maxSpeed * dt |
536 | local newRotZ = MathUtil.clamp(curZ + rotSpeed, automaticTiltNode.minAngle, automaticTiltNode.maxAngle) |
537 | setRotation(automaticTiltNode.node, 0, 0, newRotZ) |
538 | |
539 | if automaticTiltNode.dependentAnimation ~= nil then |
540 | local alpha = MathUtil.inverseLerp(automaticTiltNode.minAngle, automaticTiltNode.maxAngle, newRotZ) |
541 | self:setAnimationTime(automaticTiltNode.dependentAnimation, alpha, true) |
542 | end |
543 | |
544 | if cutter ~= nil and automaticTiltNode.updateAttacherJoint and math.abs(newRotZ-automaticTiltNode.lastJointUpdateRot) > 0.00001 then |
545 | automaticTiltNode.lastJointUpdateRot = newRotZ |
546 | local jointDesc = self:getAttacherJointDescFromObject(cutter) |
547 | if jointDesc.jointIndex ~= 0 then |
548 | setJointFrame(jointDesc.jointIndex, 0, jointDesc.jointTransform) |
549 | end |
550 | end |
551 | |
552 | if self.setMovingToolDirty ~= nil then |
553 | self:setMovingToolDirty(automaticTiltNode.node) |
554 | end |
555 | end |
556 | end |
557 | end |
558 | end |
onUpdateTick
DescriptionCalled on update tickDefinition
onUpdateTick(float dt, boolean isActiveForInput, boolean isSelected)Arguments
float | dt | time since last call in ms |
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
565 | function Combine:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
566 | local spec = self.spec_combine |
567 | |
568 | if self.isServer then |
569 | spec.lastArea = spec.lastCuttersArea |
570 | spec.lastAreaZeroTime = spec.lastAreaZeroTime + dt |
571 | if spec.lastArea > 0 then |
572 | spec.lastAreaZeroTime = 0 |
573 | spec.lastAreaNonZeroTime = g_currentMission.time |
574 | end |
575 | spec.lastInputFruitType = spec.lastCuttersInputFruitType |
576 | spec.lastCuttersArea = 0 |
577 | spec.lastCuttersInputFruitType = FruitType.UNKNOWN |
578 | spec.lastCuttersFruitType = FruitType.UNKNOWN |
579 | |
580 | if spec.lastInputFruitType ~= FruitType.UNKNOWN then |
581 | spec.lastValidInputFruitType = spec.lastInputFruitType |
582 | end |
583 | |
584 | local inputBuffer = spec.processing.inputBuffer |
585 | |
586 | if spec.lastAreaZeroTime > spec.fillTimeThreshold then |
587 | if spec.fillDisableTime == nil then |
588 | spec.fillDisableTime = g_currentMission.time + spec.processing.toggleTime |
589 | end |
590 | end |
591 | if spec.fillEnableTime ~= nil and spec.fillEnableTime <= g_currentMission.time then |
592 | self:setCombineIsFilling(true, false, false) |
593 | spec.fillEnableTime = nil |
594 | end |
595 | if spec.fillDisableTime ~= nil and spec.fillDisableTime <= g_currentMission.time then |
596 | self:setCombineIsFilling(false, false, false) |
597 | spec.fillDisableTime = nil |
598 | end |
599 | |
600 | spec.workAreaParameters.isChopperEffectEnabled = math.max(spec.workAreaParameters.isChopperEffectEnabled - dt, 0) |
601 | spec.workAreaParameters.isStrawEffectEnabled = math.max(spec.workAreaParameters.isStrawEffectEnabled - dt, 0) |
602 | |
603 | local density = spec.workAreaParameters.effectDensity |
604 | local chopperPSActive = spec.workAreaParameters.isChopperEffectEnabled > 0 |
605 | local strawPSActive = spec.workAreaParameters.isStrawEffectEnabled > 0 |
606 | self:setChopperPSEnabled(chopperPSActive, false, density, false) |
607 | self:setStrawPSEnabled(strawPSActive, false, density, false) |
608 | |
609 | if chopperPSActive or strawPSActive then |
610 | self:raiseActive() |
611 | end |
612 | |
613 | if self:getIsTurnedOn() then |
614 | local stats = g_currentMission:farmStats(self:getOwnerFarmId()) |
615 | stats:updateStats("threshedTime", dt / (1000 * 60)) |
616 | |
617 | self:updateLastWorkedArea(0) -- mark as working |
618 | end |
619 | |
620 | inputBuffer.slotTimer = inputBuffer.slotTimer - dt |
621 | if inputBuffer.slotTimer < 0 then |
622 | inputBuffer.slotTimer = inputBuffer.slotDuration |
623 | |
624 | inputBuffer.fillIndex = inputBuffer.fillIndex + 1 |
625 | if inputBuffer.fillIndex > inputBuffer.slotCount then |
626 | inputBuffer.fillIndex = 1 |
627 | end |
628 | |
629 | local lastDropIndex = inputBuffer.dropIndex |
630 | inputBuffer.dropIndex = inputBuffer.dropIndex + 1 |
631 | if inputBuffer.dropIndex > inputBuffer.slotCount then |
632 | inputBuffer.dropIndex = 1 |
633 | end |
634 | |
635 | inputBuffer.buffer[inputBuffer.dropIndex].liters = inputBuffer.buffer[inputBuffer.dropIndex].liters + inputBuffer.buffer[lastDropIndex].liters |
636 | inputBuffer.buffer[inputBuffer.dropIndex].inputLiters = inputBuffer.buffer[inputBuffer.dropIndex].inputLiters + inputBuffer.buffer[lastDropIndex].liters --inputLiters |
637 | |
638 | inputBuffer.buffer[lastDropIndex].area = 0 |
639 | inputBuffer.buffer[lastDropIndex].realArea = 0 |
640 | inputBuffer.buffer[lastDropIndex].liters = 0 |
641 | inputBuffer.buffer[lastDropIndex].inputLiters = 0 |
642 | end |
643 | |
644 | if spec.bufferFillUnitIndex ~= nil then |
645 | if spec.lastCuttersAreaTime + dt * 10 < g_currentMission.time then |
646 | if self:getFillUnitFillLevel(spec.bufferFillUnitIndex) > 0 then |
647 | local deltaFillLevel = dt * (self:getFillUnitCapacity(spec.bufferFillUnitIndex) / spec.bufferUnloadingTime) |
648 | deltaFillLevel = self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.bufferFillUnitIndex, -deltaFillLevel, self:getFillUnitFillType(spec.bufferFillUnitIndex), ToolType.UNDEFINED) |
649 | |
650 | self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -deltaFillLevel, self:getFillUnitFillType(spec.bufferFillUnitIndex), ToolType.UNDEFINED, self:getFillVolumeLoadInfo(spec.loadInfoIndex)) |
651 | end |
652 | end |
653 | end |
654 | |
655 | if spec.loadingDelay > 0 then |
656 | for i=1, #spec.loadingDelaySlots do |
657 | local slot = spec.loadingDelaySlots[i] |
658 | if slot.valid then |
659 | if slot.time + spec.loadingDelay < g_time then |
660 | slot.valid = false |
661 | self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, slot.fillLevelDelta, slot.fillType, ToolType.UNDEFINED, self:getFillVolumeLoadInfo(spec.loadInfoIndex)) |
662 | end |
663 | end |
664 | end |
665 | end |
666 | |
667 | if spec.isFilling ~= spec.sentIsFilling |
668 | or spec.chopperPSenabled ~= spec.sentChopperPSenabled |
669 | or spec.strawPSenabled ~= spec.sentStrawPSenabled |
670 | or math.abs(spec.workAreaParameters.effectDensity - spec.workAreaParameters.effectDensitySent) > 0.05 then |
671 | self:raiseDirtyFlags(spec.effectDirtyFlag) |
672 | |
673 | spec.sentIsFilling = spec.isFilling |
674 | spec.sentChopperPSenabled = spec.chopperPSenabled |
675 | spec.sentStrawPSenabled = spec.strawPSenabled |
676 | spec.workAreaParameters.effectDensitySent = spec.workAreaParameters.effectDensity |
677 | end |
678 | end |
679 | end |
onWriteStream
DescriptionCalled on server side on joinDefinition
onWriteStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
394 | function Combine:onWriteStream(streamId, connection) |
395 | local spec = self.spec_combine |
396 | |
397 | streamWriteUIntN(streamId, spec.lastValidInputFruitType, FruitTypeManager.SEND_NUM_BITS) |
398 | streamWriteBool(streamId, spec.isFilling) |
399 | streamWriteBool(streamId, spec.chopperPSenabled) |
400 | streamWriteBool(streamId, spec.strawPSenabled) |
401 | streamWriteUIntN(streamId, self:getCombineLastValidFillType(), FillTypeManager.SEND_NUM_BITS) |
402 | |
403 | streamWriteBool(streamId, spec.isSwathActive) |
404 | streamWriteFloat32(streamId, spec.workedHectars) |
405 | end |
onWriteUpdateStream
DescriptionCalled on on updateDefinition
onWriteUpdateStream(integer streamId, table connection, integer dirtyMask)Arguments
integer | streamId | stream ID |
table | connection | connection |
integer | dirtyMask | dirty mask |
443 | function Combine:onWriteUpdateStream(streamId, connection, dirtyMask) |
444 | if not connection:getIsServer() then |
445 | local spec = self.spec_combine |
446 | |
447 | if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then |
448 | streamWriteUIntN(streamId, spec.lastValidInputFruitType, FruitTypeManager.SEND_NUM_BITS) |
449 | streamWriteFloat32(streamId, spec.workedHectars) |
450 | end |
451 | |
452 | if streamWriteBool(streamId, bitAND(dirtyMask, spec.effectDirtyFlag) ~= 0) then |
453 | streamWriteBool(streamId, spec.isFilling) |
454 | streamWriteBool(streamId, spec.chopperPSenabled) |
455 | streamWriteBool(streamId, spec.strawPSenabled) |
456 | |
457 | streamWriteUIntN(streamId, spec.workAreaParameters.effectDensity * (2^5 - 1), 5) |
458 | |
459 | streamWriteUIntN(streamId, self:getCombineLastValidFillType(), FillTypeManager.SEND_NUM_BITS) |
460 | end |
461 | end |
462 | end |
prerequisitesPresent
DescriptionDefinitionprerequisitesPresent()Code
118 | function Combine.prerequisitesPresent(specializations) |
119 | return SpecializationUtil.hasSpecialization(WorkArea, specializations) and |
120 | SpecializationUtil.hasSpecialization(FillUnit, specializations) and |
121 | (SpecializationUtil.hasSpecialization(Drivable, specializations) or SpecializationUtil.hasSpecialization(Attachable, specializations)) and |
122 | SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations) and |
123 | SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations) |
124 | end |
processCombineChopperArea
DescriptionDefinitionprocessCombineChopperArea()Code
942 | function Combine:processCombineChopperArea(workArea) |
943 | local spec = self.spec_combine |
944 | |
945 | if not spec.isSwathActive then |
946 | local litersToDrop = spec.workAreaParameters.litersToDrop |
947 | local strawRatio = spec.workAreaParameters.strawRatio |
948 | local strawGroundType = spec.workAreaParameters.strawGroundType |
949 | spec.workAreaParameters.droppedLiters = litersToDrop |
950 | |
951 | if litersToDrop > 0 and strawRatio > 0 then |
952 | if Platform.gameplay.useSprayDiffuseMaps and strawRatio > 0.5 and strawGroundType ~= nil then |
953 | local xs,_,zs = getWorldTranslation(workArea.start) |
954 | local xw,_,zw = getWorldTranslation(workArea.width) |
955 | local xh,_,zh = getWorldTranslation(workArea.height) |
956 | |
957 | FSDensityMapUtil.setGroundTypeLayerArea(xs, zs, xw, zw, xh, zh, strawGroundType) |
958 | end |
959 | |
960 | -- raise active until litersToDrop is 0 |
961 | self:raiseActive() |
962 | spec.workAreaParameters.isChopperEffectEnabled = 500 |
963 | end |
964 | end |
965 | |
966 | return spec.workAreaParameters.lastRealArea, spec.workAreaParameters.lastArea |
967 | end |
processCombineSwathArea
DescriptionDefinitionprocessCombineSwathArea()Code
971 | function Combine:processCombineSwathArea(workArea) |
972 | local spec = self.spec_combine |
973 | local litersToDrop = spec.workAreaParameters.litersToDrop |
974 | |
975 | if spec.isSwathActive then |
976 | if litersToDrop > 0 then |
977 | local droppedLiters = 0 |
978 | local fruitDesc = g_fruitTypeManager:getFruitTypeByFillTypeIndex(spec.workAreaParameters.dropFillType) |
979 | if fruitDesc ~= nil and fruitDesc.windrowLiterPerSqm ~= nil then |
980 | local windrowFillType = g_fruitTypeManager:getWindrowFillTypeIndexByFruitTypeIndex(fruitDesc.index) |
981 | if windrowFillType ~= nil then |
982 | local sx,sy,sz,ex,ey,ez = DensityMapHeightUtil.getLineByArea(workArea.start, workArea.width, workArea.height, true) |
983 | local dropped, lineOffset = DensityMapHeightUtil.tipToGroundAroundLine(self, litersToDrop, windrowFillType, sx, sy, sz, ex, ey, ez, 0, nil, workArea.lineOffset, false, nil, false) |
984 | droppedLiters = dropped |
985 | workArea.lineOffset = lineOffset |
986 | end |
987 | end |
988 | if droppedLiters > 0 then |
989 | spec.workAreaParameters.isStrawEffectEnabled = 500 |
990 | end |
991 | spec.workAreaParameters.droppedLiters = droppedLiters |
992 | end |
993 | end |
994 | |
995 | return spec.workAreaParameters.lastRealArea, spec.workAreaParameters.lastArea |
996 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
177 | function Combine.registerEventListeners(vehicleType) |
178 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", Combine) |
179 | SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", Combine) |
180 | SpecializationUtil.registerEventListener(vehicleType, "onDelete", Combine) |
181 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Combine) |
182 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Combine) |
183 | SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", Combine) |
184 | SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", Combine) |
185 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Combine) |
186 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Combine) |
187 | SpecializationUtil.registerEventListener(vehicleType, "onDraw", Combine) |
188 | SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", Combine) |
189 | SpecializationUtil.registerEventListener(vehicleType, "onStartWorkAreaProcessing", Combine) |
190 | SpecializationUtil.registerEventListener(vehicleType, "onEndWorkAreaProcessing", Combine) |
191 | SpecializationUtil.registerEventListener(vehicleType, "onChangedFillType", Combine) |
192 | SpecializationUtil.registerEventListener(vehicleType, "onDeactivate", Combine) |
193 | SpecializationUtil.registerEventListener(vehicleType, "onPostAttachImplement", Combine) |
194 | SpecializationUtil.registerEventListener(vehicleType, "onPostDetachImplement", Combine) |
195 | SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", Combine) |
196 | SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", Combine) |
197 | SpecializationUtil.registerEventListener(vehicleType, "onEnterVehicle", Combine) |
198 | SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", Combine) |
199 | SpecializationUtil.registerEventListener(vehicleType, "onFoldStateChanged", Combine) |
200 | SpecializationUtil.registerEventListener(vehicleType, "onFillUnitFillLevelChanged", Combine) |
201 | end |
registerEvents
DescriptionDefinitionregisterEvents()Code
128 | function Combine.registerEvents(vehicleType) |
129 | SpecializationUtil.registerEvent(vehicleType, "onStartThreshing") |
130 | SpecializationUtil.registerEvent(vehicleType, "onStopThreshing") |
131 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
135 | function Combine.registerFunctions(vehicleType) |
136 | SpecializationUtil.registerFunction(vehicleType, "loadCombineSetup", Combine.loadCombineSetup) |
137 | SpecializationUtil.registerFunction(vehicleType, "loadCombineEffects", Combine.loadCombineEffects) |
138 | SpecializationUtil.registerFunction(vehicleType, "loadCombineRotationNodes", Combine.loadCombineRotationNodes) |
139 | SpecializationUtil.registerFunction(vehicleType, "loadCombineSamples", Combine.loadCombineSamples) |
140 | SpecializationUtil.registerFunction(vehicleType, "setIsSwathActive", Combine.setIsSwathActive) |
141 | SpecializationUtil.registerFunction(vehicleType, "processCombineChopperArea", Combine.processCombineChopperArea) |
142 | SpecializationUtil.registerFunction(vehicleType, "processCombineSwathArea", Combine.processCombineSwathArea) |
143 | SpecializationUtil.registerFunction(vehicleType, "setChopperPSEnabled", Combine.setChopperPSEnabled) |
144 | SpecializationUtil.registerFunction(vehicleType, "setStrawPSEnabled", Combine.setStrawPSEnabled) |
145 | SpecializationUtil.registerFunction(vehicleType, "setCombineIsFilling", Combine.setCombineIsFilling) |
146 | SpecializationUtil.registerFunction(vehicleType, "startThreshing", Combine.startThreshing) |
147 | SpecializationUtil.registerFunction(vehicleType, "stopThreshing", Combine.stopThreshing) |
148 | SpecializationUtil.registerFunction(vehicleType, "setWorkedHectars", Combine.setWorkedHectars) |
149 | SpecializationUtil.registerFunction(vehicleType, "addCutterToCombine", Combine.addCutterToCombine) |
150 | SpecializationUtil.registerFunction(vehicleType, "removeCutterFromCombine", Combine.removeCutterFromCombine) |
151 | SpecializationUtil.registerFunction(vehicleType, "addCutterArea", Combine.addCutterArea) |
152 | SpecializationUtil.registerFunction(vehicleType, "getIsThreshingDuringRain", Combine.getIsThreshingDuringRain) |
153 | SpecializationUtil.registerFunction(vehicleType, "verifyCombine", Combine.verifyCombine) |
154 | SpecializationUtil.registerFunction(vehicleType, "getFillLevelDependentSpeed", Combine.getFillLevelDependentSpeed) |
155 | SpecializationUtil.registerFunction(vehicleType, "getCombineLastValidFillType", Combine.getCombineLastValidFillType) |
156 | SpecializationUtil.registerFunction(vehicleType, "getCombineLoadPercentage", Combine.getCombineLoadPercentage) |
157 | SpecializationUtil.registerFunction(vehicleType, "getIsCutterCompatible", Combine.getIsCutterCompatible) |
158 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
162 | function Combine.registerOverwrittenFunctions(vehicleType) |
163 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeTurnedOn", Combine.getCanBeTurnedOn) |
164 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getTurnedOnNotAllowedWarning", Combine.getTurnedOnNotAllowedWarning) |
165 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAreControlledActionsAllowed", Combine.getAreControlledActionsAllowed) |
166 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsFoldAllowed", Combine.getIsFoldAllowed) |
167 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeSelected", Combine.getCanBeSelected) |
168 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadWorkAreaFromXML", Combine.loadWorkAreaFromXML) |
169 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDirtMultiplier", Combine.getDirtMultiplier) |
170 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getWearMultiplier", Combine.getWearMultiplier) |
171 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadTurnedOnAnimationFromXML", Combine.loadTurnedOnAnimationFromXML) |
172 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsTurnedOnAnimationActive", Combine.getIsTurnedOnAnimationActive) |
173 | end |
removeCutterFromCombine
DescriptionDefinitionremoveCutterFromCombine()Code
1228 | function Combine:removeCutterFromCombine(cutter) |
1229 | local spec = self.spec_combine |
1230 | |
1231 | if spec.attachedCutters[cutter] ~= nil then |
1232 | spec.numAttachedCutters = spec.numAttachedCutters - 1 |
1233 | if spec.numAttachedCutters == 0 then |
1234 | self:setIsTurnedOn(false, true) |
1235 | -- if its a buffered combine -> clear the "invisible" tank on cutter detach |
1236 | if spec.isBufferCombine then |
1237 | local currentFillType = self:getFillUnitFillType(spec.fillUnitIndex) |
1238 | if currentFillType ~= FillType.UNKNOWN then |
1239 | self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, -math.huge, currentFillType, ToolType.UNDEFINED, nil) |
1240 | end |
1241 | end |
1242 | end |
1243 | spec.attachedCutters[cutter] = nil |
1244 | |
1245 | local ladder = self.spec_combine.ladder |
1246 | if ladder.unfoldWhileCutterAttached and ladder.animName ~= nil then |
1247 | local fold = true |
1248 | if self.getFoldAnimTime ~= nil then |
1249 | local foldAnimTime = self:getFoldAnimTime() |
1250 | if foldAnimTime > ladder.foldMaxLimit or foldAnimTime < ladder.foldMinLimit then |
1251 | fold = false |
1252 | end |
1253 | end |
1254 | |
1255 | if fold then |
1256 | self:playAnimation(ladder.animName, -ladder.animSpeedScale, self:getAnimationTime(ladder.animName), true) |
1257 | end |
1258 | end |
1259 | end |
1260 | end |
saveToXMLFile
DescriptionDefinitionsaveToXMLFile()Code
355 | function Combine:saveToXMLFile(xmlFile, key, usedModNames) |
356 | local spec = self.spec_combine |
357 | |
358 | if spec.swath.isAvailable then |
359 | xmlFile:setValue(key.."#isSwathActive", spec.isSwathActive) |
360 | end |
361 | |
362 | xmlFile:setValue(key.."#workedHectars", spec.workedHectars) |
363 | xmlFile:setValue(key.."#numAttachedCutters", spec.numAttachedCutters) |
364 | end |
setChopperPSEnabled
DescriptionSet chopper PS enabledDefinition
setChopperPSEnabled(boolean chopperPSenabled, boolean fruitTypeChanged, float density, boolean isSynchronized)Arguments
boolean | chopperPSenabled | set enabled |
boolean | fruitTypeChanged | fruit type has changed |
float | density | density |
boolean | isSynchronized | filling is synchronized |
1004 | function Combine:setChopperPSEnabled(chopperPSenabled, fruitTypeChanged, density, isSynchronized) |
1005 | local spec = self.spec_combine |
1006 | |
1007 | if spec.chopperPSenabled ~= chopperPSenabled or fruitTypeChanged then |
1008 | spec.chopperPSenabled = chopperPSenabled |
1009 | if self.isServer and isSynchronized then |
1010 | spec.sentChopperPSenabled = chopperPSenabled |
1011 | end |
1012 | |
1013 | if self.isClient then |
1014 | if not chopperPSenabled or fruitTypeChanged then |
1015 | g_effectManager:stopEffects(spec.chopperEffects) |
1016 | end |
1017 | |
1018 | if chopperPSenabled then |
1019 | g_effectManager:setFillType(spec.chopperEffects, self:getCombineLastValidFillType()) |
1020 | g_effectManager:startEffects(spec.chopperEffects) |
1021 | |
1022 | if not g_soundManager:getIsSamplePlaying(spec.samples.chopStraw) then |
1023 | g_soundManager:playSample(spec.samples.chopStraw) |
1024 | end |
1025 | else |
1026 | if g_soundManager:getIsSamplePlaying(spec.samples.chopStraw) then |
1027 | g_soundManager:stopSample(spec.samples.chopStraw) |
1028 | end |
1029 | end |
1030 | end |
1031 | end |
1032 | |
1033 | if spec.chopperPSenabled and density ~= nil then |
1034 | g_effectManager:setDensity(spec.chopperEffects, density) |
1035 | end |
1036 | end |
setCombineIsFilling
DescriptionSet combine is fillingDefinition
setCombineIsFilling(boolean isFilling, boolean fruitTypeChanged, boolean isSynchronized)Arguments
boolean | isFilling | combine is filling |
boolean | fruitTypeChanged | fruit type has changed |
boolean | isSynchronized | filling is synchronized |
1086 | function Combine:setCombineIsFilling(isFilling, fruitTypeChanged, isSynchronized) |
1087 | local spec = self.spec_combine |
1088 | |
1089 | if spec.isFilling ~= isFilling or fruitTypeChanged then |
1090 | spec.isFilling = isFilling |
1091 | |
1092 | if self.isServer and isSynchronized then |
1093 | spec.sentIsFilling = isFilling |
1094 | end |
1095 | |
1096 | if self.isClient then |
1097 | if isFilling then |
1098 | g_animationManager:startAnimations(spec.fillingAnimationNodes) |
1099 | else |
1100 | g_animationManager:stopAnimations(spec.fillingAnimationNodes) |
1101 | end |
1102 | g_animationManager:setFillType(spec.fillingAnimationNodes, self:getCombineLastValidFillType()) |
1103 | |
1104 | g_effectManager:setFillType(spec.effects, self:getCombineLastValidFillType(spec.fillUnitIndex)) |
1105 | |
1106 | if not isFilling or fruitTypeChanged then |
1107 | g_effectManager:stopEffects(spec.fillEffects) |
1108 | end |
1109 | |
1110 | if isFilling then |
1111 | g_effectManager:setFillType(spec.fillEffects, self:getCombineLastValidFillType()) |
1112 | g_effectManager:startEffects(spec.fillEffects) |
1113 | end |
1114 | |
1115 | if isFilling then |
1116 | if not g_soundManager:getIsSamplePlaying(spec.samples.fill) then |
1117 | g_soundManager:playSample(spec.samples.fill) |
1118 | end |
1119 | else |
1120 | if g_soundManager:getIsSamplePlaying(spec.samples.fill) then |
1121 | g_soundManager:stopSample(spec.samples.fill) |
1122 | end |
1123 | end |
1124 | end |
1125 | end |
1126 | end |
setIsSwathActive
DescriptionSet is straw enabledDefinition
setIsSwathActive(boolean isSwathActive, boolean noEventSend, boolean force)Arguments
boolean | isSwathActive | new state |
boolean | noEventSend | no event send |
boolean | force | force action |
889 | function Combine:setIsSwathActive(isSwathActive, noEventSend, force) |
890 | local spec = self.spec_combine |
891 | |
892 | if isSwathActive ~= spec.isSwathActive or force then |
893 | CombineStrawEnableEvent.sendEvent(self, isSwathActive, noEventSend) |
894 | spec.isSwathActive = isSwathActive |
895 | |
896 | local anim = spec.chopper.animName |
897 | if self.playAnimation ~= nil and anim ~= nil then |
898 | local dir = 1 |
899 | if isSwathActive then |
900 | dir = -1 |
901 | end |
902 | self:playAnimation(anim, dir * spec.chopper.animSpeedScale, self:getAnimationTime(anim), true) |
903 | |
904 | if force then |
905 | AnimatedVehicle.updateAnimationByName(self, anim, 9999999, true) |
906 | end |
907 | end |
908 | |
909 | -- reset buffer drop slots (may still be some liters that could not be dropped to swath, but then can be chopped) |
910 | local inputBuffer = spec.processing.inputBuffer |
911 | for i=1, #inputBuffer.buffer do |
912 | inputBuffer.buffer[i].liters = 0 |
913 | end |
914 | |
915 | if self:getIsTurnedOn() then |
916 | if self.isClient then |
917 | if spec.isSwathActive then |
918 | g_animationManager:stopAnimations(spec.chopperAnimationNodes) |
919 | g_animationManager:startAnimations(spec.strawDropAnimationNodes) |
920 | |
921 | if g_soundManager:getIsSamplePlaying(spec.samples.chopperWork) then |
922 | g_soundManager:stopSample(spec.samples.chopperWork) |
923 | g_soundManager:playSample(spec.samples.chopperStop) |
924 | end |
925 | else |
926 | g_animationManager:stopAnimations(spec.strawDropAnimationNodes) |
927 | g_animationManager:startAnimations(spec.chopperAnimationNodes) |
928 | |
929 | g_soundManager:stopSample(spec.samples.chopperStop) |
930 | g_soundManager:playSample(spec.samples.chopperStart) |
931 | g_soundManager:playSample(spec.samples.chopperWork, 0, spec.samples.chopperStart) |
932 | end |
933 | end |
934 | end |
935 | |
936 | Combine.updateToggleStrawText(self) |
937 | end |
938 | end |
setStrawPSEnabled
DescriptionSet straw PS enabledDefinition
setStrawPSEnabled(boolean strawPSenabled, boolean fruitTypeChanged, float density, boolean isSynchronized)Arguments
boolean | strawPSenabled | set enabled |
boolean | fruitTypeChanged | fruit type has changed |
float | density | density |
boolean | isSynchronized | filling is synchronized |
1044 | function Combine:setStrawPSEnabled(strawPSenabled, fruitTypeChanged, density, isSynchronized) |
1045 | local spec = self.spec_combine |
1046 | |
1047 | if spec.strawPSenabled ~= strawPSenabled or fruitTypeChanged then |
1048 | spec.strawPSenabled = strawPSenabled |
1049 | if self.isServer and isSynchronized then |
1050 | spec.sentStrawPSenabled = strawPSenabled |
1051 | end |
1052 | if not strawPSenabled then |
1053 | spec.strawToDrop = 0 |
1054 | end |
1055 | |
1056 | if self.isClient then |
1057 | if not strawPSenabled or fruitTypeChanged then |
1058 | g_effectManager:stopEffects(spec.strawEffects) |
1059 | end |
1060 | |
1061 | if strawPSenabled then |
1062 | g_effectManager:setFillType(spec.strawEffects, self:getCombineLastValidFillType()) |
1063 | g_effectManager:startEffects(spec.strawEffects) |
1064 | |
1065 | if not g_soundManager:getIsSamplePlaying(spec.samples.dropStraw) then |
1066 | g_soundManager:playSample(spec.samples.dropStraw) |
1067 | end |
1068 | else |
1069 | if g_soundManager:getIsSamplePlaying(spec.samples.dropStraw) then |
1070 | g_soundManager:stopSample(spec.samples.dropStraw) |
1071 | end |
1072 | end |
1073 | end |
1074 | end |
1075 | |
1076 | if spec.strawPSenabled and density ~= nil then |
1077 | g_effectManager:setDensity(spec.strawEffects, density) |
1078 | end |
1079 | end |
setWorkedHectars
DescriptionSet worked hectars value and updated hudDefinition
setWorkedHectars(float hectars)Arguments
float | hectars | new hectars value |
1195 | function Combine:setWorkedHectars(hectars) |
1196 | local spec = self.spec_combine |
1197 | |
1198 | spec.workedHectars = hectars |
1199 | |
1200 | if self.isServer then |
1201 | if math.abs(spec.workedHectars-spec.workedHectarsSent) > 0.01 then |
1202 | self:raiseDirtyFlags(spec.dirtyFlag) |
1203 | spec.workedHectarsSent = spec.workedHectars |
1204 | end |
1205 | end |
1206 | end |
startThreshing
DescriptionStart threshingDefinition
startThreshing()Code
1130 | function Combine:startThreshing() |
1131 | local spec = self.spec_combine |
1132 | |
1133 | if spec.numAttachedCutters > 0 then |
1134 | -- do not lower the cutter if the combine is turned on during headland (happens if ai was blocked during headland) |
1135 | local allowLowering = not self:getIsAIActive() or not self.rootVehicle:getAIFieldWorkerIsTurning() |
1136 | |
1137 | for _,cutter in pairs(spec.attachedCutters) do |
1138 | if allowLowering then |
1139 | if cutter ~= self then |
1140 | local jointDescIndex = self:getAttacherJointIndexFromObject(cutter) |
1141 | self:setJointMoveDown(jointDescIndex, true, true) |
1142 | end |
1143 | end |
1144 | |
1145 | cutter:setIsTurnedOn(true, true) |
1146 | end |
1147 | |
1148 | if spec.threshingStartAnimation ~= nil and self.playAnimation ~= nil then |
1149 | self:playAnimation(spec.threshingStartAnimation, spec.threshingStartAnimationSpeedScale, self:getAnimationTime(spec.threshingStartAnimation), true) |
1150 | end |
1151 | |
1152 | if self.isClient then |
1153 | g_soundManager:stopSample(spec.samples.stop) |
1154 | g_soundManager:stopSample(spec.samples.work) |
1155 | g_soundManager:playSample(spec.samples.start) |
1156 | g_soundManager:playSample(spec.samples.work, 0, spec.samples.start) |
1157 | end |
1158 | |
1159 | SpecializationUtil.raiseEvent(self, "onStartThreshing") |
1160 | end |
1161 | end |
stopThreshing
DescriptionStop threshingDefinition
stopThreshing()Code
1165 | function Combine:stopThreshing() |
1166 | local spec = self.spec_combine |
1167 | |
1168 | if self.isClient then |
1169 | g_soundManager:stopSample(spec.samples.start) |
1170 | g_soundManager:stopSample(spec.samples.work) |
1171 | g_soundManager:playSample(spec.samples.stop) |
1172 | end |
1173 | |
1174 | self:setCombineIsFilling(false, false, true) |
1175 | |
1176 | for cutter,_ in pairs(spec.attachedCutters) do |
1177 | if cutter ~= self then |
1178 | local jointDescIndex = self:getAttacherJointIndexFromObject(cutter) |
1179 | self:setJointMoveDown(jointDescIndex, false, true) |
1180 | end |
1181 | |
1182 | cutter:setIsTurnedOn(false, true) |
1183 | end |
1184 | |
1185 | if spec.threshingStartAnimation ~= nil and spec.playAnimation ~= nil then |
1186 | self:playAnimation(spec.threshingStartAnimation, -spec.threshingStartAnimationSpeedScale, self:getAnimationTime(spec.threshingStartAnimation), true) |
1187 | end |
1188 | |
1189 | SpecializationUtil.raiseEvent(self, "onStopThreshing") |
1190 | end |
updateToggleStrawText
DescriptionDefinitionupdateToggleStrawText()Code
1971 | function Combine.updateToggleStrawText(self) |
1972 | local spec = self.spec_combine |
1973 | local actionEvent = spec.actionEvents[InputAction.TOGGLE_CHOPPER] |
1974 | if actionEvent ~= nil and actionEvent.actionEventId ~= nil then |
1975 | local text |
1976 | if spec.isSwathActive then |
1977 | text = g_i18n:getText("action_disableStrawSwath") |
1978 | else |
1979 | text = g_i18n:getText("action_enableStrawSwath") |
1980 | end |
1981 | |
1982 | g_inputBinding:setActionEventText(actionEvent.actionEventId, text) |
1983 | end |
1984 | end |
verifyCombine
DescriptionDefinitionverifyCombine()Code
1423 | function Combine:verifyCombine(fruitType, outputFillType) |
1424 | local spec = self.spec_combine |
1425 | local fillUnitIndex = spec.bufferFillUnitIndex or spec.fillUnitIndex |
1426 | -- buffer combine can never be over the limit since the capacity is math.huge |
1427 | if self:getFillUnitFillLevelPercentage(fillUnitIndex) > self:getFillTypeChangeThreshold() or spec.isBufferCombine then |
1428 | local currentFillType = self:getFillUnitFillType(fillUnitIndex) |
1429 | if currentFillType ~= FillType.UNKNOWN and fruitType ~= FruitType.UNKNOWN and currentFillType ~= outputFillType then |
1430 | -- if we are a combine harvester without a "real" fill unit we empty the buffer if a new fill type comes from the cutter |
1431 | if spec.isBufferCombine then |
1432 | self:addFillUnitFillLevel(self:getOwnerFarmId(), fillUnitIndex, -math.huge, currentFillType, ToolType.UNDEFINED, nil) |
1433 | return self |
1434 | end |
1435 | |
1436 | return nil, self, currentFillType |
1437 | end |
1438 | end |
1439 | |
1440 | local maxFreeCapacity = 0 |
1441 | if spec.bufferFillUnitIndex ~= nil then |
1442 | maxFreeCapacity = self:getFillUnitFillLevel(spec.bufferFillUnitIndex) |
1443 | end |
1444 | if self:getFillUnitFreeCapacity(spec.fillUnitIndex) <= maxFreeCapacity then |
1445 | return nil |
1446 | end |
1447 | |
1448 | return self |
1449 | end |