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
GroundReference
DescriptionSpecialization for determining if nodes are within a given distance threshold to the terrain/gorund.Functions
- checkMovingPartDirtyUpdateNode
- getGroundReferenceNodeFromIndex
- getIsGroundReferenceNodeActive
- getIsGroundReferenceNodeThreshold
- getIsSpeedRotatingPartActive
- getPowerMultiplier
- initSpecialization
- loadGroundReferenceNode
- loadSpeedRotatingPartFromXML
- onLoad
- onReadUpdateStream
- onUpdateTick
- onWriteUpdateStream
- prerequisitesPresent
- registerEventListeners
- registerEvents
- registerFunctions
- registerOverwrittenFunctions
- updateGroundReferenceNode
checkMovingPartDirtyUpdateNode
DescriptionDefinitioncheckMovingPartDirtyUpdateNode()Code
297 | function GroundReference:checkMovingPartDirtyUpdateNode(superFunc, node, movingPart) |
298 | superFunc(self, node, movingPart) |
299 | |
300 | local spec = self.spec_groundReference |
301 | for i=1, #spec.groundReferenceNodes do |
302 | local groundReferenceNode = spec.groundReferenceNodes[i] |
303 | if node == groundReferenceNode.node then |
304 | Logging.xmlError(self.xmlFile, "Found ground reference node '%s' in active dirty moving part '%s' with limited update distance. Remove limit or adjust hierarchy for correct function. (maxUpdateDistance='-')", getName(node), getName(movingPart.node)) |
305 | end |
306 | end |
307 | end |
getGroundReferenceNodeFromIndex
DescriptionDefinitiongetGroundReferenceNodeFromIndex()Code
213 | function GroundReference:getGroundReferenceNodeFromIndex(refNodeIndex) |
214 | local spec = self.spec_groundReference |
215 | return spec.groundReferenceNodes[refNodeIndex] |
216 | end |
getIsGroundReferenceNodeActive
DescriptionDefinitiongetIsGroundReferenceNodeActive()Code
220 | function GroundReference:getIsGroundReferenceNodeActive(groundReferenceNode) |
221 | return groundReferenceNode.isActive |
222 | end |
getIsGroundReferenceNodeThreshold
DescriptionDefinitiongetIsGroundReferenceNodeThreshold()Code
226 | function GroundReference:getIsGroundReferenceNodeThreshold(groundReferenceNode) |
227 | return groundReferenceNode.threshold |
228 | end |
getIsSpeedRotatingPartActive
DescriptionDefinitiongetIsSpeedRotatingPartActive()Code
278 | function GroundReference:getIsSpeedRotatingPartActive(superFunc, speedRotatingPart) |
279 | if speedRotatingPart.groundReferenceNodeIndex ~= nil then |
280 | local spec = self.spec_groundReference |
281 | |
282 | if spec.groundReferenceNodes[speedRotatingPart.groundReferenceNodeIndex] ~= nil then |
283 | if not spec.groundReferenceNodes[speedRotatingPart.groundReferenceNodeIndex].isActive then |
284 | return false |
285 | end |
286 | else |
287 | Logging.xmlWarning(self.xmlFile, "Unknown ground reference node index '%d' for speed rotating part '%s'! Indices start with 1!", speedRotatingPart.groundReferenceNodeIndex, getName(speedRotatingPart.repr or speedRotatingPart.shaderNode)) |
288 | speedRotatingPart.groundReferenceNodeIndex = nil |
289 | end |
290 | end |
291 | |
292 | return superFunc(self, speedRotatingPart) |
293 | end |
getPowerMultiplier
DescriptionDefinitiongetPowerMultiplier()Code
232 | function GroundReference:getPowerMultiplier(superFunc) |
233 | local powerMultiplier = superFunc(self) |
234 | |
235 | local spec = self.spec_groundReference |
236 | if #(spec.groundReferenceNodes) > 0 then |
237 | local factor = 0 |
238 | if spec.hasForceFactors then |
239 | for _, refNode in ipairs(spec.groundReferenceNodes) do |
240 | if refNode.isActive then |
241 | factor = factor + refNode.forceFactor |
242 | end |
243 | end |
244 | else |
245 | for _, refNode in ipairs(spec.groundReferenceNodes) do |
246 | if refNode.isActive then |
247 | factor = refNode.chargeValue |
248 | end |
249 | end |
250 | end |
251 | |
252 | powerMultiplier = powerMultiplier * factor |
253 | end |
254 | return powerMultiplier |
255 | end |
initSpecialization
DescriptionCalled on specialization initializingDefinition
initSpecialization()Code
22 | function GroundReference.initSpecialization() |
23 | local schema = Vehicle.xmlSchema |
24 | schema:setXMLSpecializationType("GroundReference") |
25 | |
26 | local basePath = GroundReference.GROUND_REFERENCE_XML_KEY |
27 | |
28 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#node", "Ground reference node") |
29 | |
30 | schema:register(XMLValueType.FLOAT, basePath .. "#threshold", "Threshold", 0) |
31 | schema:register(XMLValueType.BOOL, basePath .. "#onlyActiveWhenLowered", "Node is only active when tool is lowered", true) |
32 | schema:register(XMLValueType.FLOAT, basePath .. "#chargeValue", "Charge value to calculate power consumption", 1) |
33 | schema:register(XMLValueType.FLOAT, basePath .. "#forceFactor", "Ground force factor") |
34 | schema:register(XMLValueType.FLOAT, basePath .. "#maxActivationDepth", "Max. activation depth", 10) |
35 | |
36 | schema:register(XMLValueType.INT, SpeedRotatingParts.SPEED_ROTATING_PART_XML_KEY .. "#groundReferenceNodeIndex", "Ground reference node index") |
37 | |
38 | schema:setXMLSpecializationType() |
39 | end |
loadGroundReferenceNode
DescriptionDefinitionloadGroundReferenceNode()Code
155 | function GroundReference:loadGroundReferenceNode(xmlFile, baseName, entry) |
156 | XMLUtil.checkDeprecatedXMLElements(xmlFile, baseName .. "#index", baseName .. "#node") --FS17 to FS19 |
157 | local spec = self.spec_groundReference |
158 | |
159 | local node = xmlFile:getValue(baseName .. "#node", nil, self.components, self.i3dMappings) |
160 | if node ~= nil then |
161 | entry.node = node |
162 | entry.threshold = xmlFile:getValue(baseName .. "#threshold", 0) |
163 | entry.onlyActiveWhenLowered = xmlFile:getValue(baseName .. "#onlyActiveWhenLowered", true) |
164 | entry.chargeValue = xmlFile:getValue(baseName .. "#chargeValue", 1) |
165 | entry.forceFactor = xmlFile:getValue(baseName .. "#forceFactor") |
166 | if entry.forceFactor ~= nil then |
167 | spec.hasForceFactors = true |
168 | end |
169 | entry.forceFactor = entry.forceFactor or 1 |
170 | entry.maxActivationDepth = xmlFile:getValue(baseName .. "#maxActivationDepth", 10) -- maximum depth below the terrain -> prevents display in 3d shop |
171 | entry.isActive = false |
172 | return true |
173 | end |
174 | return false |
175 | end |
loadSpeedRotatingPartFromXML
DescriptionDefinitionloadSpeedRotatingPartFromXML()Code
260 | function GroundReference:loadSpeedRotatingPartFromXML(superFunc, speedRotatingPart, xmlFile, key) |
261 | if not superFunc(self, speedRotatingPart, xmlFile, key) then |
262 | return false |
263 | end |
264 | |
265 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#refNodeIndex", key.."#groundReferenceNodeIndex") -- FS17 to FS19 |
266 | |
267 | speedRotatingPart.groundReferenceNodeIndex = xmlFile:getValue(key.."#groundReferenceNodeIndex") |
268 | |
269 | if speedRotatingPart.groundReferenceNodeIndex ~= nil and speedRotatingPart.groundReferenceNodeIndex == 0 then |
270 | Logging.xmlWarning(self.xmlFile, "Unknown ground reference node index '%d' in '%s'! Indices start with 1!", speedRotatingPart.groundReferenceNodeIndex, key) |
271 | end |
272 | |
273 | return true |
274 | end |
onLoad
DescriptionDefinitiononLoad()Code
76 | function GroundReference:onLoad(savegame) |
77 | local spec = self.spec_groundReference |
78 | |
79 | spec.hasForceFactors = false |
80 | spec.groundReferenceNodes = {} |
81 | local i = 0 |
82 | while true do |
83 | local baseName = string.format("vehicle.groundReferenceNodes.groundReferenceNode(%d)", i) |
84 | if not self.xmlFile:hasProperty(baseName) then |
85 | break |
86 | end |
87 | local entry = {} |
88 | if self:loadGroundReferenceNode(self.xmlFile, baseName, entry) then |
89 | table.insert(spec.groundReferenceNodes, entry) |
90 | end |
91 | i = i + 1 |
92 | end |
93 | |
94 | -- normalize chargeValues |
95 | -- deprecated: to be removed in FS21 |
96 | local totalCharge = 0 |
97 | for _, refNode in pairs(spec.groundReferenceNodes) do |
98 | totalCharge = totalCharge + refNode.chargeValue |
99 | end |
100 | if totalCharge > 0 then |
101 | for _, refNode in pairs(spec.groundReferenceNodes) do |
102 | refNode.chargeValue = refNode.chargeValue / totalCharge |
103 | end |
104 | end |
105 | |
106 | -- normalize forceFactors |
107 | local forceFactorSum = 0 |
108 | for _, refNode in pairs(spec.groundReferenceNodes) do |
109 | forceFactorSum = forceFactorSum + refNode.forceFactor |
110 | end |
111 | if forceFactorSum > 0 then |
112 | for _, refNode in pairs(spec.groundReferenceNodes) do |
113 | refNode.forceFactor = refNode.forceFactor / forceFactorSum |
114 | end |
115 | end |
116 | |
117 | if #spec.groundReferenceNodes == 0 then |
118 | SpecializationUtil.removeEventListener(self, "onUpdateTick", GroundReference) |
119 | end |
120 | end |
onReadUpdateStream
DescriptionDefinitiononReadUpdateStream()Code
124 | function GroundReference:onReadUpdateStream(streamId, timestamp, connection) |
125 | local spec = self.spec_groundReference |
126 | if connection:getIsServer() then |
127 | for _,groundReferenceNode in ipairs(spec.groundReferenceNodes) do |
128 | groundReferenceNode.isActive = streamReadBool(streamId) |
129 | end |
130 | end |
131 | end |
onUpdateTick
DescriptionDefinitiononUpdateTick()Code
146 | function GroundReference:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
147 | local spec = self.spec_groundReference |
148 | for _,groundReferenceNode in ipairs(spec.groundReferenceNodes) do |
149 | self:updateGroundReferenceNode(groundReferenceNode) |
150 | end |
151 | end |
onWriteUpdateStream
DescriptionDefinitiononWriteUpdateStream()Code
135 | function GroundReference:onWriteUpdateStream(streamId, connection, dirtyMask) |
136 | local spec = self.spec_groundReference |
137 | if not connection:getIsServer() then |
138 | for _,groundReferenceNode in ipairs(spec.groundReferenceNodes) do |
139 | streamWriteBool(streamId, groundReferenceNode.isActive) |
140 | end |
141 | end |
142 | end |
prerequisitesPresent
DescriptionDefinitionprerequisitesPresent()Code
16 | function GroundReference.prerequisitesPresent(specializations) |
17 | return true |
18 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
67 | function GroundReference.registerEventListeners(vehicleType) |
68 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", GroundReference) |
69 | SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", GroundReference) |
70 | SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", GroundReference) |
71 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", GroundReference) |
72 | end |
registerEvents
DescriptionDefinitionregisterEvents()Code
43 | function GroundReference.registerEvents(vehicleType) |
44 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
48 | function GroundReference.registerFunctions(vehicleType) |
49 | SpecializationUtil.registerFunction(vehicleType, "loadGroundReferenceNode", GroundReference.loadGroundReferenceNode) |
50 | SpecializationUtil.registerFunction(vehicleType, "updateGroundReferenceNode", GroundReference.updateGroundReferenceNode) |
51 | SpecializationUtil.registerFunction(vehicleType, "getGroundReferenceNodeFromIndex", GroundReference.getGroundReferenceNodeFromIndex) |
52 | SpecializationUtil.registerFunction(vehicleType, "getIsGroundReferenceNodeActive", GroundReference.getIsGroundReferenceNodeActive) |
53 | SpecializationUtil.registerFunction(vehicleType, "getIsGroundReferenceNodeThreshold", GroundReference.getIsGroundReferenceNodeThreshold) |
54 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
58 | function GroundReference.registerOverwrittenFunctions(vehicleType) |
59 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getPowerMultiplier", GroundReference.getPowerMultiplier) |
60 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadSpeedRotatingPartFromXML", GroundReference.loadSpeedRotatingPartFromXML) |
61 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsSpeedRotatingPartActive", GroundReference.getIsSpeedRotatingPartActive) |
62 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "checkMovingPartDirtyUpdateNode", GroundReference.checkMovingPartDirtyUpdateNode) |
63 | end |
updateGroundReferenceNode
DescriptionDefinitionupdateGroundReferenceNode()Code
179 | function GroundReference:updateGroundReferenceNode(groundReferenceNode) |
180 | if self.isServer then |
181 | local activeLowered = true |
182 | if groundReferenceNode.onlyActiveWhenLowered then |
183 | if self.getIsLowered ~= nil then |
184 | if not self:getIsLowered(false) then |
185 | activeLowered = false |
186 | end |
187 | end |
188 | end |
189 | |
190 | local threshold = self:getIsGroundReferenceNodeThreshold(groundReferenceNode) |
191 | |
192 | local x,y,z = getWorldTranslation(groundReferenceNode.node) |
193 | local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x,y,z) |
194 | |
195 | local terrainDiff = (terrainHeight + threshold) - y |
196 | local terrainActiv = terrainDiff > 0 and terrainDiff < groundReferenceNode.maxActivationDepth |
197 | |
198 | local densityHeight, _ = DensityMapHeightUtil.getHeightAtWorldPos(x,y,z) |
199 | local densityDiff = (densityHeight + threshold) - y |
200 | local densityActiv = densityDiff > 0 and densityDiff < groundReferenceNode.maxActivationDepth |
201 | |
202 | groundReferenceNode.isActive = activeLowered and (terrainActiv or densityActiv) |
203 | |
204 | --#debug if VehicleDebug.state == VehicleDebug.DEBUG_ATTRIBUTES then |
205 | --#debug DebugUtil.drawDebugNode(groundReferenceNode.node, "", false, 0) |
206 | --#debug drawDebugLine(x, y, z, groundReferenceNode.isActive and 0 or 1, groundReferenceNode.isActive and 1 or 0, 0, x, terrainHeight, z, groundReferenceNode.isActive and 0 or 1, groundReferenceNode.isActive and 1 or 0, 0, true) |
207 | --#debug end |
208 | end |
209 | end |