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
InlineWrapper
DescriptionClass for inline wrappersFunctions
- getAllowBalePushing
- getBrakeForce
- getCanInteract
- getCanPushOff
- getCurrentInlineBale
- getIsActive
- getIsFoldAllowed
- getIsInlineBalingAllowed
- getSpecValueBaleSize
- getSpecValueBaleSizeRound
- getSpecValueBaleSizeSquare
- getWrapperBaleType
- initSpecialization
- inlineBaleTriggerCallback
- inlineWrapTriggerCallback
- loadSpecValueBaleSize
- loadSpecValueBaleSizeRound
- loadSpecValueBaleSizeSquare
- onDelete
- onEnterVehicle
- onLeaveVehicle
- onLoad
- onPostLoad
- onReadStream
- onReadUpdateStream
- onRegisterActionEvents
- onUpdate
- onUpdateTick
- onWriteStream
- onWriteUpdateStream
- prerequisitesPresent
- pushOffInlineBale
- pushOffInlineBaleEvent
- readInlineBales
- registerEventListeners
- registerFunctions
- registerOverwrittenFunctions
- setCurrentInlineBale
- updateInlineSteeringWheels
- updateRoundBaleWrappingNode
- updateSquareBaleWrappingNode
- updateWrapperRailings
- updateWrappingNodes
- writeInlineBales
getAllowBalePushing
DescriptionDefinitiongetAllowBalePushing()Code
1006 | function InlineWrapper:getAllowBalePushing(bale) |
1007 | if bale.dynamicMountJointIndex ~= nil then |
1008 | return false |
1009 | end |
1010 | |
1011 | return true |
1012 | end |
getBrakeForce
DescriptionDefinitiongetBrakeForce()Code
867 | function InlineWrapper:getBrakeForce(superFunc) |
868 | local spec = self.spec_inlineWrapper |
869 | if spec.releaseBrake then |
870 | spec.releaseBrakeSet = spec.releaseBrake |
871 | return 0 |
872 | end |
873 | |
874 | return superFunc(self) |
875 | end |
getCanInteract
DescriptionDefinitiongetCanInteract()Code
1076 | function InlineWrapper:getCanInteract() |
1077 | if not g_currentMission.controlPlayer then |
1078 | return false |
1079 | end |
1080 | |
1081 | if not g_currentMission.accessHandler:canPlayerAccess(self) then |
1082 | return false |
1083 | end |
1084 | |
1085 | local x1, y1, z1 = getWorldTranslation(g_currentMission.player.rootNode) |
1086 | local x2, y2, z2 = getWorldTranslation(self.components[1].node) |
1087 | |
1088 | local distance = MathUtil.vector3Length(x1-x2, y1-y2, z1-z2) |
1089 | |
1090 | return distance < InlineWrapper.INTERACTION_RADIUS |
1091 | end |
getCanPushOff
DescriptionDefinitiongetCanPushOff()Code
1095 | function InlineWrapper:getCanPushOff() |
1096 | local spec = self.spec_inlineWrapper |
1097 | |
1098 | local currentInlineBale = self:getCurrentInlineBale() |
1099 | if currentInlineBale == nil then |
1100 | return false |
1101 | end |
1102 | |
1103 | if currentInlineBale:getPendingBale() ~= nil then |
1104 | return false |
1105 | end |
1106 | |
1107 | if self:getIsAnimationPlaying(spec.animations.pusher) then |
1108 | return false |
1109 | end |
1110 | |
1111 | if self:getIsAnimationPlaying(spec.animations.pushOff) then |
1112 | return false |
1113 | end |
1114 | |
1115 | return true |
1116 | end |
getCurrentInlineBale
DescriptionDefinitiongetCurrentInlineBale()Code
1137 | function InlineWrapper:getCurrentInlineBale() |
1138 | return NetworkUtil.getObject(self.spec_inlineWrapper.currentInlineBale) |
1139 | end |
getIsActive
DescriptionDefinitiongetIsActive()Code
856 | function InlineWrapper:getIsActive(superFunc) |
857 | local spec = self.spec_inlineWrapper |
858 | if spec.releaseBrake or spec.releaseBrake ~= spec.releaseBrakeSet then |
859 | return true |
860 | end |
861 | |
862 | return superFunc(self) |
863 | end |
getIsFoldAllowed
DescriptionDefinitiongetIsFoldAllowed()Code
845 | function InlineWrapper:getIsFoldAllowed(superFunc, direction, onAiTurnOn) |
846 | local spec = self.spec_inlineWrapper |
847 | if next(spec.enteredInlineBales) ~= nil then |
848 | return false |
849 | end |
850 | |
851 | return superFunc(self, direction, onAiTurnOn) |
852 | end |
getIsInlineBalingAllowed
DescriptionDefinitiongetIsInlineBalingAllowed()Code
879 | function InlineWrapper:getIsInlineBalingAllowed() |
880 | local spec = self.spec_inlineWrapper |
881 | if self.getFoldAnimTime ~= nil then |
882 | local foldTime = self:getFoldAnimTime() |
883 | if foldTime < spec.minFoldTime or foldTime > spec.maxFoldTime then |
884 | return false |
885 | end |
886 | end |
887 | |
888 | if self:getIsAnimationPlaying(spec.animations.pusher) then |
889 | return false |
890 | end |
891 | |
892 | if self:getIsAnimationPlaying(spec.animations.pushOff) or self:getAnimationTime(spec.animations.pushOff) > 0 then |
893 | return false |
894 | end |
895 | |
896 | return true |
897 | end |
getSpecValueBaleSize
DescriptionDefinitiongetSpecValueBaleSize()Code
1192 | function InlineWrapper.getSpecValueBaleSize(storeItem, realItem, configurations, saleItem, returnValues, returnRange, roundBaleWrapper) |
1193 | local baleSizeAttributes = roundBaleWrapper and storeItem.specs.inlineWrapperBaleSizeRound or storeItem.specs.inlineWrapperBaleSizeSquare |
1194 | if baleSizeAttributes ~= nil then |
1195 | local minValue = roundBaleWrapper and baleSizeAttributes.minDiameter or baleSizeAttributes.minLength |
1196 | local maxValue = roundBaleWrapper and baleSizeAttributes.maxDiameter or baleSizeAttributes.maxLength |
1197 | |
1198 | if returnValues == nil or not returnValues then |
1199 | local unit = g_i18n:getText("unit_cmShort") |
1200 | local size |
1201 | if maxValue ~= minValue then |
1202 | size = string.format("%d%s-%d%s", minValue * 100, unit, maxValue * 100, unit) |
1203 | else |
1204 | size = string.format("%d%s", minValue * 100, unit) |
1205 | end |
1206 | |
1207 | return size |
1208 | else |
1209 | if returnRange == true and maxValue ~= minValue then |
1210 | return minValue * 100, maxValue * 100, g_i18n:getText("unit_cmShort") |
1211 | else |
1212 | return minValue * 100, g_i18n:getText("unit_cmShort") |
1213 | end |
1214 | end |
1215 | else |
1216 | if returnValues and returnRange then |
1217 | return 0, 0, "" |
1218 | elseif returnValues then |
1219 | return 0, "" |
1220 | else |
1221 | return "" |
1222 | end |
1223 | end |
1224 | end |
getSpecValueBaleSizeRound
DescriptionDefinitiongetSpecValueBaleSizeRound()Code
1240 | function InlineWrapper.getSpecValueBaleSizeRound(storeItem, realItem, configurations, saleItem, returnValues, returnRange) |
1241 | if storeItem.specs.inlineWrapperBaleSizeRound ~= nil then |
1242 | return InlineWrapper.getSpecValueBaleSize(storeItem, realItem, configurations, saleItem, returnValues, returnRange, true) |
1243 | end |
1244 | end |
getSpecValueBaleSizeSquare
DescriptionDefinitiongetSpecValueBaleSizeSquare()Code
1248 | function InlineWrapper.getSpecValueBaleSizeSquare(storeItem, realItem, configurations, saleItem, returnValues, returnRange) |
1249 | if storeItem.specs.inlineWrapperBaleSizeSquare ~= nil then |
1250 | return InlineWrapper.getSpecValueBaleSize(storeItem, realItem, configurations, saleItem, returnValues, returnRange, false) |
1251 | end |
1252 | end |
getWrapperBaleType
DescriptionDefinitiongetWrapperBaleType()Code
977 | function InlineWrapper:getWrapperBaleType(bale) |
978 | local spec = self.spec_inlineWrapper |
979 | |
980 | for _, baleType in pairs(spec.baleTypes) do |
981 | if bale:getSupportsWrapping() then |
982 | if bale.isRoundbale then |
983 | if baleType.isRoundBale then |
984 | if bale.diameter == baleType.diameter |
985 | and bale.width == baleType.width then |
986 | return baleType |
987 | end |
988 | end |
989 | else |
990 | if not baleType.isRoundBale then |
991 | if bale.width == baleType.width |
992 | and bale.height == baleType.height |
993 | and bale.length == baleType.length then |
994 | return baleType |
995 | end |
996 | end |
997 | end |
998 | end |
999 | end |
1000 | |
1001 | return nil |
1002 | end |
initSpecialization
DescriptionCalled on specialization initializingDefinition
initSpecialization()Code
27 | function InlineWrapper.initSpecialization() |
28 | g_storeManager:addSpecType("inlineWrapperBaleSizeRound", "shopListAttributeIconBaleWrapperBaleSizeRound", InlineWrapper.loadSpecValueBaleSizeRound, InlineWrapper.getSpecValueBaleSizeRound, "vehicle") |
29 | g_storeManager:addSpecType("inlineWrapperBaleSizeSquare", "shopListAttributeIconBaleWrapperBaleSizeSquare", InlineWrapper.loadSpecValueBaleSizeSquare, InlineWrapper.getSpecValueBaleSizeSquare, "vehicle") |
30 | |
31 | local schema = Vehicle.xmlSchema |
32 | schema:setXMLSpecializationType("InlineWrapper") |
33 | |
34 | schema:register(XMLValueType.NODE_INDEX, "vehicle.inlineWrapper.baleTrigger#node", "Bale pickup trigger") |
35 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.baleTrigger#minFoldTime", "Min. folding time for bale pickup", 0) |
36 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.baleTrigger#maxFoldTime", "Max. folding time for bale pickup", 1) |
37 | schema:register(XMLValueType.NODE_INDEX, "vehicle.inlineWrapper.wrapTrigger#node", "Wrap trigger") |
38 | |
39 | schema:register(XMLValueType.NODE_INDEX, "vehicle.inlineWrapper.baleTypes.baleType(?)#startNode", "Start placement node for bale") |
40 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.baleTypes.baleType(?).railing#width", "Railing width to set") |
41 | schema:register(XMLValueType.STRING, "vehicle.inlineWrapper.baleTypes.baleType(?).inlineBale#filename", "Path to inline bale xml file") |
42 | |
43 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.baleTypes.baleType(?).size#diameter", "Bale diameter") |
44 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.baleTypes.baleType(?).size#width", "Bale width") |
45 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.baleTypes.baleType(?).size#height", "Bale height") |
46 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.baleTypes.baleType(?).size#length", "Bale length") |
47 | |
48 | schema:register(XMLValueType.STRING, "vehicle.inlineWrapper.railings#animation", "Railing animation") |
49 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.railings#animStartX", "Railing width at start of animation") |
50 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.railings#animEndX", "Railing width at end of animation") |
51 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.railings#defaultX", "Default railing width", 1) |
52 | |
53 | schema:register(XMLValueType.NODE_INDEX, "vehicle.inlineWrapper.wrapping#startNode", "Reference node for warpping state of bale") |
54 | |
55 | schema:register(XMLValueType.NODE_INDEX, "vehicle.inlineWrapper.steeringNodes.steeringNode(?)#node", "Steering node that is aligned to the start wrapping direction") |
56 | |
57 | schema:register(XMLValueType.NODE_INDEX, "vehicle.inlineWrapper.wrappingNodes.wrappingNode(?)#node", "Wrapping node") |
58 | schema:register(XMLValueType.NODE_INDEX, "vehicle.inlineWrapper.wrappingNodes.wrappingNode(?)#target", "Target node that is aliged to the bale") |
59 | schema:register(XMLValueType.VECTOR_TRANS, "vehicle.inlineWrapper.wrappingNodes.wrappingNode(?)#startTrans", "Start translation") |
60 | |
61 | schema:register(XMLValueType.STRING, "vehicle.inlineWrapper.animations#pusher", "Pusher animation", "pusherAnimation") |
62 | schema:register(XMLValueType.STRING, "vehicle.inlineWrapper.animations#wrapping", "Wrapping animation", "wrappingAnimation") |
63 | schema:register(XMLValueType.STRING, "vehicle.inlineWrapper.animations#pushOff", "Push bale off animation", "pushOffAnimation") |
64 | |
65 | schema:register(XMLValueType.STRING, "vehicle.inlineWrapper.pushing#brakeForce", "Brake force while pushing", 0) |
66 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.pushing#openBrakeTime", "Pusher animation time to open brake", 0.1) |
67 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper.pushing#closeBrakeTime", "Pusher animation time to close brake", 0.5) |
68 | schema:register(XMLValueType.INT, "vehicle.inlineWrapper.pushing#minBaleAmount", "Min. bales wrapped to open brake", 4) |
69 | |
70 | schema:register(XMLValueType.FLOAT, "vehicle.inlineWrapper#baleMovedThreshold", "Bale moved threshold for starting wrappign animation", 0.05) |
71 | schema:register(XMLValueType.INT, "vehicle.inlineWrapper#numObjectBits", "Num bits for sending bales", 4) |
72 | |
73 | SoundManager.registerSampleXMLPaths(schema, "vehicle.inlineWrapper.sounds", "wrap") |
74 | SoundManager.registerSampleXMLPaths(schema, "vehicle.inlineWrapper.sounds", "start") |
75 | SoundManager.registerSampleXMLPaths(schema, "vehicle.inlineWrapper.sounds", "stop") |
76 | |
77 | schema:setXMLSpecializationType() |
78 | end |
inlineBaleTriggerCallback
DescriptionDefinitioninlineBaleTriggerCallback()Code
901 | function InlineWrapper:inlineBaleTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
902 | if self.isServer then |
903 | local object = g_currentMission:getNodeObject(otherActorId) |
904 | if object ~= nil and object:isa(Bale) then |
905 | local objectId = NetworkUtil.getObjectId(object) |
906 | local spec = self.spec_inlineWrapper |
907 | if onEnter then |
908 | if not object:isa(InlineBaleSingle) then |
909 | if self:getWrapperBaleType(object) ~= nil then |
910 | spec.pendingSingleBales[objectId] = objectId |
911 | end |
912 | else |
913 | spec.enteredInlineBales[objectId] = objectId |
914 | |
915 | -- set wrapper and wrapping node again if the bale reenteres |
916 | local connectedInlineBale = object:getConnectedInlineBale() |
917 | if connectedInlineBale ~= nil then |
918 | connectedInlineBale:setCurrentWrapperInfo(self, spec.wrappingStartNode) |
919 | else |
920 | -- add information to inline bale if the bale was added to the inline bale (while loading) |
921 | object.inlineWrapperToAdd = {wrapper=self, wrappingNode=spec.wrappingStartNode} |
922 | end |
923 | end |
924 | elseif onLeave then |
925 | spec.pendingSingleBales[objectId] = nil |
926 | spec.enteredInlineBales[objectId] = nil |
927 | |
928 | if object:isa(InlineBaleSingle) then |
929 | local connectedInlineBale = object:getConnectedInlineBale() |
930 | if connectedInlineBale ~= nil then |
931 | local bales = connectedInlineBale:getBales() |
932 | local removeFromWrapper = true |
933 | for _, bale in ipairs(bales) do |
934 | local baleId = NetworkUtil.getObjectId(bale) |
935 | if spec.pendingSingleBales[baleId] ~= nil or |
936 | spec.enteredInlineBales[baleId] ~= nil then |
937 | removeFromWrapper = false |
938 | break |
939 | end |
940 | end |
941 | |
942 | if removeFromWrapper then |
943 | connectedInlineBale:setCurrentWrapperInfo(nil, nil) |
944 | self:setCurrentInlineBale(nil) |
945 | end |
946 | end |
947 | end |
948 | end |
949 | |
950 | self:raiseDirtyFlags(spec.inlineBalesDirtyFlag) |
951 | end |
952 | end |
953 | end |
inlineWrapTriggerCallback
DescriptionDefinitioninlineWrapTriggerCallback()Code
957 | function InlineWrapper:inlineWrapTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
958 | if self.isServer then |
959 | local object = g_currentMission:getNodeObject(otherActorId) |
960 | if object ~= nil and object:isa(Bale) then |
961 | local spec = self.spec_inlineWrapper |
962 | local objectId = NetworkUtil.getObjectId(object) |
963 | if onEnter then |
964 | spec.enteredBalesToWrap[objectId] = objectId |
965 | elseif onLeave then |
966 | spec.enteredBalesToWrap[objectId] = nil |
967 | end |
968 | |
969 | self:raiseActive() |
970 | self:raiseDirtyFlags(spec.inlineBalesDirtyFlag) |
971 | end |
972 | end |
973 | end |
loadSpecValueBaleSize
DescriptionDefinitionloadSpecValueBaleSize()Code
1165 | function InlineWrapper.loadSpecValueBaleSize(xmlFile, customEnvironment, baseDir, roundBaleWrapper) |
1166 | local rootName = xmlFile:getRootName() |
1167 | |
1168 | local baleSizeAttributes = {} |
1169 | baleSizeAttributes.minDiameter, baleSizeAttributes.maxDiameter = math.huge, -math.huge |
1170 | baleSizeAttributes.minLength, baleSizeAttributes.maxLength = math.huge, -math.huge |
1171 | xmlFile:iterate(rootName .. ".inlineWrapper.baleTypes.baleType", function(_, key) |
1172 | local diameter = MathUtil.round(xmlFile:getValue(key..".size#diameter", 0), 2) |
1173 | if roundBaleWrapper and diameter ~= 0 then |
1174 | baleSizeAttributes.minDiameter = math.min(baleSizeAttributes.minDiameter, diameter) |
1175 | baleSizeAttributes.maxDiameter = math.max(baleSizeAttributes.maxDiameter, diameter) |
1176 | end |
1177 | |
1178 | local length = MathUtil.round(xmlFile:getValue(key..".size#length", 0), 2) |
1179 | if not roundBaleWrapper and length ~= 0 then |
1180 | baleSizeAttributes.minLength = math.min(baleSizeAttributes.minLength, length) |
1181 | baleSizeAttributes.maxLength = math.max(baleSizeAttributes.maxLength, length) |
1182 | end |
1183 | end) |
1184 | |
1185 | if baleSizeAttributes.minDiameter ~= math.huge or baleSizeAttributes.minLength ~= math.huge then |
1186 | return baleSizeAttributes |
1187 | end |
1188 | end |
loadSpecValueBaleSizeRound
DescriptionDefinitionloadSpecValueBaleSizeRound()Code
1228 | function InlineWrapper.loadSpecValueBaleSizeRound(xmlFile, customEnvironment, baseDir) |
1229 | return InlineWrapper.loadSpecValueBaleSize(xmlFile, customEnvironment, baseDir, true) |
1230 | end |
loadSpecValueBaleSizeSquare
DescriptionDefinitionloadSpecValueBaleSizeSquare()Code
1234 | function InlineWrapper.loadSpecValueBaleSizeSquare(xmlFile, customEnvironment, baseDir) |
1235 | return InlineWrapper.loadSpecValueBaleSize(xmlFile, customEnvironment, baseDir, false) |
1236 | end |
onDelete
DescriptionCalled on deletingDefinition
onDelete()Code
259 | function InlineWrapper:onDelete() |
260 | local spec = self.spec_inlineWrapper |
261 | if spec.triggerNode ~= nil then |
262 | removeTrigger(spec.triggerNode) |
263 | end |
264 | if spec.wrapTriggerNode ~= nil then |
265 | removeTrigger(spec.wrapTriggerNode) |
266 | end |
267 | |
268 | g_soundManager:deleteSamples(spec.samples) |
269 | |
270 | g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable) |
271 | |
272 | local inlineBale = self:getCurrentInlineBale() |
273 | if inlineBale ~= nil then |
274 | inlineBale:wakeUp(50) |
275 | inlineBale:setWrappingState(1) |
276 | inlineBale:setCurrentWrapperInfo(nil, nil) |
277 | self:setCurrentInlineBale(nil) |
278 | end |
279 | end |
onEnterVehicle
DescriptionDefinitiononEnterVehicle()Code
1063 | function InlineWrapper:onEnterVehicle() |
1064 | local spec = self.spec_inlineWrapper |
1065 | for _, steeringNode in ipairs(spec.steeringNodes) do |
1066 | setRotation(steeringNode.node, unpack(steeringNode.startRot)) |
1067 | |
1068 | if self.setMovingToolDirty ~= nil then |
1069 | self:setMovingToolDirty(steeringNode.node) |
1070 | end |
1071 | end |
1072 | end |
onLeaveVehicle
DescriptionDefinitiononLeaveVehicle()Code
1057 | function InlineWrapper:onLeaveVehicle() |
1058 | self.rotatedTime = 0 |
1059 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
130 | function InlineWrapper:onLoad(savegame) |
131 | local spec = self.spec_inlineWrapper |
132 | |
133 | local baseKey = "vehicle.inlineWrapper" |
134 | |
135 | spec.triggerNode = self.xmlFile:getValue(baseKey..".baleTrigger#node", nil, self.components, self.i3dMappings) |
136 | if spec.triggerNode ~= nil then |
137 | addTrigger(spec.triggerNode, "inlineBaleTriggerCallback", self) |
138 | end |
139 | |
140 | spec.wrapTriggerNode = self.xmlFile:getValue(baseKey..".wrapTrigger#node", nil, self.components, self.i3dMappings) |
141 | if spec.wrapTriggerNode ~= nil then |
142 | addTrigger(spec.wrapTriggerNode, "inlineWrapTriggerCallback", self) |
143 | end |
144 | |
145 | spec.minFoldTime = self.xmlFile:getValue(baseKey..".baleTrigger#minFoldTime", 0) |
146 | spec.maxFoldTime = self.xmlFile:getValue(baseKey..".baleTrigger#maxFoldTime", 1) |
147 | |
148 | spec.baleTypes = {} |
149 | self.xmlFile:iterate(baseKey .. ".baleTypes.baleType", function(index, key) |
150 | local entry = {} |
151 | entry.startNode = self.xmlFile:getValue(key.."#startNode", nil, self.components, self.i3dMappings) |
152 | if entry.startNode ~= nil then |
153 | entry.railingWidth = self.xmlFile:getValue(key..".railing#width") |
154 | |
155 | entry.inlineBaleFilename = Utils.getFilename(self.xmlFile:getValue(key..".inlineBale#filename"), self.baseDirectory) |
156 | if entry.inlineBaleFilename ~= nil then |
157 | entry.diameter = MathUtil.round(self.xmlFile:getValue(key..".size#diameter", 0), 2) |
158 | entry.width = MathUtil.round(self.xmlFile:getValue(key..".size#width", 0), 2) |
159 | entry.isRoundBale = entry.diameter ~= 0 |
160 | if not entry.isRoundBale then |
161 | entry.height = MathUtil.round(self.xmlFile:getValue(key..".size#height", 0), 2) |
162 | entry.length = MathUtil.round(self.xmlFile:getValue(key..".size#length", 0), 2) |
163 | end |
164 | |
165 | entry.index = #spec.baleTypes + 1 |
166 | |
167 | table.insert(spec.baleTypes, entry) |
168 | else |
169 | Logging.xmlError(self.xmlFile, "Failed to load bale type. Missing inline bale filename! '%s'", key) |
170 | end |
171 | else |
172 | Logging.xmlError(self.xmlFile, "Failed to load bale type. Missing start node! '%s'", key) |
173 | end |
174 | end) |
175 | |
176 | spec.railingsAnimation = self.xmlFile:getValue(baseKey..".railings#animation") |
177 | spec.railingsAnimationStartX = self.xmlFile:getValue(baseKey..".railings#animStartX") |
178 | spec.railingsAnimationEndX = self.xmlFile:getValue(baseKey..".railings#animEndX") |
179 | spec.railingStartX = self.xmlFile:getValue(baseKey..".railings#defaultX", 1) |
180 | spec.currentPosition = spec.railingStartX + 0.01 |
181 | spec.targetPosition = spec.railingStartX + 0.01 |
182 | |
183 | spec.wrappingStartNode = self.xmlFile:getValue(baseKey..".wrapping#startNode", nil, self.components, self.i3dMappings) |
184 | |
185 | spec.steeringNodes = {} |
186 | self.xmlFile:iterate(baseKey .. ".steeringNodes.steeringNode", function(_, key) |
187 | local entry = {} |
188 | entry.node = self.xmlFile:getValue(key.."#node", nil, self.components, self.i3dMappings) |
189 | |
190 | if entry.node ~= nil then |
191 | entry.startRot = {getRotation(entry.node)} |
192 | table.insert(spec.steeringNodes, entry) |
193 | end |
194 | end) |
195 | |
196 | spec.wrappingNodes = {} |
197 | self.xmlFile:iterate(baseKey .. ".wrappingNodes.wrappingNode", function(_, key) |
198 | local entry = {} |
199 | entry.node = self.xmlFile:getValue(key.."#node", nil, self.components, self.i3dMappings) |
200 | entry.target = self.xmlFile:getValue(key.."#target", nil, self.components, self.i3dMappings) |
201 | |
202 | if entry.node ~= nil and entry.target ~= nil then |
203 | entry.startTrans = self.xmlFile:getValue(key.."#startTrans", {getTranslation(entry.target)}, true) |
204 | setTranslation(entry.target, entry.startTrans[1], entry.startTrans[2], entry.startTrans[3]) |
205 | |
206 | table.insert(spec.wrappingNodes, entry) |
207 | end |
208 | end) |
209 | |
210 | spec.animations = {} |
211 | spec.animations.pusher = self.xmlFile:getValue(baseKey..".animations#pusher", "pusherAnimation") |
212 | spec.animations.wrapping = self.xmlFile:getValue(baseKey..".animations#wrapping", "wrappingAnimation") |
213 | spec.animations.pushOff = self.xmlFile:getValue(baseKey..".animations#pushOff", "pushOffAnimation") |
214 | |
215 | spec.pushingBrakeForce = self.xmlFile:getValue(baseKey..".pushing#brakeForce", 0) |
216 | spec.pushingOpenBrakeTime = self.xmlFile:getValue(baseKey..".pushing#openBrakeTime", 0.1) |
217 | spec.pushingCloseBrakeTime = self.xmlFile:getValue(baseKey..".pushing#closeBrakeTime", 0.5) |
218 | spec.pushingMinBaleAmount = self.xmlFile:getValue(baseKey..".pushing#minBaleAmount", 4) |
219 | |
220 | spec.baleMovedThreshold = self.xmlFile:getValue(baseKey.."#baleMovedThreshold", 0.05) |
221 | |
222 | spec.pusherAnimationDirty = false |
223 | |
224 | spec.pendingSingleBales = {} |
225 | spec.enteredInlineBales = {} |
226 | spec.enteredBalesToWrap = {} |
227 | |
228 | spec.numObjectBits = self.xmlFile:getValue("vehicle.inlineWrapper#numObjectBits", 4) |
229 | spec.inlineBalesDirtyFlag = self:getNextDirtyFlag() |
230 | |
231 | spec.currentLineDirection = nil |
232 | spec.lineDirection = nil |
233 | spec.activatable = InlineWrapperActivatable.new(self) |
234 | |
235 | if self.isClient then |
236 | spec.samples = {} |
237 | spec.samples.wrap = g_soundManager:loadSampleFromXML(self.xmlFile, baseKey..".sounds", "wrap", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
238 | spec.samples.start = g_soundManager:loadSampleFromXML(self.xmlFile, baseKey..".sounds", "start", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
239 | spec.samples.stop = g_soundManager:loadSampleFromXML(self.xmlFile, baseKey..".sounds", "stop", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
240 | end |
241 | end |
onPostLoad
DescriptionCalled after loadingDefinition
onPostLoad(table savegame)Arguments
table | savegame | savegame |
246 | function InlineWrapper:onPostLoad(savegame) |
247 | local spec = self.spec_inlineWrapper |
248 | if spec.railingsAnimation ~= nil then |
249 | self:setAnimationTime(spec.railingsAnimation, 1, true) |
250 | end |
251 | |
252 | if self.configurations["wrappingColor"] ~= nil then |
253 | self:applyBaseMaterialConfiguration(self.xmlFile, "wrappingColor", self.configurations["wrappingColor"]) |
254 | end |
255 | end |
onReadStream
DescriptionDefinitiononReadStream()Code
283 | function InlineWrapper:onReadStream(streamId, connection) |
284 | self:readInlineBales("pendingSingleBales", streamId, connection) |
285 | self:readInlineBales("enteredInlineBales", streamId, connection) |
286 | self:readInlineBales("enteredBalesToWrap", streamId, connection) |
287 | |
288 | if streamReadBool(streamId) then |
289 | local inlineBale = NetworkUtil.readNodeObjectId(streamId) |
290 | self:setCurrentInlineBale(inlineBale, true) |
291 | else |
292 | self:setCurrentInlineBale(nil, true) |
293 | end |
294 | |
295 | local spec = self.spec_inlineWrapper |
296 | g_currentMission.activatableObjectsSystem:addActivatable(spec.activatable) |
297 | end |
onReadUpdateStream
DescriptionDefinitiononReadUpdateStream()Code
314 | function InlineWrapper:onReadUpdateStream(streamId, timestamp, connection) |
315 | if connection:getIsServer() then |
316 | if streamReadBool(streamId) then |
317 | self:readInlineBales("pendingSingleBales", streamId, connection) |
318 | self:readInlineBales("enteredInlineBales", streamId, connection) |
319 | self:readInlineBales("enteredBalesToWrap", streamId, connection) |
320 | |
321 | if streamReadBool(streamId) then |
322 | local inlineBale = NetworkUtil.readNodeObjectId(streamId) |
323 | self:setCurrentInlineBale(inlineBale, true) |
324 | else |
325 | self:setCurrentInlineBale(nil, true) |
326 | end |
327 | |
328 | local spec = self.spec_inlineWrapper |
329 | g_currentMission.activatableObjectsSystem:addActivatable(spec.activatable) |
330 | end |
331 | end |
332 | end |
onRegisterActionEvents
DescriptionDefinitiononRegisterActionEvents()Code
828 | function InlineWrapper:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
829 | if self.isClient then |
830 | local spec = self.spec_inlineWrapper |
831 | self:clearActionEventsTable(spec.actionEvents) |
832 | |
833 | if isActiveForInput then |
834 | local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.ACTIVATE_OBJECT, self, InlineWrapper.pushOffInlineBaleEvent, false, false, true, true, nil) |
835 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_HIGH) |
836 | g_inputBinding:setActionEventActive(actionEventId, self:getCanPushOff()) |
837 | g_inputBinding:setActionEventTextVisibility(actionEventId, true) |
838 | g_inputBinding:setActionEventText(actionEventId, g_i18n:getText("action_baleloaderUnload")) |
839 | end |
840 | end |
841 | 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 |
389 | function InlineWrapper:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
390 | local spec = self.spec_inlineWrapper |
391 | if self:getIsAnimationPlaying(spec.animations.wrapping) then |
392 | self:updateWrappingNodes() |
393 | end |
394 | 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 |
401 | function InlineWrapper:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
402 | local spec = self.spec_inlineWrapper |
403 | if self.isServer then |
404 | local pendingBaleId = next(spec.pendingSingleBales) |
405 | local pendingBale = NetworkUtil.getObject(pendingBaleId) |
406 | if pendingBale ~= nil and self:getIsInlineBalingAllowed() then |
407 | local baleType = self:getWrapperBaleType(pendingBale) |
408 | local lastBaleId = next(spec.enteredInlineBales) |
409 | local lastBale = NetworkUtil.getObject(lastBaleId) |
410 | local inlineBale |
411 | local success = false |
412 | if lastBale == nil then |
413 | -- first bale |
414 | inlineBale = InlineBale.new(self.isServer, self.isClient) |
415 | |
416 | if inlineBale:loadFromConfigXML(baleType.inlineBaleFilename) then |
417 | inlineBale:setOwnerFarmId(self:getActiveFarm(), true) |
418 | |
419 | inlineBale:setCurrentWrapperInfo(self, spec.wrappingStartNode) |
420 | |
421 | inlineBale:register() |
422 | |
423 | success = inlineBale:addBale(pendingBale, baleType) |
424 | else |
425 | inlineBale:delete() |
426 | end |
427 | else |
428 | -- add another bale |
429 | if lastBale:isa(InlineBaleSingle) then |
430 | inlineBale = lastBale:getConnectedInlineBale() |
431 | if inlineBale ~= nil then |
432 | |
433 | success = inlineBale:addBale(pendingBale, baleType) |
434 | |
435 | if success then |
436 | local currentInlineBale = self:getCurrentInlineBale() |
437 | currentInlineBale:setCurrentWrapperInfo(self, spec.wrappingStartNode) |
438 | end |
439 | end |
440 | end |
441 | end |
442 | |
443 | if success then |
444 | spec.pendingSingleBales[pendingBaleId] = nil |
445 | spec.enteredInlineBales[pendingBaleId] = pendingBaleId |
446 | |
447 | spec.pusherAnimationDirty = true |
448 | self:setCurrentInlineBale(inlineBale) |
449 | |
450 | g_currentMission.activatableObjectsSystem:addActivatable(spec.activatable) |
451 | |
452 | local stats = g_currentMission:farmStats(self:getOwnerFarmId()) |
453 | local total = stats:updateStats("wrappedBales", 1) |
454 | g_achievementManager:tryUnlock("WrappedBales", total) |
455 | |
456 | self:raiseDirtyFlags(spec.inlineBalesDirtyFlag) |
457 | end |
458 | end |
459 | end |
460 | |
461 | -- set currentInlineBale not matter if a new bale ist getting mounted (necessary for clients and singleplayer if the savegame if reloaded) |
462 | local inlineBaleId = next(spec.enteredInlineBales) |
463 | local bale = NetworkUtil.getObject(inlineBaleId) |
464 | if bale ~= nil then |
465 | if self:getCurrentInlineBale() == nil then |
466 | if bale:isa(InlineBaleSingle) then |
467 | local inlineBale = bale:getConnectedInlineBale() |
468 | if inlineBale ~= nil then |
469 | self:setCurrentInlineBale(inlineBale) |
470 | |
471 | g_currentMission.activatableObjectsSystem:addActivatable(spec.activatable) |
472 | |
473 | self:updateWrappingNodes() |
474 | |
475 | local currentInlineBale = self:getCurrentInlineBale() |
476 | currentInlineBale:setCurrentWrapperInfo(self, spec.wrappingStartNode) |
477 | end |
478 | end |
479 | end |
480 | else |
481 | self:setCurrentInlineBale(nil) |
482 | end |
483 | |
484 | local needsSteering = (next(spec.enteredInlineBales) ~= nil or spec.pushOffStarted) and self:getAttacherVehicle() == nil |
485 | local steeringActive = needsSteering and not self:getIsControlled() |
486 | |
487 | if spec.lineDirection == nil and needsSteering then |
488 | local x, _, z = localDirectionToWorld(self.components[1].node, 0, 0, -1) |
489 | spec.lineDirection = {x, z} |
490 | elseif spec.lineDirection ~= nil and not needsSteering then |
491 | spec.lineDirection = nil |
492 | end |
493 | |
494 | if not steeringActive then |
495 | if spec.currentLineDirection ~= nil then |
496 | spec.currentLineDirection = nil |
497 | self:updateInlineSteeringWheels() |
498 | end |
499 | else |
500 | spec.currentLineDirection = spec.lineDirection |
501 | end |
502 | |
503 | if spec.currentLineDirection ~= nil then |
504 | self:updateInlineSteeringWheels(spec.currentLineDirection[1], spec.currentLineDirection[2]) |
505 | end |
506 | |
507 | if self.isServer then |
508 | spec.releaseBrake = false |
509 | local currentInlineBale = self:getCurrentInlineBale() |
510 | |
511 | if spec.pusherAnimationDirty then |
512 | local allowedToPush = true |
513 | |
514 | for _, baleId in pairs(spec.pendingSingleBales) do |
515 | if not self:getAllowBalePushing(NetworkUtil.getObject(baleId)) then |
516 | allowedToPush = false |
517 | break |
518 | end |
519 | end |
520 | |
521 | if allowedToPush then |
522 | for _, baleId in pairs(spec.enteredInlineBales) do |
523 | if not self:getAllowBalePushing(NetworkUtil.getObject(baleId)) then |
524 | allowedToPush = false |
525 | break |
526 | end |
527 | end |
528 | end |
529 | |
530 | if allowedToPush then |
531 | if currentInlineBale ~= nil then |
532 | local pendingBale = currentInlineBale:getPendingBale() |
533 | local pendingBaleId = NetworkUtil.getObjectId(pendingBale) |
534 | local baleType = self:getWrapperBaleType(pendingBale) |
535 | |
536 | local replaced, newBaleId = currentInlineBale:replacePendingBale(baleType.startNode, ConfigurationUtil.getColorByConfigId(self, "wrappingColor", self.configurations["wrappingColor"])) |
537 | if replaced then |
538 | spec.enteredInlineBales[pendingBaleId] = nil |
539 | spec.enteredInlineBales[newBaleId] = newBaleId |
540 | end |
541 | |
542 | self:playAnimation(spec.animations.pusher, 1, 0) |
543 | spec.pusherAnimationDirty = false |
544 | currentInlineBale:connectPendingBale() |
545 | self:raiseDirtyFlags(spec.inlineBalesDirtyFlag) |
546 | end |
547 | end |
548 | |
549 | self:raiseActive() |
550 | end |
551 | |
552 | if self:getAttacherVehicle() == nil then |
553 | local allowBrakeOpening = true |
554 | if currentInlineBale ~= nil then |
555 | if currentInlineBale:getNumberOfBales() < spec.pushingMinBaleAmount then |
556 | allowBrakeOpening = false |
557 | end |
558 | end |
559 | |
560 | local animTime = self:getAnimationTime(spec.animations.pusher) |
561 | local isPushing = self:getIsAnimationPlaying(spec.animations.pusher) and animTime > spec.pushingOpenBrakeTime and animTime < spec.pushingCloseBrakeTime |
562 | local currentSpeed = self:getAnimationSpeed(spec.animations.pushOff) |
563 | local isPushingOff = self:getIsAnimationPlaying(spec.animations.pushOff) and currentSpeed > 0 |
564 | |
565 | local releaseBrake = isPushing or isPushingOff |
566 | |
567 | if allowBrakeOpening then |
568 | spec.releaseBrake = releaseBrake |
569 | end |
570 | end |
571 | end |
572 | |
573 | local playWrapAnimation = false |
574 | for _, wrapBaleId in pairs(spec.enteredBalesToWrap) do |
575 | local wrapBale = NetworkUtil.getObject(wrapBaleId) |
576 | if wrapBale ~= nil then |
577 | if entityExists(wrapBale.nodeId) then |
578 | local x, y, z = localToLocal(wrapBale.nodeId, self.components[1].node, 0, 0, 0) |
579 | if wrapBale.lastWrapTranslation ~= nil and wrapBale.lastWrapMoveTime ~= nil then |
580 | if math.abs(wrapBale.lastWrapTranslation[1]-x) + math.abs(wrapBale.lastWrapTranslation[2]-y) + math.abs(wrapBale.lastWrapTranslation[3]-z) > spec.baleMovedThreshold then |
581 | wrapBale.lastWrapMoveTime = g_currentMission.time |
582 | wrapBale.lastWrapTranslation = {x, y, z} |
583 | end |
584 | else |
585 | wrapBale.lastWrapMoveTime = -math.huge |
586 | wrapBale.lastWrapTranslation = {x, y, z} |
587 | end |
588 | |
589 | if wrapBale.lastWrapMoveTime + 1500 > g_currentMission.time then |
590 | playWrapAnimation = true |
591 | break |
592 | end |
593 | |
594 | self:raiseActive() |
595 | end |
596 | end |
597 | end |
598 | |
599 | if playWrapAnimation then |
600 | if not self:getIsAnimationPlaying(spec.animations.wrapping) then |
601 | self:playAnimation(spec.animations.wrapping, 1, self:getAnimationTime(spec.animations.wrapping), true) |
602 | end |
603 | |
604 | if self.isClient then |
605 | if not g_soundManager:getIsSamplePlaying(spec.samples.start) and not g_soundManager:getIsSamplePlaying(spec.samples.wrap) then |
606 | g_soundManager:playSample(spec.samples.start) |
607 | g_soundManager:playSample(spec.samples.wrap, 0, spec.samples.start) |
608 | end |
609 | end |
610 | else |
611 | self:stopAnimation(spec.animations.wrapping, true) |
612 | |
613 | if self.isClient then |
614 | if g_soundManager:getIsSamplePlaying(spec.samples.start) or g_soundManager:getIsSamplePlaying(spec.samples.wrap) then |
615 | g_soundManager:stopSample(spec.samples.start) |
616 | g_soundManager:stopSample(spec.samples.wrap) |
617 | g_soundManager:playSample(spec.samples.stop) |
618 | end |
619 | end |
620 | end |
621 | |
622 | local baleId = next(spec.pendingSingleBales) or next(spec.enteredInlineBales) |
623 | bale = NetworkUtil.getObject(baleId) |
624 | if bale ~= nil then |
625 | local baleType = self:getWrapperBaleType(bale) |
626 | |
627 | local currentInlineBale = self:getCurrentInlineBale() |
628 | if currentInlineBale ~= nil then |
629 | if not currentInlineBale:getIsBaleAllowed(bale, baleType) then |
630 | baleType = nil |
631 | end |
632 | end |
633 | |
634 | if baleType ~= nil then |
635 | spec.targetPosition = baleType.railingWidth |
636 | |
637 | self:updateWrapperRailings(spec.targetPosition, dt) |
638 | end |
639 | else |
640 | self:updateWrapperRailings(spec.railingStartX, dt) |
641 | end |
642 | |
643 | -- reset push off arm |
644 | if self.isServer then |
645 | if spec.pushOffStarted ~= nil and spec.pushOffStarted then |
646 | if not self:getIsAnimationPlaying(spec.animations.pushOff) then |
647 | self:playAnimation(spec.animations.pushOff, -1, 1) |
648 | spec.pushOffStarted = nil |
649 | end |
650 | end |
651 | end |
652 | |
653 | if self.isClient then |
654 | local actionEvent = spec.actionEvents[InputAction.ACTIVATE_OBJECT] |
655 | if actionEvent ~= nil then |
656 | g_inputBinding:setActionEventActive(actionEvent.actionEventId, self:getCanPushOff()) |
657 | end |
658 | end |
659 | end |
onWriteStream
DescriptionDefinitiononWriteStream()Code
301 | function InlineWrapper:onWriteStream(streamId, connection) |
302 | self:writeInlineBales("pendingSingleBales", streamId, connection) |
303 | self:writeInlineBales("enteredInlineBales", streamId, connection) |
304 | self:writeInlineBales("enteredBalesToWrap", streamId, connection) |
305 | |
306 | local currentInlineBale = self:getCurrentInlineBale() |
307 | if streamWriteBool(streamId, currentInlineBale ~= nil) then |
308 | NetworkUtil.writeNodeObject(streamId, currentInlineBale) |
309 | end |
310 | end |
onWriteUpdateStream
DescriptionDefinitiononWriteUpdateStream()Code
336 | function InlineWrapper:onWriteUpdateStream(streamId, connection, dirtyMask) |
337 | if not connection:getIsServer() then |
338 | local spec = self.spec_inlineWrapper |
339 | |
340 | if streamWriteBool(streamId, bitAND(dirtyMask, spec.inlineBalesDirtyFlag) ~= 0) then |
341 | self:writeInlineBales("pendingSingleBales", streamId, connection) |
342 | self:writeInlineBales("enteredInlineBales", streamId, connection) |
343 | self:writeInlineBales("enteredBalesToWrap", streamId, connection) |
344 | |
345 | local currentInlineBale = self:getCurrentInlineBale() |
346 | if streamWriteBool(streamId, currentInlineBale ~= nil) then |
347 | NetworkUtil.writeNodeObject(streamId, currentInlineBale) |
348 | end |
349 | end |
350 | end |
351 | 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 |
21 | function InlineWrapper.prerequisitesPresent(specializations) |
22 | return true |
23 | end |
pushOffInlineBale
DescriptionDefinitionpushOffInlineBale()Code
1155 | function InlineWrapper:pushOffInlineBale() |
1156 | local spec = self.spec_inlineWrapper |
1157 | if not self:getIsAnimationPlaying(spec.animations.pushOff) then |
1158 | self:playAnimation(spec.animations.pushOff, 1) |
1159 | spec.pushOffStarted = true |
1160 | end |
1161 | end |
pushOffInlineBaleEvent
DescriptionDefinitionpushOffInlineBaleEvent()Code
1143 | function InlineWrapper.pushOffInlineBaleEvent(self, actionName, inputValue, callbackState, isAnalog) |
1144 | if inputValue == 1 then |
1145 | if g_server ~= nil then |
1146 | self:pushOffInlineBale() |
1147 | else |
1148 | g_client:getServerConnection():sendEvent(InlineWrapperPushOffEvent.new(self)) |
1149 | end |
1150 | end |
1151 | end |
readInlineBales
DescriptionDefinitionreadInlineBales()Code
355 | function InlineWrapper:readInlineBales(name, streamId, connection) |
356 | local spec = self.spec_inlineWrapper |
357 | local sum = streamReadUIntN(streamId, spec.numObjectBits) |
358 | |
359 | spec[name] = {} |
360 | for _=1, sum do |
361 | local object = NetworkUtil.readNodeObjectId(streamId) |
362 | spec[name][object] = object |
363 | end |
364 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
112 | function InlineWrapper.registerEventListeners(vehicleType) |
113 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", InlineWrapper) |
114 | SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", InlineWrapper) |
115 | SpecializationUtil.registerEventListener(vehicleType, "onDelete", InlineWrapper) |
116 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", InlineWrapper) |
117 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", InlineWrapper) |
118 | SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", InlineWrapper) |
119 | SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", InlineWrapper) |
120 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", InlineWrapper) |
121 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", InlineWrapper) |
122 | SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", InlineWrapper) |
123 | SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", InlineWrapper) |
124 | SpecializationUtil.registerEventListener(vehicleType, "onEnterVehicle", InlineWrapper) |
125 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
82 | function InlineWrapper.registerFunctions(vehicleType) |
83 | SpecializationUtil.registerFunction(vehicleType, "readInlineBales", InlineWrapper.readInlineBales) |
84 | SpecializationUtil.registerFunction(vehicleType, "writeInlineBales", InlineWrapper.writeInlineBales) |
85 | SpecializationUtil.registerFunction(vehicleType, "getIsInlineBalingAllowed", InlineWrapper.getIsInlineBalingAllowed) |
86 | SpecializationUtil.registerFunction(vehicleType, "inlineBaleTriggerCallback", InlineWrapper.inlineBaleTriggerCallback) |
87 | SpecializationUtil.registerFunction(vehicleType, "inlineWrapTriggerCallback", InlineWrapper.inlineWrapTriggerCallback) |
88 | SpecializationUtil.registerFunction(vehicleType, "updateWrappingNodes", InlineWrapper.updateWrappingNodes) |
89 | SpecializationUtil.registerFunction(vehicleType, "updateRoundBaleWrappingNode", InlineWrapper.updateRoundBaleWrappingNode) |
90 | SpecializationUtil.registerFunction(vehicleType, "updateSquareBaleWrappingNode", InlineWrapper.updateSquareBaleWrappingNode) |
91 | SpecializationUtil.registerFunction(vehicleType, "getWrapperBaleType", InlineWrapper.getWrapperBaleType) |
92 | SpecializationUtil.registerFunction(vehicleType, "getAllowBalePushing", InlineWrapper.getAllowBalePushing) |
93 | SpecializationUtil.registerFunction(vehicleType, "updateWrapperRailings", InlineWrapper.updateWrapperRailings) |
94 | SpecializationUtil.registerFunction(vehicleType, "updateInlineSteeringWheels", InlineWrapper.updateInlineSteeringWheels) |
95 | SpecializationUtil.registerFunction(vehicleType, "getCanInteract", InlineWrapper.getCanInteract) |
96 | SpecializationUtil.registerFunction(vehicleType, "getCanPushOff", InlineWrapper.getCanPushOff) |
97 | SpecializationUtil.registerFunction(vehicleType, "setCurrentInlineBale", InlineWrapper.setCurrentInlineBale) |
98 | SpecializationUtil.registerFunction(vehicleType, "getCurrentInlineBale", InlineWrapper.getCurrentInlineBale) |
99 | SpecializationUtil.registerFunction(vehicleType, "pushOffInlineBale", InlineWrapper.pushOffInlineBale) |
100 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
104 | function InlineWrapper.registerOverwrittenFunctions(vehicleType) |
105 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsFoldAllowed", InlineWrapper.getIsFoldAllowed) |
106 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsActive", InlineWrapper.getIsActive) |
107 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getBrakeForce", InlineWrapper.getBrakeForce) |
108 | end |
setCurrentInlineBale
DescriptionDefinitionsetCurrentInlineBale()Code
1120 | function InlineWrapper:setCurrentInlineBale(inlineBale, isClient) |
1121 | local spec = self.spec_inlineWrapper |
1122 | if self.isServer then |
1123 | local newInlineBale = NetworkUtil.getObjectId(inlineBale) |
1124 | if newInlineBale ~= spec.currentInlineBale then |
1125 | spec.currentInlineBale = newInlineBale |
1126 | self:raiseDirtyFlags(spec.inlineBalesDirtyFlag) |
1127 | end |
1128 | end |
1129 | |
1130 | if isClient then |
1131 | spec.currentInlineBale = inlineBale |
1132 | end |
1133 | end |
updateInlineSteeringWheels
DescriptionDefinitionupdateInlineSteeringWheels()Code
1034 | function InlineWrapper:updateInlineSteeringWheels(dirX, dirZ) |
1035 | local spec = self.spec_inlineWrapper |
1036 | |
1037 | for _, steeringNode in ipairs(spec.steeringNodes) do |
1038 | if dirX == nil or dirZ == nil then |
1039 | setRotation(steeringNode.node, unpack(steeringNode.startRot)) |
1040 | else |
1041 | local px, py, pz = getWorldTranslation(steeringNode.node) |
1042 | local targetX, _, targetZ = worldToLocal(getParent(steeringNode.node), px+(dirX)*10, py, pz+(dirZ)*10) |
1043 | targetX, _, targetZ = MathUtil.vector3Normalize(targetX, 0, targetZ) |
1044 | |
1045 | local upX, upY, upZ = localDirectionToWorld(getParent(steeringNode.node), 0, 1, 0) |
1046 | setDirection(steeringNode.node, targetX, 0, targetZ, upX, upY, upZ) |
1047 | end |
1048 | |
1049 | if self.setMovingToolDirty ~= nil then |
1050 | self:setMovingToolDirty(steeringNode.node) |
1051 | end |
1052 | end |
1053 | end |
updateRoundBaleWrappingNode
DescriptionDefinitionupdateRoundBaleWrappingNode()Code
737 | function InlineWrapper:updateRoundBaleWrappingNode(bale, wrappingNode, x, y, z) |
738 | local baleNode = bale.nodeId |
739 | local baleRadius = bale.diameter / 2 |
740 | local steps = 32 |
741 | local intersectOffset = 0.01 |
742 | local foilOffset = -0.03 |
743 | |
744 | local w1x, w1y, w1z = worldToLocal(baleNode, x, y, z) |
745 | |
746 | local distanceToCenter = MathUtil.vector3Length(w1x, w1y, 0) |
747 | local maxDirY = -math.huge |
748 | local targetX, targetY, targetZ |
749 | for i=1, steps do |
750 | local a = (i/steps)*2*math.pi |
751 | |
752 | local c = math.cos(a) * (baleRadius+intersectOffset) |
753 | local s = math.sin(a) * (baleRadius+intersectOffset) |
754 | |
755 | local distance = MathUtil.vector2Length(c-w1x, s-w1y) |
756 | if distance < distanceToCenter then |
757 | local intersect, _, _, _, _ = MathUtil.getCircleLineIntersection(0, 0, baleRadius, w1x, w1y, c, s) |
758 | |
759 | if not intersect then |
760 | local px, py, pz = localToWorld(baleNode, c, s, 0) |
761 | local _, wrapDirY, _ = worldToLocal(wrappingNode, px, py, pz) |
762 | if wrapDirY > maxDirY then |
763 | maxDirY = wrapDirY |
764 | |
765 | targetX, targetY, targetZ = localToWorld(baleNode, math.cos(a) * (baleRadius+foilOffset), math.sin(a) * (baleRadius+foilOffset), w1z) |
766 | end |
767 | end |
768 | end |
769 | end |
770 | |
771 | return targetX, targetY, targetZ |
772 | end |
updateSquareBaleWrappingNode
DescriptionDefinitionupdateSquareBaleWrappingNode()Code
776 | function InlineWrapper:updateSquareBaleWrappingNode(bale, wrappingNode, x, y, z) |
777 | local baleNode = bale.nodeId |
778 | |
779 | local minAngle = math.huge |
780 | local targetX, targetY, targetZ |
781 | local height = bale.height / 2 |
782 | local length = bale.length / 2 |
783 | local intersectOffset = 0.01 |
784 | local foilOffset = -0.05 |
785 | |
786 | local w1x, w1y, w1z = worldToLocal(baleNode, x, y, z) |
787 | |
788 | if bale.wrappingEdges == nil then |
789 | bale.wrappingEdges = {} |
790 | bale.wrappingEdges[1] = {0, height, -length} |
791 | bale.wrappingEdges[2] = {0, -height, -length} |
792 | bale.wrappingEdges[3] = {0, -height, length} |
793 | bale.wrappingEdges[4] = {0, height, length} |
794 | end |
795 | |
796 | for _, edge in ipairs(bale.wrappingEdges) do |
797 | local edgeY = edge[2] + MathUtil.sign(edge[2]) * intersectOffset |
798 | local edgeZ = edge[3] + MathUtil.sign(edge[3]) * intersectOffset |
799 | |
800 | local intersect = false |
801 | for i=1, 4 do |
802 | local i2 = i <= 3 and i + 1 or 1 |
803 | intersect = intersect or MathUtil.getLineBoundingVolumeIntersect(edgeY, edgeZ, w1y, w1z, bale.wrappingEdges[i][2], bale.wrappingEdges[i][3], bale.wrappingEdges[i2][2], bale.wrappingEdges[i2][3]) |
804 | end |
805 | |
806 | if not intersect then |
807 | local px, py, pz = localToWorld(baleNode, w1x, edgeY, edgeZ) |
808 | local _, wrapDirY, wrapDirZ = worldToLocal(wrappingNode, px, py, pz) |
809 | local angle = MathUtil.getYRotationFromDirection(wrapDirY, wrapDirZ) |
810 | |
811 | if angle < 0 then |
812 | angle = math.pi + (math.pi+angle) |
813 | end |
814 | |
815 | if angle < minAngle then |
816 | minAngle = angle |
817 | |
818 | targetX, targetY, targetZ = localToWorld(baleNode, w1x, edge[2] + MathUtil.sign(edge[2]) * foilOffset, edge[3] + MathUtil.sign(edge[3]) * foilOffset) |
819 | end |
820 | end |
821 | end |
822 | |
823 | return targetX, targetY, targetZ |
824 | end |
updateWrapperRailings
DescriptionDefinitionupdateWrapperRailings()Code
1016 | function InlineWrapper:updateWrapperRailings(targetPosition, dt) |
1017 | local spec = self.spec_inlineWrapper |
1018 | if targetPosition ~= spec.currentPosition then |
1019 | local dir = MathUtil.sign(targetPosition - spec.currentPosition) |
1020 | spec.currentPosition = spec.currentPosition + 0.0001 * dt * dir |
1021 | if dir > 0 then |
1022 | spec.currentPosition = math.min(spec.currentPosition, targetPosition) |
1023 | else |
1024 | spec.currentPosition = math.max(spec.currentPosition, targetPosition) |
1025 | end |
1026 | |
1027 | local animTime = (spec.currentPosition - spec.railingsAnimationStartX) / (spec.railingsAnimationEndX - spec.railingsAnimationStartX) |
1028 | self:setAnimationTime(spec.railingsAnimation, animTime, true) |
1029 | end |
1030 | end |
updateWrappingNodes
DescriptionDefinitionupdateWrappingNodes()Code
663 | function InlineWrapper:updateWrappingNodes() |
664 | local spec = self.spec_inlineWrapper |
665 | |
666 | local inlineBale = self:getCurrentInlineBale() |
667 | if inlineBale ~= nil then |
668 | local bales = spec.enteredBalesToWrap |
669 | |
670 | for _, wrappingNode in ipairs(spec.wrappingNodes) do |
671 | local x, y, z = getWorldTranslation(wrappingNode.node) |
672 | local minDistance = math.huge |
673 | local minBale |
674 | for _, baleId in pairs(bales) do |
675 | local bale = NetworkUtil.getObject(baleId) |
676 | if bale ~= nil then |
677 | if bale ~= inlineBale:getPendingBale() then |
678 | local bx, _, bz = worldToLocal(bale.nodeId, x, y, z) |
679 | local x1, y1, z1 |
680 | local x2, y2, z2 |
681 | if bale.isRoundbale then |
682 | if bz >= -bale.width / 2 then |
683 | x1, y1, z1 = localToWorld(bale.nodeId, 0, 0, bale.width/2) |
684 | x2, y2, z2 = localToWorld(bale.nodeId, 0, 0, -bale.width/2) |
685 | end |
686 | else |
687 | if bx >= -bale.width / 2 then |
688 | x1, y1, z1 = localToWorld(bale.nodeId, bale.width/2, 0, 0) |
689 | x2, y2, z2 = localToWorld(bale.nodeId, -bale.width/2, 0, 0) |
690 | end |
691 | end |
692 | |
693 | if x1 ~= nil then |
694 | local distance = math.min(MathUtil.vector3Length(x-x1, y-y1, z-z1), MathUtil.vector3Length(x-x2, y-y2, z-z2)) |
695 | if distance < minDistance then |
696 | minDistance = distance |
697 | minBale = bale |
698 | end |
699 | end |
700 | end |
701 | end |
702 | end |
703 | |
704 | if minBale ~= nil then |
705 | local targetX, targetY, targetZ |
706 | if minBale.isRoundbale then |
707 | targetX, targetY, targetZ = self:updateRoundBaleWrappingNode(minBale, wrappingNode.node, x, y, z) |
708 | else |
709 | targetX, targetY, targetZ = self:updateSquareBaleWrappingNode(minBale, wrappingNode.node, x, y, z) |
710 | end |
711 | |
712 | if targetX ~= nil then |
713 | targetX, targetY, targetZ = worldToLocal(getParent(wrappingNode.target), targetX, targetY, targetZ) |
714 | setTranslation(wrappingNode.target, targetX, targetY, targetZ) |
715 | else |
716 | setTranslation(wrappingNode.target, wrappingNode.startTrans[1], wrappingNode.startTrans[2], wrappingNode.startTrans[3]) |
717 | end |
718 | else |
719 | setTranslation(wrappingNode.target, wrappingNode.startTrans[1], wrappingNode.startTrans[2], wrappingNode.startTrans[3]) |
720 | end |
721 | end |
722 | |
723 | spec.resetWrappingNodes = true |
724 | else |
725 | if spec.resetWrappingNodes then |
726 | for _, wrappingNode in ipairs(spec.wrappingNodes) do |
727 | setTranslation(wrappingNode.target, wrappingNode.startTrans[1], wrappingNode.startTrans[2], wrappingNode.startTrans[3]) |
728 | end |
729 | |
730 | spec.resetWrappingNodes = nil |
731 | end |
732 | end |
733 | end |
writeInlineBales
DescriptionDefinitionwriteInlineBales()Code
368 | function InlineWrapper:writeInlineBales(name, streamId, connection) |
369 | local spec = self.spec_inlineWrapper |
370 | local num = table.size(spec[name]) |
371 | streamWriteUIntN(streamId, num, spec.numObjectBits) |
372 | |
373 | local objectIndex = 0 |
374 | for object,_ in pairs(spec[name]) do |
375 | objectIndex = objectIndex + 1 |
376 | if objectIndex <= num then |
377 | NetworkUtil.writeNodeObjectId(streamId, object) |
378 | else |
379 | Logging.xmlWarning(self.xmlFile, "Not enough bits to send all inline objects. Please increase '%s'", "vehicle.inlineWrapper#numObjectBits") |
380 | end |
381 | end |
382 | end |