Script v1.4.4.0
- Handtools
- Events
- Objects
- Placeables
- Triggers
- Utils
- Vehicles
- Specializations
- AIVehicle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BuiltInCutterTrailer
- BunkerSiloCompacter
- Combine
- ConveyorBelt
- Cover
- CrabSteering
- Crawler
- Cultivator
- Cutter
- Cylindered
- Drivable
- DynamicMountAttacher
- Fillable
- FillActivatable
- FillVolume
- Foldable
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- FuelTrailer
- Honk
- HookLiftContainer
- HookLiftTrailer
- Leveler
- Lights
- LivestockTrailer
- ManureBarrel
- ManureSpreader
- MixerWagon
- Motorized
- Mountable
- Mower
- NonTabbable
- Overloading
- Pickup
- Pipe
- Plough
- PowerConsumer
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- RidgeMarker
- Roller
- Ropes
- RotorSpreader
- SemiTrailerFront
- Shovel
- SowingMachine
- SpeedRotatingParts
- Sprayer
- Steerable
- StrawBlower
- StumpCutter
- Tedder
- TensionBelts
- Trailer
- TreePlanter
- TreePlanterActivatable
- TreeSaw
- TurnOnVehicle
- Washable
- WaterTrailer
- Weeder
- WheelRotations
- Windrower
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkParticles
Engine v7.0.0.2
- General
- Entity
- Node
- Scenegraph
- Lighting
- Camera
- Shape
- Particle System
- Physics
- Spline
- Animation
- Overlays
- Sound
- Input
- XML
- Network
- Callbacks
- Text Rendering
- Terrain Detail
- Tire Track
- Editor
- Rendering
- String
- Math
- I3D
- Fillplanes
Foundation Reference
Weeder
DescriptionClass for all weedersFunctions
- initSpecialization
- prerequisitesPresent
- preLoad
- load
- delete
- readUpdateStream
- writeUpdateStream
- updateTick
- draw
- onAttach
- onDeactivate
- onDeactivateSounds
- loadWorkAreaFromXML
- getIsWorkAreaActive
- getDoGroundManipulation
- getDirtMultiplier
- doCheckSpeedLimit
- getDefaultSpeedLimit
- processWeederAreas
- loadGroundParticleMapping
initSpecialization
DescriptionCalled on specialization initializingDefinition
initSpecialization()Code
15 | function Weeder.initSpecialization() |
16 | WorkArea.registerAreaType("weeder"); |
17 | 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 Weeder.prerequisitesPresent(specializations) |
24 | return SpecializationUtil.hasSpecialization(WorkArea, specializations) and |
25 | SpecializationUtil.hasSpecialization(AttacherJoints, specializations); |
26 | end |
preLoad
DescriptionCalled before loadingDefinition
preLoad(table savegame)Arguments
table | savegame | savegame |
31 | function Weeder:preLoad(savegame) |
32 | self.loadWorkAreaFromXML = Utils.overwrittenFunction(self.loadWorkAreaFromXML, Weeder.loadWorkAreaFromXML); |
33 | self.doCheckSpeedLimit = Utils.overwrittenFunction(self.doCheckSpeedLimit, Weeder.doCheckSpeedLimit); |
34 | self.getIsWorkAreaActive = Utils.overwrittenFunction(self.getIsWorkAreaActive, Weeder.getIsWorkAreaActive); |
35 | self.loadGroundParticleMapping = Utils.overwrittenFunction(self.loadGroundParticleMapping, Weeder.loadGroundParticleMapping); |
36 | |
37 | self.processWeederAreas = Weeder.processWeederAreas; |
38 | end |
load
DescriptionCalled on loadingDefinition
load(table savegame)Arguments
table | savegame | savegame |
43 | function Weeder:load(savegame) |
44 | |
45 | if self.isClient then |
46 | self.sampleWeeder = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.weederSound", nil, self.baseDirectory); |
47 | end |
48 | |
49 | self.startActivationTimeout = 2000; |
50 | self.startActivationTime = 0; |
51 | |
52 | self.showFieldNotOwnedWarning = false; |
53 | self.isWeederSpeedLimitActive = false; |
54 | self.weederHasGroundContact = false |
55 | |
56 | -- ai setup |
57 | table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.sowingValue, g_currentMission.sowingValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels}); |
58 | table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.sowingWidthValue, g_currentMission.sowingWidthValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels}); |
59 | table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.grassValue, g_currentMission.grassValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels}) |
60 | |
61 | table.insert(self.terrainDetailProhibitValueRanges, {1, 1, g_currentMission.sprayFirstChannel, g_currentMission.sprayNumChannels}); |
62 | table.insert(self.terrainDetailProhibitValueRanges, {g_currentMission.sprayLevelMaxValue, g_currentMission.sprayLevelMaxValue, g_currentMission.sprayLevelFirstChannel, g_currentMission.sprayLevelNumChannels}); |
63 | |
64 | self.weederDirtyFlag = self:getNextDirtyFlag(); |
65 | end |
delete
DescriptionCalled on deletingDefinition
delete()Code
69 | function Weeder:delete() |
70 | if self.isClient then |
71 | SoundUtil.deleteSample(self.sampleWeeder); |
72 | end |
73 | end |
readUpdateStream
DescriptionCalled on on updateDefinition
readUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | stream ID |
integer | timestamp | timestamp |
table | connection | connection |
86 | function Weeder:readUpdateStream(streamId, timestamp, connection) |
87 | if connection:getIsServer() then |
88 | self.weederHasGroundContact = streamReadBool(streamId); |
89 | self.showFieldNotOwnedWarning = streamReadBool(streamId); |
90 | end |
91 | end |
writeUpdateStream
DescriptionCalled on on updateDefinition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)Arguments
integer | streamId | stream ID |
table | connection | connection |
integer | dirtyMask | dirty mask |
98 | function Weeder:writeUpdateStream(streamId, connection, dirtyMask) |
99 | if not connection:getIsServer() then |
100 | streamWriteBool(streamId, self.weederHasGroundContact); |
101 | streamWriteBool(streamId, self.showFieldNotOwnedWarning); |
102 | end |
103 | end |
updateTick
DescriptionCalled on update tickDefinition
updateTick(float dt)Arguments
float | dt | time since last call in ms |
117 | function Weeder:updateTick(dt) |
118 | self.isWeederSpeedLimitActive = false; |
119 | if self:getIsActive() then |
120 | local showFieldNotOwnedWarning = false; |
121 | |
122 | if self.isServer then |
123 | local hasGroundContact = self:getIsTypedWorkAreaActive(WorkArea.AREATYPE_WEEDER); |
124 | if self.weederHasGroundContact ~= hasGroundContact then |
125 | self:raiseDirtyFlags(self.weederDirtyFlag); |
126 | self.weederHasGroundContact = hasGroundContact; |
127 | end; |
128 | end; |
129 | local hasGroundContact = self.weederHasGroundContact; |
130 | |
131 | self.doGroundManipulation = (self.movingDirection > 0 and hasGroundContact and (not self.onlyActiveWhenLowered or self:isLowered(false)) and self.startActivationTime <= g_currentMission.time); |
132 | |
133 | if self.doGroundManipulation then |
134 | if self.weederColorParticleSystems ~= nil then |
135 | for _, mapping in pairs(self.weederColorParticleSystems) do |
136 | local wx, wy, wz = getWorldTranslation(mapping.node); |
137 | |
138 | local densityBits = getDensityAtWorldPos(g_currentMission.terrainDetailId, wx, wy, wz); |
139 | local isOnField = densityBits ~= 0; |
140 | |
141 | if isOnField then |
142 | mapping.lastColor[1], mapping.lastColor[2], mapping.lastColor[3], _ = Utils.getTireTrackColorFromDensityBits(densityBits) |
143 | else |
144 | mapping.lastColor[1], mapping.lastColor[2], mapping.lastColor[3], _, _ = getTerrainAttributesAtWorldPos(g_currentMission.terrainRootNode, wx, wy, wz, true, true, true, true, false); |
145 | end |
146 | |
147 | -- interpolate between different ground colors to avoid unrealisitic particle color changes |
148 | if mapping.targetColor == nil then |
149 | mapping.targetColor = {mapping.lastColor[1],mapping.lastColor[2],mapping.lastColor[3]}; |
150 | mapping.currentColor = {mapping.lastColor[1],mapping.lastColor[2],mapping.lastColor[3]}; |
151 | mapping.alpha = 1; |
152 | end; |
153 | |
154 | if mapping.alpha ~= 1 then |
155 | mapping.alpha = math.min(mapping.alpha + dt/1000, 1); |
156 | mapping.currentColor = {Utils.vector3ArrayLerp(mapping.lastColor, mapping.targetColor, mapping.alpha)}; |
157 | if mapping.alpha == 1 then |
158 | mapping.lastColor = {mapping.currentColor[1], mapping.currentColor[2], mapping.currentColor[3]}; |
159 | end; |
160 | end; |
161 | |
162 | if mapping.alpha == 1 and mapping.lastColor[1] ~= mapping.targetColor[1] and mapping.lastColor[2] ~= mapping.targetColor[2] and mapping.lastColor[3] ~= mapping.targetColor[3] then |
163 | mapping.alpha = 0; |
164 | mapping.targetColor = {mapping.lastColor[1], mapping.lastColor[2], mapping.lastColor[3]}; |
165 | end; |
166 | |
167 | setShaderParameter(mapping.particleSystem.shape, "psColor", mapping.currentColor[1], mapping.currentColor[2], mapping.currentColor[3], 1, false); |
168 | end; |
169 | end |
170 | |
171 | self.isWeederSpeedLimitActive = true; |
172 | if self.isServer then |
173 | local workAreas, showWarning, _ = self:getTypedNetworkAreas(WorkArea.AREATYPE_WEEDER, true); |
174 | showFieldNotOwnedWarning = showWarning; |
175 | |
176 | if #workAreas > 0 then |
177 | local totalNumPixels = self:processWeederAreas(workAreas); |
178 | local ha = Utils.areaToHa(totalNumPixels, g_currentMission:getFruitPixelsToSqm()); |
179 | g_currentMission.missionStats:updateStats("workedHectares", ha); |
180 | end; |
181 | end; |
182 | g_currentMission.missionStats:updateStats("workedTime", dt/(1000*60)); |
183 | end |
184 | |
185 | if self.isClient then |
186 | if self.doGroundManipulation and self:getLastSpeed() > 3 then |
187 | if self:getIsActiveForSound() then |
188 | SoundUtil.playSample(self.sampleWeeder, 0, 0, nil); |
189 | end; |
190 | else |
191 | SoundUtil.stopSample(self.sampleWeeder); |
192 | end; |
193 | end; |
194 | |
195 | if self.isServer then |
196 | if showFieldNotOwnedWarning ~= self.showFieldNotOwnedWarning then |
197 | self.showFieldNotOwnedWarning = showFieldNotOwnedWarning; |
198 | self:raiseDirtyFlags(self.weederDirtyFlag); |
199 | end |
200 | end |
201 | end; |
202 | end |
draw
DescriptionCalled on drawDefinition
draw()Code
206 | function Weeder:draw() |
207 | if self.isClient then |
208 | if self.showFieldNotOwnedWarning then |
209 | g_currentMission:showBlinkingWarning(g_i18n:getText("warning_youDontOwnThisField")); |
210 | end |
211 | end |
212 | end |
onAttach
DescriptionCalled if vehicle gets attachedDefinition
onAttach(table attacherVehicle)Arguments
table | attacherVehicle | attacher vehicle |
217 | function Weeder:onAttach(attacherVehicle) |
218 | self.startActivationTime = g_currentMission.time + self.startActivationTimeout; |
219 | end; |
onDeactivate
DescriptionCalled on deactivateDefinition
onDeactivate()Code
223 | function Weeder:onDeactivate() |
224 | self.showFieldNotOwnedWarning = false; |
225 | end |
onDeactivateSounds
DescriptionCalled on deactivating soundsDefinition
onDeactivateSounds()Code
229 | function Weeder:onDeactivateSounds() |
230 | if self.isClient then |
231 | SoundUtil.stopSample(self.sampleWeeder, true); |
232 | end |
233 | end |
loadWorkAreaFromXML
DescriptionLoads work areas from xmlDefinition
loadWorkAreaFromXML(table workArea, integer xmlFile, string key)Arguments
table | workArea | workArea |
integer | xmlFile | id of xml object |
string | key | key |
boolean | success | success |
241 | function Weeder:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key) |
242 | local retValue = true; |
243 | if superFunc ~= nil then |
244 | retValue = superFunc(self, workArea, xmlFile, key) |
245 | end |
246 | |
247 | if workArea.type == WorkArea.AREATYPE_DEFAULT then |
248 | workArea.type = WorkArea.AREATYPE_WEEDER; |
249 | end |
250 | |
251 | return retValue; |
252 | end |
getIsWorkAreaActive
DescriptionReturns true if work area is activeDefinition
getIsWorkAreaActive(table workArea)Arguments
table | workArea | workArea |
boolean | isActive | work area is active |
258 | function Weeder:getIsWorkAreaActive(superFunc, workArea) |
259 | if workArea.type == WorkArea.AREATYPE_WEEDER and (workArea.refNode ~= nil and workArea.refNode.isActive) then |
260 | return true |
261 | end |
262 | |
263 | if superFunc ~= nil then |
264 | return superFunc(self, workArea); |
265 | end |
266 | return true; |
267 | end; |
getDoGroundManipulation
DescriptionReturns if tool does ground manipulationDefinition
getDoGroundManipulation()Return Values
boolean | doGroundManipulation | do ground manipulation |
272 | function Weeder:getDoGroundManipulation(superFunc) |
273 | if not self.doGroundManipulation then |
274 | return false; |
275 | end; |
276 | |
277 | if superFunc ~= nil then |
278 | return superFunc(self); |
279 | end |
280 | return true; |
281 | end; |
getDirtMultiplier
DescriptionReturns current dirt multiplierDefinition
getDirtMultiplier()Return Values
float | dirtMultiplier | current dirt multiplier |
286 | function Weeder:getDirtMultiplier(superFunc) |
287 | local multiplier = 0; |
288 | if superFunc ~= nil then |
289 | multiplier = multiplier + superFunc(self); |
290 | end; |
291 | |
292 | if self.doGroundManipulation then |
293 | multiplier = multiplier + self.workMultiplier * self:getLastSpeed() / self.speedLimit; |
294 | end; |
295 | |
296 | return multiplier; |
297 | end; |
doCheckSpeedLimit
DescriptionReturns if speed limit should be checkedDefinition
doCheckSpeedLimit()Return Values
boolean | checkSpeedlimit | check speed limit |
302 | function Weeder:doCheckSpeedLimit(superFunc) |
303 | local parent = false; |
304 | if superFunc ~= nil then |
305 | parent = superFunc(self); |
306 | end |
307 | |
308 | return parent or self.isWeederSpeedLimitActive; |
309 | end; |
getDefaultSpeedLimit
DescriptionReturns default speed limitDefinition
getDefaultSpeedLimit()Return Values
float | speedLimit | speed limit |
314 | function Weeder.getDefaultSpeedLimit() |
315 | return 15; |
316 | end |
processWeederAreas
DescriptionProcess weeder areasDefinition
processWeederAreas(table workAreas)Arguments
table | workAreas | work areas to process |
float | totalNumPixels | total number of pixels changed |
322 | function Weeder:processWeederAreas(workAreas) |
323 | local totalNumPixels = 0; |
324 | for _, area in pairs(workAreas) do |
325 | totalNumPixels = totalNumPixels + Utils.updateWeederArea(area[1], area[2], area[3], area[4], area[5], area[6]); |
326 | end; |
327 | return totalNumPixels; |
328 | end; |
loadGroundParticleMapping
DescriptionLoad ground particle mapping from xml fileDefinition
loadGroundParticleMapping(integer xmlFile, string key, table mapping, integer index, integer i3dNode)Arguments
integer | xmlFile | id of xml object |
string | key | key |
table | mapping | mapping |
integer | index | index |
integer | i3dNode | id of i3d node |
boolean | success | success |
338 | function Weeder:loadGroundParticleMapping(superFunc, xmlFile, key, mapping, index, i3dNode) |
339 | if superFunc ~= nil then |
340 | if not superFunc(self, xmlFile, key, mapping, index, i3dNode) then |
341 | return false |
342 | end |
343 | end; |
344 | |
345 | mapping.adjustColor = Utils.getNoNil(getXMLBool(xmlFile, key.."#adjustColor"), false) |
346 | if mapping.adjustColor then |
347 | if self.weederColorParticleSystems == nil then |
348 | self.weederColorParticleSystems = {} |
349 | end |
350 | mapping.lastColor = {} |
351 | |
352 | table.insert(self.weederColorParticleSystems, mapping) |
353 | end |
354 | |
355 | return true; |
356 | end; |