Script v1.7.1.0
- AI
- Animals
- Contracts
- Debug
- Economy
- Effects
- Events
- Farms
- GUI
- Handtools
- I3d
- Materials
- Misc
- Objects
- Placeables
- Player
- Shop
- Sounds
- Specializations
- AIConveyorBelt
- AIImplement
- AIVehicle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BunkerSiloCompacter
- BunkerSiloInteractor
- BuyableBale
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- JigglingParts
- Leveler
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- MixerWagon
- Motorized
- Mountable
- Mower
- Pickup
- Pipe
- Plow
- PowerConsumer
- PowerTakeOffs
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StrawBlower
- StumpCutter
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TipOccluder
- Trailer
- TreePlanter
- TreeSaw
- TurnOnVehicle
- Washable
- WaterTrailer
- Wearable
- Weeder
- Wheels
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- Triggers
- Utils
- Vehicles
- Weather
Engine v1.7.1.0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- XML
- general
Foundation Reference
GroundAdjustedNodes
DescriptionSpecialization for adjusting nodes to the ground/terrain height (e.g. liquid manure spreaders with hoses)Functions
- getIsGroundAdjustedNodeActive
- groundAdjustRaycastCallback
- loadGroundAdjustedNodeFromXML
- loadGroundAdjustedRaycastNodeFromXML
- onLoad
- onUpdate
- onUpdateTick
- prerequisitesPresent
- registerEventListeners
- registerFunctions
getIsGroundAdjustedNodeActive
DescriptionDefinitiongetIsGroundAdjustedNodeActive()Code
178 | function GroundAdjustedNodes:getIsGroundAdjustedNodeActive(groundAdjustedNode) |
179 | return true |
180 | end |
groundAdjustRaycastCallback
DescriptionRaycast callbackDefinition
groundAdjustRaycastCallback(integer transformId, float x, float y, float z, float distance)Arguments
integer | transformId | id raycasted object |
float | x | x raycast position |
float | y | y raycast position |
float | z | z raycast position |
float | distance | distance to raycast position |
189 | function GroundAdjustedNodes:groundAdjustRaycastCallback(transformId, x, y, z, distance) |
190 | self.lastRaycastDistance = distance; |
191 | end |
loadGroundAdjustedNodeFromXML
DescriptionDefinitionloadGroundAdjustedNodeFromXML()Code
106 | function GroundAdjustedNodes:loadGroundAdjustedNodeFromXML(xmlFile, key, adjustedNode) |
107 | |
108 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, key.."#index", key.."#node") --FS17 to FS19 |
109 | |
110 | local node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, key.."#node"), self.i3dMappings) |
111 | if node == nil then |
112 | g_logManager:xmlWarning(self.configFileName, "Missing 'node' for groundAdjustedNode '%s'!", key) |
113 | return false |
114 | end |
115 | |
116 | local x, y, z = getTranslation(node) |
117 | adjustedNode.node = node |
118 | adjustedNode.x = x |
119 | adjustedNode.y = y |
120 | adjustedNode.z = z |
121 | adjustedNode.raycastNodes = {} |
122 | |
123 | local j = 0 |
124 | while true do |
125 | local raycastKey = string.format("%s.raycastNode(%d)", key, j) |
126 | if not hasXMLProperty(self.xmlFile, raycastKey) then |
127 | break |
128 | end |
129 | |
130 | local raycastNode = {} |
131 | if self:loadGroundAdjustedRaycastNodeFromXML(xmlFile, raycastKey, adjustedNode, raycastNode) then |
132 | table.insert(adjustedNode.raycastNodes, raycastNode) |
133 | end |
134 | |
135 | j = j + 1 |
136 | end |
137 | |
138 | if #adjustedNode.raycastNodes > 0 then |
139 | adjustedNode.minY = getXMLFloat(self.xmlFile, key.."#minY") or (y - 1) |
140 | adjustedNode.maxY = getXMLFloat(self.xmlFile, key.."#maxY") or (adjustedNode.minY + 1) |
141 | adjustedNode.yOffset = getXMLFloat(self.xmlFile, key.."#yOffset") or 0 |
142 | adjustedNode.moveSpeed = (getXMLFloat(self.xmlFile, key.."#moveSpeed") or 1) / 1000 |
143 | adjustedNode.targetY = y |
144 | adjustedNode.curY = y |
145 | else |
146 | g_logManager:xmlWarning(self.configFileName, "No raycastNodes defined for groundAdjustedNode '%s'!", key) |
147 | return false |
148 | end |
149 | |
150 | return true |
151 | end |
loadGroundAdjustedRaycastNodeFromXML
DescriptionDefinitionloadGroundAdjustedRaycastNodeFromXML()Code
155 | function GroundAdjustedNodes:loadGroundAdjustedRaycastNodeFromXML(xmlFile, key, groundAdjustedNode, raycastNode) |
156 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, key.."#index", key.."#node") --FS17 to FS19 |
157 | |
158 | local node = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key.."#node"), self.i3dMappings) |
159 | if node == nil then |
160 | g_logManager:xmlWarning(self.configFileName, "Missing 'node' for groundAdjustedNodes raycast '%s'!", key) |
161 | return false |
162 | end |
163 | |
164 | if getParent(groundAdjustedNode.node) ~= getParent(node) then |
165 | g_logManager:xmlWarning(self.configFileName, "Raycast node is not on the same hierarchy level as the groundAdjustedNode (%s)!", key) |
166 | return false |
167 | end |
168 | |
169 | local _,y1,_ = getTranslation(node) |
170 | raycastNode.node = node |
171 | raycastNode.yDiff = y1 - groundAdjustedNode.y |
172 | |
173 | return true |
174 | end |
onLoad
DescriptionDefinitiononLoad()Code
38 | function GroundAdjustedNodes:onLoad(savegame) |
39 | local spec = self.spec_groundAdjustedNodes |
40 | |
41 | spec.groundAdjustedNodes = {} |
42 | local i = 0 |
43 | while true do |
44 | local key = string.format("vehicle.groundAdjustedNodes.groundAdjustedNode(%d)", i) |
45 | if not hasXMLProperty(self.xmlFile, key) then |
46 | break |
47 | end |
48 | |
49 | local node = {} |
50 | if self:loadGroundAdjustedNodeFromXML(self.xmlFile, key, node) then |
51 | table.insert(spec.groundAdjustedNodes, node) |
52 | end |
53 | |
54 | i = i + 1 |
55 | end |
56 | end |
onUpdate
DescriptionDefinitiononUpdate()Code
60 | function GroundAdjustedNodes:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
61 | local spec = self.spec_groundAdjustedNodes |
62 | for _, adjustedNode in pairs(spec.groundAdjustedNodes) do |
63 | if adjustedNode.targetY ~= adjustedNode.curY then |
64 | if adjustedNode.targetY > adjustedNode.curY then |
65 | adjustedNode.curY = math.min(adjustedNode.curY + adjustedNode.moveSpeed*dt, adjustedNode.targetY) |
66 | else |
67 | adjustedNode.curY = math.max(adjustedNode.curY - adjustedNode.moveSpeed*dt, adjustedNode.targetY) |
68 | end |
69 | setTranslation(adjustedNode.node, adjustedNode.x, adjustedNode.curY, adjustedNode.z) |
70 | |
71 | if self.setMovingToolDirty ~= nil then |
72 | self:setMovingToolDirty(adjustedNode.node) |
73 | end |
74 | end |
75 | end |
76 | end |
onUpdateTick
DescriptionDefinitiononUpdateTick()Code
80 | function GroundAdjustedNodes:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
81 | local spec = self.spec_groundAdjustedNodes |
82 | for _, adjustedNode in ipairs(spec.groundAdjustedNodes) do |
83 | if self:getIsGroundAdjustedNodeActive(adjustedNode) then |
84 | local newY = adjustedNode.minY |
85 | |
86 | for _, raycastNode in ipairs(adjustedNode.raycastNodes) do |
87 | local x,y,z = getWorldTranslation(raycastNode.node) |
88 | local dx,dy,dz = localDirectionToWorld(raycastNode.node, 0, -1, 0) |
89 | |
90 | self.lastRaycastDistance = 0 |
91 | raycastClosest(x, y, z, dx, dy, dz, "groundAdjustRaycastCallback", 4, self) |
92 | if self.lastRaycastDistance ~= 0 then |
93 | newY = math.max(newY, adjustedNode.y - self.lastRaycastDistance + raycastNode.yDiff - adjustedNode.yOffset) |
94 | end |
95 | |
96 | newY = MathUtil.clamp(newY, adjustedNode.minY, adjustedNode.maxY) |
97 | adjustedNode.targetY = newY |
98 | _, adjustedNode.curY, _ = getTranslation(adjustedNode.node) |
99 | end |
100 | end |
101 | end |
102 | end |
prerequisitesPresent
DescriptionDefinitionprerequisitesPresent()Code
15 | function GroundAdjustedNodes.prerequisitesPresent(specializations) |
16 | return true |
17 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
30 | function GroundAdjustedNodes.registerEventListeners(vehicleType) |
31 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", GroundAdjustedNodes) |
32 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", GroundAdjustedNodes) |
33 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", GroundAdjustedNodes) |
34 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
21 | function GroundAdjustedNodes.registerFunctions(vehicleType) |
22 | SpecializationUtil.registerFunction(vehicleType, "loadGroundAdjustedNodeFromXML", GroundAdjustedNodes.loadGroundAdjustedNodeFromXML) |
23 | SpecializationUtil.registerFunction(vehicleType, "loadGroundAdjustedRaycastNodeFromXML", GroundAdjustedNodes.loadGroundAdjustedRaycastNodeFromXML) |
24 | SpecializationUtil.registerFunction(vehicleType, "getIsGroundAdjustedNodeActive", GroundAdjustedNodes.getIsGroundAdjustedNodeActive) |
25 | SpecializationUtil.registerFunction(vehicleType, "groundAdjustRaycastCallback", GroundAdjustedNodes.groundAdjustRaycastCallback) |
26 | end |