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
MixerWagon
DescriptionSpecialization for forage mixer wagons creating forage from bales, chaff, straw and/or hayFunctions
- addFillUnitFillLevel
- getDischargeFillType
- getFillUnitAllowsFillType
- getIsPlayerInTrigger
- initSpecialization
- mixerWagonBaleTriggerCallback
- onDelete
- onFillUnitFillLevelChanged
- onHUDTriggerCallback
- onLoad
- onPostLoad
- onReadStream
- onReadUpdateStream
- onTurnedOff
- onTurnedOn
- onUpdate
- onWriteStream
- onWriteUpdateStream
- prerequisitesPresent
- registerEventListeners
- registerFunctions
- registerOverwrittenFunctions
- saveToXMLFile
- updateDebugValues
addFillUnitFillLevel
DescriptionDefinitionaddFillUnitFillLevel()Code
434 | function MixerWagon:addFillUnitFillLevel(superFunc, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData) |
435 | local spec = self.spec_mixerWagon |
436 | |
437 | if fillUnitIndex ~= spec.fillUnitIndex then |
438 | return superFunc(self, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData) |
439 | end |
440 | |
441 | local oldFillLevel = self:getFillUnitFillLevel(fillUnitIndex) |
442 | |
443 | local mixerWagonFillType = spec.fillTypeToMixerWagonFillType[fillTypeIndex] |
444 | |
445 | -- allow to put forage back to mixer. Split it up into valid forage mixing ratios |
446 | if fillTypeIndex == FillType.FORAGE and fillLevelDelta > 0 then |
447 | for _, entry in pairs(spec.mixerWagonFillTypes) do |
448 | local delta = fillLevelDelta * entry.ratio |
449 | self:addFillUnitFillLevel(farmId, fillUnitIndex, delta, next(entry.fillTypes), toolType, fillPositionData) |
450 | end |
451 | |
452 | return fillLevelDelta |
453 | end |
454 | |
455 | if mixerWagonFillType == nil then |
456 | -- used for discharge |
457 | if fillLevelDelta < 0 and oldFillLevel > 0 then |
458 | -- remove values from all fill types such that the ratio doesn't change |
459 | fillLevelDelta = math.max(fillLevelDelta, -oldFillLevel) |
460 | |
461 | local newFillLevel = 0 |
462 | for _, entry in pairs(spec.mixerWagonFillTypes) do |
463 | local entryDelta = fillLevelDelta * (entry.fillLevel / oldFillLevel) |
464 | entry.fillLevel = math.max(entry.fillLevel + entryDelta, 0) |
465 | newFillLevel = newFillLevel + entry.fillLevel |
466 | end |
467 | |
468 | if newFillLevel < 0.1 then |
469 | for _, entry in pairs(spec.mixerWagonFillTypes) do |
470 | entry.fillLevel = 0 |
471 | end |
472 | fillLevelDelta = -oldFillLevel |
473 | end |
474 | |
475 | self:raiseDirtyFlags(spec.dirtyFlag) |
476 | local ret = superFunc(self, farmId, fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData) |
477 | return ret |
478 | end |
479 | |
480 | return 0 |
481 | end |
482 | |
483 | local capacity = self:getFillUnitCapacity(fillUnitIndex) |
484 | local free = capacity - oldFillLevel |
485 | |
486 | if fillLevelDelta > 0 then |
487 | mixerWagonFillType.fillLevel = mixerWagonFillType.fillLevel + math.min(free, fillLevelDelta) |
488 | if self:getIsSynchronized() then |
489 | spec.activeTimer = spec.activeTimerMax |
490 | end |
491 | else |
492 | mixerWagonFillType.fillLevel = math.max(0, mixerWagonFillType.fillLevel + fillLevelDelta) |
493 | end |
494 | |
495 | local newFillLevel = 0 |
496 | for _, fillType in pairs(spec.mixerWagonFillTypes) do |
497 | newFillLevel = newFillLevel + fillType.fillLevel |
498 | end |
499 | newFillLevel = MathUtil.clamp(newFillLevel, 0, self:getFillUnitCapacity(fillUnitIndex)) |
500 | |
501 | local newFillType = FillType.UNKNOWN |
502 | local isSingleFilled = false |
503 | local isForageOk = false |
504 | |
505 | for _, fillType in pairs(spec.mixerWagonFillTypes) do |
506 | if newFillLevel == fillType.fillLevel then |
507 | isSingleFilled = true |
508 | newFillType = next(mixerWagonFillType.fillTypes) |
509 | break |
510 | end |
511 | end |
512 | |
513 | if not isSingleFilled then |
514 | isForageOk = true |
515 | for _, fillType in pairs(spec.mixerWagonFillTypes) do |
516 | if fillType.fillLevel < fillType.minPercentage * newFillLevel - 0.01 or fillType.fillLevel > fillType.maxPercentage * newFillLevel + 0.01 then |
517 | isForageOk = false |
518 | break |
519 | end |
520 | end |
521 | end |
522 | |
523 | if isForageOk then |
524 | newFillType = FillType.FORAGE |
525 | elseif not isSingleFilled then |
526 | newFillType = FillType.FORAGE_MIXING |
527 | end |
528 | |
529 | self:raiseDirtyFlags(spec.dirtyFlag) |
530 | |
531 | self:setFillUnitFillType(fillUnitIndex, newFillType) |
532 | |
533 | return superFunc(self, farmId, fillUnitIndex, newFillLevel-oldFillLevel, newFillType, toolType, fillPositionData) |
534 | end |
getDischargeFillType
DescriptionDefinitiongetDischargeFillType()Code
553 | function MixerWagon:getDischargeFillType(superFunc, dischargeNode) |
554 | local spec = self.spec_mixerWagon |
555 | local fillUnitIndex = dischargeNode.fillUnitIndex |
556 | |
557 | if fillUnitIndex == spec.fillUnitIndex then |
558 | local currentFillType = self:getFillUnitFillType(fillUnitIndex) |
559 | local fillLevel = self:getFillUnitFillLevel(fillUnitIndex) |
560 | |
561 | if currentFillType == FillType.FORAGE_MIXING and fillLevel > 0 then |
562 | for _, entry in pairs(spec.mixerWagonFillTypes) do |
563 | if entry.fillLevel > 0 then |
564 | currentFillType = next(entry.fillTypes) |
565 | break |
566 | end |
567 | end |
568 | end |
569 | |
570 | return currentFillType, 1 |
571 | end |
572 | |
573 | return superFunc(self, dischargeNode) |
574 | end |
getFillUnitAllowsFillType
DescriptionDefinitiongetFillUnitAllowsFillType()Code
538 | function MixerWagon:getFillUnitAllowsFillType(superFunc, fillUnitIndex, fillTypeIndex) |
539 | local spec = self.spec_mixerWagon |
540 | |
541 | if spec.fillUnitIndex == fillUnitIndex then |
542 | local mixerWagonFillType = spec.fillTypeToMixerWagonFillType[fillTypeIndex] |
543 | if mixerWagonFillType ~= nil then |
544 | return true |
545 | end |
546 | end |
547 | |
548 | return superFunc(self, fillUnitIndex, fillTypeIndex) |
549 | end |
getIsPlayerInTrigger
DescriptionGet if current player is in the HUD trigger as character or with a vehicleDefinition
getIsPlayerInTrigger()Code
645 | function MixerWagon:getIsPlayerInTrigger() |
646 | local spec = self.spec_mixerWagon |
647 | |
648 | if g_currentMission.controlPlayer and g_currentMission.player ~= nil then |
649 | return spec.vehicleToNodeCount[g_currentMission.player.rootNode] ~= nil |
650 | elseif g_currentMission.controlledVehicle ~= nil then |
651 | return spec.vehicleToNodeCount[g_currentMission.controlledVehicle] ~= nil |
652 | end |
653 | |
654 | return false |
655 | end |
initSpecialization
DescriptionDefinitioninitSpecialization()Code
29 | function MixerWagon.initSpecialization() |
30 | local schema = Vehicle.xmlSchema |
31 | schema:setXMLSpecializationType("MixerWagon") |
32 | |
33 | AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.mixerWagon.mixAnimationNodes") |
34 | AnimationManager.registerAnimationNodesXMLPaths(schema, "vehicle.mixerWagon.pickupAnimationNodes") |
35 | |
36 | schema:register(XMLValueType.NODE_INDEX, "vehicle.mixerWagon.baleTriggers.baleTrigger(?)#node", "Bale trigger node") |
37 | schema:register(XMLValueType.FLOAT, "vehicle.mixerWagon.baleTriggers.baleTrigger(?)#pickupSpeed", "Bale pickup speed in liter per second", 500) |
38 | schema:register(XMLValueType.BOOL, "vehicle.mixerWagon.baleTriggers.baleTrigger(?)#needsSetIsTurnedOn", "Vehicle needs to be turned on to pickup bales with this trigger", false) |
39 | schema:register(XMLValueType.BOOL, "vehicle.mixerWagon.baleTriggers.baleTrigger(?)#useEffect", "Filling effect is played while picking up a bale", false) |
40 | |
41 | schema:register(XMLValueType.TIME, "vehicle.mixerWagon#mixingTime", "Mixing time after the fill level was changed", 5) |
42 | schema:register(XMLValueType.INT, "vehicle.mixerWagon#fillUnitIndex", "Fill unit index", 1) |
43 | schema:register(XMLValueType.STRING, "vehicle.mixerWagon#recipe", "Recipe fill type name", "Forage") |
44 | |
45 | EffectManager.registerEffectXMLPaths(schema, "vehicle.mixerWagon.fillEffect") |
46 | |
47 | schema:setXMLSpecializationType() |
48 | |
49 | local schemaSavegame = Vehicle.xmlSchemaSavegame |
50 | schemaSavegame:register(XMLValueType.FLOAT, "vehicles.vehicle(?).mixerWagon.fillType(?)#fillLevel", "Fill level", 0) |
51 | end |
mixerWagonBaleTriggerCallback
DescriptionTrigger callbackDefinition
mixerWagonBaleTriggerCallback(integer triggerId, integer otherActorId, boolean onEnter, boolean onLeave, boolean onStay, integer otherShapeId)Arguments
integer | triggerId | id of trigger |
integer | otherActorId | id of other actor |
boolean | onEnter | on enter |
boolean | onLeave | on leave |
boolean | onStay | on stay |
integer | otherShapeId | id of other shape |
400 | function MixerWagon:mixerWagonBaleTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
401 | -- this happens if a compound child of a deleted compound is entering |
402 | if otherActorId ~= 0 then |
403 | local bale = g_currentMission:getNodeObject(otherActorId) |
404 | if bale ~= nil then |
405 | if bale:isa(Bale) then |
406 | local spec = self.spec_mixerWagon |
407 | |
408 | if self:getFillUnitSupportsFillType(spec.fillUnitIndex, bale:getFillType()) then |
409 | for i=1, #spec.baleTriggers do |
410 | local baleTrigger = spec.baleTriggers[i] |
411 | if baleTrigger.node == triggerId then |
412 | if onEnter then |
413 | baleTrigger.balesInTrigger[bale] = (baleTrigger.balesInTrigger[bale] or 0) + 1 |
414 | elseif onLeave then |
415 | baleTrigger.balesInTrigger[bale] = (baleTrigger.balesInTrigger[bale] or 1) - 1 |
416 | if baleTrigger.balesInTrigger[bale] == 0 then |
417 | baleTrigger.balesInTrigger[bale] = nil |
418 | end |
419 | end |
420 | end |
421 | end |
422 | else |
423 | if onEnter and otherActorId == bale.nodeId then |
424 | g_currentMission:broadcastEventToFarm(MixerWagonBaleNotAcceptedEvent.new(), self:getOwnerFarmId(), true) |
425 | end |
426 | end |
427 | end |
428 | end |
429 | end |
430 | end |
onDelete
DescriptionCalled on deletingDefinition
onDelete()Code
213 | function MixerWagon:onDelete() |
214 | local spec = self.spec_mixerWagon |
215 | if spec.baleTriggers ~= nil then |
216 | for i=1, #spec.baleTriggers do |
217 | removeTrigger(spec.baleTriggers[i].node) |
218 | end |
219 | end |
220 | |
221 | g_animationManager:deleteAnimations(spec.mixAnimationNodes) |
222 | g_animationManager:deleteAnimations(spec.pickupAnimationNodes) |
223 | g_effectManager:deleteEffects(spec.fillEffects) |
224 | |
225 | if spec.hudTrigger ~= nil then |
226 | removeTrigger(spec.hudTrigger) |
227 | g_i3DManager:releaseSharedI3DFile(spec.hudTriggerSharedLoadRequestId) |
228 | end |
229 | end |
onFillUnitFillLevelChanged
DescriptionDefinitiononFillUnitFillLevelChanged()Code
579 | function MixerWagon:onFillUnitFillLevelChanged(fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionData, appliedDelta) |
580 | local spec = self.spec_mixerWagon |
581 | |
582 | if spec.fillUnitIndex == fillUnitIndex then |
583 | local fillLevel = self:getFillUnitFillLevel(fillUnitIndex) |
584 | if fillLevel == 0 then |
585 | for _, entry in pairs(spec.mixerWagonFillTypes) do |
586 | entry.fillLevel = 0 |
587 | end |
588 | end |
589 | end |
590 | end |
onHUDTriggerCallback
DescriptionTrigger callback function adding mixer wagon hud extension to UI if player or vehicle is near the mixer wagonDefinition
onHUDTriggerCallback()Code
612 | function MixerWagon:onHUDTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
613 | local object = g_currentMission.nodeToObject[otherActorId] |
614 | if object ~= nil and object:isa(Vehicle) and not SpecializationUtil.hasSpecialization(Enterable, object.specializations) then |
615 | -- only enterable vehicles are relevant |
616 | return |
617 | elseif g_currentMission.player ~= nil and otherActorId == g_currentMission.player.rootNode then |
618 | object = g_currentMission.player.rootNode |
619 | end |
620 | |
621 | if object ~= nil and object ~= self then -- exclude mixer wagon from triggering on himself |
622 | local spec = self.spec_mixerWagon |
623 | if onEnter then |
624 | if not g_currentMission.accessHandler:canPlayerAccess(self) then |
625 | return |
626 | end |
627 | -- count number of nodes per vehicle inside trigger |
628 | spec.vehicleToNodeCount[object] = (spec.vehicleToNodeCount[object] or 0) + 1 |
629 | elseif onLeave then |
630 | spec.vehicleToNodeCount[object] = (spec.vehicleToNodeCount[object] or 0) - 1 |
631 | end |
632 | |
633 | if spec.vehicleToNodeCount[object] == 1 then |
634 | -- only add once on inital node enter |
635 | g_currentMission.hud.inputHelp:addExtraExtensionVehicleNodeId(self.rootNode) |
636 | elseif spec.vehicleToNodeCount[object] <= 0 then |
637 | g_currentMission.hud.inputHelp:removeExtraExtensionVehicleNodeId(self.rootNode) |
638 | spec.vehicleToNodeCount[object] = nil |
639 | end |
640 | end |
641 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
88 | function MixerWagon:onLoad(savegame) |
89 | |
90 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagonBaleTrigger#index", "vehicle.mixerWagon.baleTrigger#node") --FS17 to FS19 |
91 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagon.baleTrigger#index", "vehicle.mixerWagon.baleTrigger#node") --FS19 to FS19 |
92 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagonPickupStartSound", "vehicle.turnOnVehicle.sounds.start") --FS17 to FS19 |
93 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagonPickupStopSound", "vehicle.turnOnVehicle.sounds.stop") --FS17 to FS19 |
94 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagonPickupSound", "vehicle.turnOnVehicle.sounds.work") --FS17 to FS19 |
95 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagonRotatingParts.mixerWagonRotatingPart#type", "vehicle.mixerWagon.mixAnimationNodes.animationNode", "mixerWagonMix") --FS17 to FS19 |
96 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagonRotatingParts.mixerWagonRotatingPart#type", "vehicle.mixerWagon.pickupAnimationNodes.animationNode", "mixerWagonPickup") --FS17 to FS19 |
97 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagonRotatingParts.mixerWagonScroller", "vehicle.mixerWagon.pickupAnimationNodes.pickupAnimationNode") --FS17 to FS19 |
98 | |
99 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.mixerWagon.baleTrigger#node", "vehicle.mixerWagon.baleTriggers.baleTrigger#node") --FS19 to FS22 |
100 | |
101 | local spec = self.spec_mixerWagon |
102 | |
103 | if self.isClient then |
104 | spec.mixAnimationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.mixerWagon.mixAnimationNodes", self.components, self, self.i3dMappings) |
105 | spec.pickupAnimationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.mixerWagon.pickupAnimationNodes", self.components, self, self.i3dMappings) |
106 | |
107 | spec.fillEffects = g_effectManager:loadEffect(self.xmlFile, "vehicle.mixerWagon.fillEffect", self.components, self, self.i3dMappings) |
108 | spec.fillEffectsFillType = FillType.UNKNOWN |
109 | spec.fillEffectsState = false |
110 | end |
111 | |
112 | if self.isServer then |
113 | spec.baleTriggers = {} |
114 | self.xmlFile:iterate("vehicle.mixerWagon.baleTriggers.baleTrigger", function(_, key) |
115 | local baleTrigger = {} |
116 | baleTrigger.node = self.xmlFile:getValue(key .. "#node", nil, self.components, self.i3dMappings) |
117 | if baleTrigger.node ~= nil then |
118 | addTrigger(baleTrigger.node, "mixerWagonBaleTriggerCallback", self) |
119 | |
120 | baleTrigger.pickupSpeed = self.xmlFile:getValue(key .. "#pickupSpeed", 500) / 1000 |
121 | baleTrigger.needsSetIsTurnedOn = self.xmlFile:getValue(key .. "#needsSetIsTurnedOn", false) |
122 | baleTrigger.useEffect = self.xmlFile:getValue(key .. "#useEffect", false) |
123 | baleTrigger.balesInTrigger = {} |
124 | table.insert(spec.baleTriggers, baleTrigger) |
125 | end |
126 | end) |
127 | end |
128 | |
129 | spec.activeTimerMax = self.xmlFile:getValue("vehicle.mixerWagon#mixingTime", 5) |
130 | spec.activeTimer = 0 |
131 | |
132 | spec.fillUnitIndex = self.xmlFile:getValue("vehicle.mixerWagon#fillUnitIndex", 1) |
133 | |
134 | -- remove grass_windrow from fillTypes, we do not want to support grass in mixer wagons becasue this would make hay "useless" |
135 | local fillUnit = self:getFillUnitByIndex(spec.fillUnitIndex) |
136 | if fillUnit ~= nil then |
137 | fillUnit.needsSaving = false |
138 | if fillUnit.supportedFillTypes[FillType.GRASS_WINDROW] then |
139 | fillUnit.supportedFillTypes[FillType.GRASS_WINDROW] = nil |
140 | end |
141 | end |
142 | |
143 | -- disable sync of fillLevels for fillUnit - will be handled by mixerWagon |
144 | fillUnit.synchronizeFillLevel = false |
145 | |
146 | spec.mixerWagonFillTypes = {} |
147 | spec.fillTypeToMixerWagonFillType = {} |
148 | |
149 | local recipeFillTypeName = self.xmlFile:getValue("vehicle.mixerWagon#recipe", "") |
150 | local recipeFillTypeIndex = g_fillTypeManager:getFillTypeIndexByName(recipeFillTypeName) |
151 | if recipeFillTypeIndex == nil then |
152 | Logging.xmlError(self.xmlFile, "MixerWagon recipe '%s' not defined!", recipeFillTypeName) |
153 | end |
154 | |
155 | local recipe = g_currentMission.animalFoodSystem:getRecipeByFillTypeIndex(recipeFillTypeIndex) |
156 | if recipe == nil then |
157 | Logging.xmlWarning(self.xmlFile, "MixerWagon recipe '%s' not defined!", recipeFillTypeName) |
158 | end |
159 | |
160 | if recipe ~= nil then |
161 | for _, ingredient in ipairs(recipe.ingredients) do |
162 | local entry = {} |
163 | entry.fillLevel = 0 |
164 | entry.fillTypes = {} |
165 | entry.name = ingredient.name |
166 | entry.minPercentage = ingredient.minPercentage |
167 | entry.maxPercentage = ingredient.maxPercentage |
168 | entry.ratio = ingredient.ratio |
169 | |
170 | for _, fillTypeIndex in ipairs(ingredient.fillTypes) do |
171 | entry.fillTypes[fillTypeIndex] = true |
172 | spec.fillTypeToMixerWagonFillType[fillTypeIndex] = entry |
173 | end |
174 | |
175 | table.insert(spec.mixerWagonFillTypes, entry) |
176 | end |
177 | end |
178 | |
179 | -- load in a trigger for displaying mixer wagon HUDExtension if player is near |
180 | local hudTriggerI3d, hudTriggerSharedLoadRequestId = g_i3DManager:loadSharedI3DFile(MixerWagon.HUD_TRIGGER_I3D_FILENAME, false, false) |
181 | if hudTriggerI3d ~= 0 then |
182 | spec.hudTrigger = getChildAt(hudTriggerI3d, 0) |
183 | spec.hudTriggerSharedLoadRequestId = hudTriggerSharedLoadRequestId |
184 | link(self.rootNode, spec.hudTrigger) |
185 | addTrigger(spec.hudTrigger, "onHUDTriggerCallback", self) |
186 | delete(hudTriggerI3d) |
187 | spec.vehicleToNodeCount = {} |
188 | end |
189 | |
190 | spec.dirtyFlag = self:getNextDirtyFlag() |
191 | spec.effectDirtyFlag = self:getNextDirtyFlag() |
192 | end |
onPostLoad
DescriptionCalled after loadingDefinition
onPostLoad(table savegame)Arguments
table | savegame | savegame |
197 | function MixerWagon:onPostLoad(savegame) |
198 | if savegame ~= nil then |
199 | local spec = self.spec_mixerWagon |
200 | for i, entry in ipairs(spec.mixerWagonFillTypes) do |
201 | local fillTypeKey = savegame.key..string.format(".mixerWagon.fillType(%d)#fillLevel", i-1) |
202 | local fillLevel = savegame.xmlFile:getValue(fillTypeKey, 0) |
203 | |
204 | if fillLevel > 0 then |
205 | self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, fillLevel, next(entry.fillTypes), ToolType.UNDEFINED, nil) |
206 | end |
207 | end |
208 | end |
209 | end |
onReadStream
DescriptionCalled on client side on joinDefinition
onReadStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
246 | function MixerWagon:onReadStream(streamId, connection) |
247 | local spec = self.spec_mixerWagon |
248 | for _, entry in ipairs(spec.mixerWagonFillTypes) do |
249 | local fillLevel = streamReadFloat32(streamId) |
250 | if fillLevel > 0 then |
251 | self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, fillLevel, next(entry.fillTypes), ToolType.UNDEFINED, nil) |
252 | end |
253 | end |
254 | |
255 | spec.fillEffectsFillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS) |
256 | end |
onReadUpdateStream
DescriptionCalled on on updateDefinition
onReadUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | stream ID |
integer | timestamp | timestamp |
table | connection | connection |
276 | function MixerWagon:onReadUpdateStream(streamId, timestamp, connection) |
277 | if connection:getIsServer() then |
278 | local spec = self.spec_mixerWagon |
279 | if streamReadBool(streamId) then |
280 | for _, entry in ipairs(spec.mixerWagonFillTypes) do |
281 | local fillLevel = streamReadFloat32(streamId) |
282 | local delta = fillLevel - entry.fillLevel |
283 | if delta ~= 0 then |
284 | self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, delta, next(entry.fillTypes), ToolType.UNDEFINED, nil) |
285 | end |
286 | end |
287 | end |
288 | |
289 | if streamReadBool(streamId) then |
290 | spec.fillEffectsFillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS) |
291 | end |
292 | end |
293 | end |
onTurnedOff
DescriptionDefinitiononTurnedOff()Code
603 | function MixerWagon:onTurnedOff() |
604 | if self.isClient then |
605 | local spec = self.spec_mixerWagon |
606 | g_animationManager:stopAnimations(spec.pickupAnimationNodes) |
607 | end |
608 | end |
onTurnedOn
DescriptionDefinitiononTurnedOn()Code
594 | function MixerWagon:onTurnedOn() |
595 | if self.isClient then |
596 | local spec = self.spec_mixerWagon |
597 | g_animationManager:startAnimations(spec.pickupAnimationNodes) |
598 | end |
599 | 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 |
320 | function MixerWagon:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
321 | local spec = self.spec_mixerWagon |
322 | |
323 | local tipState = self:getTipState() |
324 | local isTurnedOn = self:getIsTurnedOn() |
325 | local isDischarging = tipState == Trailer.TIPSTATE_OPENING or tipState == Trailer.TIPSTATE_OPEN |
326 | |
327 | if self:getIsPowered() and (spec.activeTimer > 0 or isTurnedOn or isDischarging) then |
328 | spec.activeTimer = spec.activeTimer - dt |
329 | g_animationManager:startAnimations(spec.mixAnimationNodes) |
330 | else |
331 | g_animationManager:stopAnimations(spec.mixAnimationNodes) |
332 | end |
333 | |
334 | if self.isServer then |
335 | local fillEffectsFillType = FillType.UNKNOWN |
336 | if self:getFillUnitFreeCapacity(spec.fillUnitIndex) > 0 then |
337 | for i=1, #spec.baleTriggers do |
338 | local baleTrigger = spec.baleTriggers[i] |
339 | if not baleTrigger.needsSetIsTurnedOn or self:getIsTurnedOn() then |
340 | for bale, _ in pairs(baleTrigger.balesInTrigger) do |
341 | local baleFillLevel = bale:getFillLevel() |
342 | local deltaFillLevel = math.min(baleTrigger.pickupSpeed * dt, baleFillLevel) |
343 | local fillType = bale:getFillType() |
344 | |
345 | deltaFillLevel = self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, deltaFillLevel, fillType, ToolType.BALE, nil) |
346 | |
347 | baleFillLevel = baleFillLevel - deltaFillLevel |
348 | bale:setFillLevel(baleFillLevel) |
349 | if baleFillLevel < 0.01 then |
350 | bale:delete() |
351 | baleTrigger.balesInTrigger[bale] = nil |
352 | end |
353 | |
354 | if baleTrigger.useEffect then |
355 | fillEffectsFillType = fillType |
356 | end |
357 | end |
358 | end |
359 | end |
360 | end |
361 | |
362 | if fillEffectsFillType == FillType.UNKNOWN then |
363 | if self.getIsShovelEffectState ~= nil then |
364 | local state, fillType = self:getIsShovelEffectState() |
365 | if state then |
366 | fillEffectsFillType = fillType |
367 | end |
368 | end |
369 | end |
370 | |
371 | if spec.fillEffectsFillType ~= fillEffectsFillType then |
372 | spec.fillEffectsFillType = fillEffectsFillType |
373 | self:raiseDirtyFlags(spec.effectDirtyFlag) |
374 | end |
375 | end |
376 | |
377 | if self.isClient then |
378 | local state = spec.fillEffectsFillType ~= FillType.UNKNOWN |
379 | if state ~= spec.fillEffectsState then |
380 | if state then |
381 | g_effectManager:setFillType(spec.fillEffects, spec.fillEffectsFillType) |
382 | g_effectManager:startEffects(spec.fillEffects) |
383 | else |
384 | g_effectManager:stopEffects(spec.fillEffects) |
385 | end |
386 | |
387 | spec.fillEffectsState = state |
388 | end |
389 | end |
390 | end |
onWriteStream
DescriptionCalled on server side on joinDefinition
onWriteStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
262 | function MixerWagon:onWriteStream(streamId, connection) |
263 | local spec = self.spec_mixerWagon |
264 | for _, entry in ipairs(spec.mixerWagonFillTypes) do |
265 | streamWriteFloat32(streamId, entry.fillLevel) |
266 | end |
267 | |
268 | streamWriteUIntN(streamId, spec.fillEffectsFillType, FillTypeManager.SEND_NUM_BITS) |
269 | 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 |
300 | function MixerWagon:onWriteUpdateStream(streamId, connection, dirtyMask) |
301 | if not connection:getIsServer() then |
302 | local spec = self.spec_mixerWagon |
303 | if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then |
304 | for _, entry in ipairs(spec.mixerWagonFillTypes) do |
305 | streamWriteFloat32(streamId, entry.fillLevel) |
306 | end |
307 | end |
308 | |
309 | if streamWriteBool(streamId, bitAND(dirtyMask, spec.effectDirtyFlag) ~= 0) then |
310 | streamWriteUIntN(streamId, spec.fillEffectsFillType, FillTypeManager.SEND_NUM_BITS) |
311 | end |
312 | end |
313 | end |
prerequisitesPresent
DescriptionChecks if all prerequisite specializations are loadedDefinition
prerequisitesPresent(table specializations)Arguments
table | specializations | specializations |
boolean | hasPrerequisite | true if all prerequisite specializations are loaded |
23 | function MixerWagon.prerequisitesPresent(specializations) |
24 | return SpecializationUtil.hasSpecialization(Trailer, specializations) and SpecializationUtil.hasSpecialization(TurnOnVehicle, specializations) |
25 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
71 | function MixerWagon.registerEventListeners(vehicleType) |
72 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", MixerWagon) |
73 | SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", MixerWagon) |
74 | SpecializationUtil.registerEventListener(vehicleType, "onDelete", MixerWagon) |
75 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", MixerWagon) |
76 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", MixerWagon) |
77 | SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", MixerWagon) |
78 | SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", MixerWagon) |
79 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", MixerWagon) |
80 | SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", MixerWagon) |
81 | SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", MixerWagon) |
82 | SpecializationUtil.registerEventListener(vehicleType, "onFillUnitFillLevelChanged", MixerWagon) |
83 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
55 | function MixerWagon.registerFunctions(vehicleType) |
56 | SpecializationUtil.registerFunction(vehicleType, "mixerWagonBaleTriggerCallback", MixerWagon.mixerWagonBaleTriggerCallback) |
57 | SpecializationUtil.registerFunction(vehicleType, "onHUDTriggerCallback", MixerWagon.onHUDTriggerCallback) |
58 | SpecializationUtil.registerFunction(vehicleType, "getIsPlayerInTrigger", MixerWagon.getIsPlayerInTrigger) |
59 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
63 | function MixerWagon.registerOverwrittenFunctions(vehicleType) |
64 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "addFillUnitFillLevel", MixerWagon.addFillUnitFillLevel) |
65 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillUnitAllowsFillType", MixerWagon.getFillUnitAllowsFillType) |
66 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDischargeFillType", MixerWagon.getDischargeFillType) |
67 | end |
saveToXMLFile
DescriptionDefinitionsaveToXMLFile()Code
233 | function MixerWagon:saveToXMLFile(xmlFile, key, usedModNames) |
234 | local spec = self.spec_mixerWagon |
235 | |
236 | for i, fillType in ipairs(spec.mixerWagonFillTypes) do |
237 | local fillTypeKey = string.format("%s.fillType(%d)", key, i-1) |
238 | xmlFile:setValue(fillTypeKey.."#fillLevel", fillType.fillLevel) |
239 | end |
240 | end |
updateDebugValues
DescriptionDefinitionupdateDebugValues()Code
659 | function MixerWagon:updateDebugValues(values) |
660 | local spec = self.spec_mixerWagon |
661 | |
662 | table.insert(values, {name="Forage isOK", value=tostring(self:getFillUnitFillType(spec.fillUnitIndex) == FillType.FORAGE)}) |
663 | |
664 | for _, mixerWagonFillType in ipairs(spec.mixerWagonFillTypes) do |
665 | local fillTypes = "" |
666 | for fillTypeIndex, _ in pairs(mixerWagonFillType.fillTypes) do |
667 | fillTypes = fillTypes .. " " .. tostring(g_fillTypeManager:getFillTypeNameByIndex(fillTypeIndex)) |
668 | end |
669 | table.insert(values, {name=fillTypes, value=mixerWagonFillType.fillLevel}) |
670 | end |
671 | end |