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
Cultivator
DescriptionClass for all cultivatorsFunctions
- initSpecialization
- prerequisitesPresent
- preLoad
- load
- delete
- readUpdateStream
- writeUpdateStream
- updateTick
- draw
- onAttach
- onDetach
- onEnter
- onDeactivate
- onDeactivateSounds
- onAiTurnOn
- onAiTurnOff
- doCheckSpeedLimit
- getDoGroundManipulation
- getIsReadyToSpray
- getDirtMultiplier
- loadWorkAreaFromXML
- getDefaultSpeedLimit
- processCultivatorAreas
initSpecialization
DescriptionCalled on specialization initializingDefinition
initSpecialization()Code
15 | function Cultivator.initSpecialization() |
16 | WorkArea.registerAreaType("cultivator"); |
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 Cultivator.prerequisitesPresent(specializations) |
24 | return SpecializationUtil.hasSpecialization(WorkArea, specializations); |
25 | end; |
preLoad
DescriptionCalled before loadingDefinition
preLoad(table savegame)Arguments
table | savegame | savegame |
30 | function Cultivator:preLoad(savegame) |
31 | self.loadWorkAreaFromXML = Utils.overwrittenFunction(self.loadWorkAreaFromXML, Cultivator.loadWorkAreaFromXML); |
32 | end |
load
DescriptionCalled on loadingDefinition
load(table savegame)Arguments
table | savegame | savegame |
37 | function Cultivator:load(savegame) |
38 | |
39 | self.getDoGroundManipulation = Utils.overwrittenFunction(self.getDoGroundManipulation, Cultivator.getDoGroundManipulation); |
40 | self.doCheckSpeedLimit = Utils.overwrittenFunction(self.doCheckSpeedLimit, Cultivator.doCheckSpeedLimit); |
41 | self.getDirtMultiplier = Utils.overwrittenFunction(self.getDirtMultiplier, Cultivator.getDirtMultiplier); |
42 | self.getIsReadyToSpray = Utils.overwrittenFunction(self.getIsReadyToSpray, Cultivator.getIsReadyToSpray); |
43 | |
44 | self.processCultivatorAreas = Cultivator.processCultivatorAreas; |
45 | |
46 | if hasXMLProperty(self.xmlFile, "vehicle.drum#index") then |
47 | print("Warning: vehicle.drum is not supported anymore, use vehicle.speedRotatingParts.speedRotatingPart instead"); |
48 | end; |
49 | |
50 | if next(self.groundReferenceNodes) == nil then |
51 | print("Warning: No ground reference nodes in "..self.configFileName); |
52 | end; |
53 | |
54 | if self.isClient then |
55 | self.sampleCultivator = SoundUtil.loadSample(self.xmlFile, {}, "vehicle.cultivatorSound", nil, self.baseDirectory); |
56 | end; |
57 | |
58 | self.cultivatorDirectionNode = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.cultivatorDirectionNode#index")), self.components[1].node); |
59 | |
60 | self.onlyActiveWhenLowered = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.onlyActiveWhenLowered#value"), true); |
61 | |
62 | table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.ploughValue, g_currentMission.ploughValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels}); |
63 | table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.sowingValue, g_currentMission.sowingValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels}); |
64 | table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.sowingWidthValue, g_currentMission.sowingWidthValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels}); |
65 | table.insert(self.terrainDetailRequiredValueRanges, {g_currentMission.grassValue, g_currentMission.grassValue, g_currentMission.terrainDetailTypeFirstChannel, g_currentMission.terrainDetailTypeNumChannels}); |
66 | |
67 | self.startActivationTimeout = 2000; |
68 | self.startActivationTime = 0; |
69 | |
70 | self.cultivatorHasGroundContact = false; |
71 | self.doGroundManipulation = false; |
72 | self.cultivatorLimitToField = false; |
73 | self.cultivatorForceLimitToField = true; |
74 | self.lastCultivatorArea = 0; |
75 | |
76 | self.isCultivatorSpeedLimitActive = false; |
77 | |
78 | self.showFieldNotOwnedWarning = false; |
79 | |
80 | self.cultivatorGroundContactFlag = self:getNextDirtyFlag(); |
81 | end; |
delete
DescriptionCalled on deletingDefinition
delete()Code
85 | function Cultivator:delete() |
86 | if self.isClient then |
87 | SoundUtil.deleteSample(self.sampleCultivator); |
88 | end; |
89 | end; |
readUpdateStream
DescriptionCalled on on updateDefinition
readUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | stream ID |
integer | timestamp | timestamp |
table | connection | connection |
96 | function Cultivator:readUpdateStream(streamId, timestamp, connection) |
97 | if connection:getIsServer() then |
98 | self.cultivatorHasGroundContact = streamReadBool(streamId); |
99 | self.showFieldNotOwnedWarning = streamReadBool(streamId); |
100 | end; |
101 | 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 |
108 | function Cultivator:writeUpdateStream(streamId, connection, dirtyMask) |
109 | if not connection:getIsServer() then |
110 | streamWriteBool(streamId, self.cultivatorHasGroundContact); |
111 | streamWriteBool(streamId, self.showFieldNotOwnedWarning); |
112 | end; |
113 | end; |
updateTick
DescriptionCalled on update tickDefinition
updateTick(float dt)Arguments
float | dt | time since last call in ms |
127 | function Cultivator:updateTick(dt) |
128 | self.isCultivatorSpeedLimitActive = false; |
129 | if self:getIsActive() then |
130 | self.lastCultivatorArea = 0; |
131 | local showFieldNotOwnedWarning = false; |
132 | |
133 | if self.isServer then |
134 | local hasGroundContact = self:getIsTypedWorkAreaActive(WorkArea.AREATYPE_CULTIVATOR); |
135 | if self.cultivatorHasGroundContact ~= hasGroundContact then |
136 | self:raiseDirtyFlags(self.cultivatorGroundContactFlag); |
137 | self.cultivatorHasGroundContact = hasGroundContact; |
138 | end; |
139 | end; |
140 | local hasGroundContact = self.cultivatorHasGroundContact; |
141 | |
142 | self.doGroundManipulation = (hasGroundContact and (not self.onlyActiveWhenLowered or self:isLowered(false)) and self.startActivationTime <= g_currentMission.time); |
143 | |
144 | local foldAnimTime = self.foldAnimTime; |
145 | if self.doGroundManipulation then |
146 | self.isCultivatorSpeedLimitActive = true; |
147 | local workAreas, showWarning, _ = self:getTypedNetworkAreas(WorkArea.AREATYPE_CULTIVATOR, true); |
148 | |
149 | if self.isServer then |
150 | showFieldNotOwnedWarning = showWarning; |
151 | |
152 | if table.getn(workAreas) > 0 then |
153 | local limitToField = self.cultivatorLimitToField or self.cultivatorForceLimitToField; |
154 | local limitGrassDestructionToField = self.cultivatorLimitToField or self.cultivatorForceLimitToField; |
155 | if not g_currentMission:getHasPermission("createFields", self:getOwner()) or g_currentMission.fieldJobManager:isFieldJobActive() then |
156 | limitToField = true; |
157 | limitGrassDestructionToField = true; |
158 | end; |
159 | |
160 | local dx,dy,dz = localDirectionToWorld(self.cultivatorDirectionNode, 0, 0, 1); |
161 | local angle = Utils.convertToDensityMapAngle(Utils.getYRotationFromDirection(dx, dz), g_currentMission.terrainDetailAngleMaxValue); |
162 | |
163 | local realArea = self:processCultivatorAreas(workAreas, limitToField, limitGrassDestructionToField, angle); |
164 | |
165 | self.lastCultivatorArea = Utils.areaToHa(realArea, g_currentMission:getFruitPixelsToSqm()); -- 4096px are mapped to 2048m |
166 | g_currentMission.missionStats:updateStats("cultivatedHectares", self.lastCultivatorArea); |
167 | g_currentMission.missionStats:updateStats("workedHectares", self.lastCultivatorArea); |
168 | end; |
169 | g_currentMission.missionStats:updateStats("cultivatedTime", dt/(1000*60)); |
170 | g_currentMission.missionStats:updateStats("workedTime", dt/(1000*60)); |
171 | end; |
172 | |
173 | -- remove tireTracks |
174 | for _, workArea in pairs(workAreas) do |
175 | Utils.eraseTireTrack(workArea[1], workArea[2], workArea[3], workArea[4], workArea[5], workArea[6]) |
176 | end |
177 | end |
178 | |
179 | if self.isClient then |
180 | if self.doGroundManipulation and self:getLastSpeed() > 3 then |
181 | if self:getIsActiveForSound() then |
182 | SoundUtil.playSample(self.sampleCultivator, 0, 0, nil); |
183 | end; |
184 | else |
185 | SoundUtil.stopSample(self.sampleCultivator); |
186 | end; |
187 | end; |
188 | |
189 | if self.isServer then |
190 | if showFieldNotOwnedWarning ~= self.showFieldNotOwnedWarning then |
191 | self.showFieldNotOwnedWarning = showFieldNotOwnedWarning; |
192 | self:raiseDirtyFlags(self.cultivatorGroundContactFlag); |
193 | end |
194 | end |
195 | end; |
196 | |
197 | end; |
draw
DescriptionCalled on drawDefinition
draw()Code
201 | function Cultivator:draw() |
202 | if self.showFieldNotOwnedWarning then |
203 | g_currentMission:showBlinkingWarning(g_i18n:getText("warning_youDontOwnThisField")); |
204 | end; |
205 | end; |
onAttach
DescriptionCalled if vehicle gets attachedDefinition
onAttach(table attacherVehicle)Arguments
table | attacherVehicle | attacher vehicle |
210 | function Cultivator:onAttach(attacherVehicle) |
211 | Cultivator.onActivate(self); |
212 | self.startActivationTime = g_currentMission.time + self.startActivationTimeout; |
213 | end; |
onDetach
DescriptionCalled if vehicle gets detachedDefinition
onDetach()Code
217 | function Cultivator:onDetach() |
218 | self.cultivatorLimitToField = false; |
219 | end; |
onEnter
DescriptionCalled on enter vehicleDefinition
onEnter(boolean isControlling)Arguments
boolean | isControlling | is player controlling the vehicle |
224 | function Cultivator:onEnter(isControlling) |
225 | if isControlling then |
226 | Cultivator.onActivate(self); |
227 | end; |
228 | end; |
onDeactivate
DescriptionCalled on deactivateDefinition
onDeactivate()Code
235 | function Cultivator:onDeactivate() |
236 | self.showFieldNotOwnedWarning = false; |
237 | end; |
onDeactivateSounds
DescriptionCalled on deactivating soundsDefinition
onDeactivateSounds()Code
241 | function Cultivator:onDeactivateSounds() |
242 | if self.isClient then |
243 | SoundUtil.stopSample(self.sampleCultivator, true); |
244 | end; |
245 | end; |
onAiTurnOn
DescriptionCalled on ai turn onDefinition
onAiTurnOn()Code
249 | function Cultivator:onAiTurnOn() |
250 | self.cultivatorLimitToField = true; |
251 | end; |
onAiTurnOff
DescriptionCalled on ai turn offDefinition
onAiTurnOff()Code
255 | function Cultivator:onAiTurnOff() |
256 | self.cultivatorLimitToField = false; |
257 | end; |
doCheckSpeedLimit
DescriptionReturns if speed limit should be checkedDefinition
doCheckSpeedLimit()Return Values
boolean | checkSpeedlimit | check speed limit |
262 | function Cultivator:doCheckSpeedLimit(superFunc) |
263 | local parent = false; |
264 | if superFunc ~= nil then |
265 | parent = superFunc(self); |
266 | end |
267 | |
268 | return parent or self.isCultivatorSpeedLimitActive; |
269 | end; |
getDoGroundManipulation
DescriptionReturns if tool does ground manipulationDefinition
getDoGroundManipulation()Return Values
boolean | doGroundManipulation | do ground manipulation |
274 | function Cultivator:getDoGroundManipulation(superFunc) |
275 | if not self.doGroundManipulation then |
276 | return false; |
277 | end; |
278 | |
279 | if superFunc ~= nil then |
280 | return superFunc(self); |
281 | end |
282 | return true; |
283 | end; |
getIsReadyToSpray
DescriptionReturns if tool is ready to sprayDefinition
getIsReadyToSpray()Return Values
boolean | isReady | is ready to spray |
288 | function Cultivator:getIsReadyToSpray(superFunc) |
289 | local isReadyToSpray = true; |
290 | if superFunc ~= nil then |
291 | isReadyToSpray = isReadyToSpray and superFunc(self); |
292 | end; |
293 | |
294 | isReadyToSpray = isReadyToSpray and self.doGroundManipulation; |
295 | |
296 | return isReadyToSpray; |
297 | end; |
getDirtMultiplier
DescriptionReturns current dirt multiplierDefinition
getDirtMultiplier()Return Values
float | dirtMultiplier | current dirt multiplier |
302 | function Cultivator:getDirtMultiplier(superFunc) |
303 | local multiplier = 0; |
304 | if superFunc ~= nil then |
305 | multiplier = multiplier + superFunc(self); |
306 | end; |
307 | |
308 | if self.doGroundManipulation then |
309 | multiplier = multiplier + self.workMultiplier * self:getLastSpeed() / self.speedLimit; |
310 | end; |
311 | |
312 | return multiplier; |
313 | 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 |
321 | function Cultivator:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key) |
322 | local retValue = true; |
323 | if superFunc ~= nil then |
324 | retValue = superFunc(self, workArea, xmlFile, key) |
325 | end |
326 | |
327 | if workArea.type == WorkArea.AREATYPE_DEFAULT then |
328 | workArea.type = WorkArea.AREATYPE_CULTIVATOR; |
329 | end; |
330 | |
331 | return retValue; |
332 | end; |
getDefaultSpeedLimit
DescriptionReturns default speed limitDefinition
getDefaultSpeedLimit()Return Values
float | speedLimit | speed limit |
337 | function Cultivator.getDefaultSpeedLimit() |
338 | return 15; |
339 | end; |
processCultivatorAreas
DescriptionProcess cultivator areasDefinition
processCultivatorAreas(table workAreas, boolean limitToField, boolean limitGrassDestructionToField, float angle)Arguments
table | workAreas | work areas to process |
boolean | limitToField | limit to field |
boolean | limitGrassDestructionToField | limit grass destruction to field |
float | angle | angle |
float | areaSum | sum of changed pixel |
348 | function Cultivator:processCultivatorAreas(workAreas, limitToField, limitGrassDestructionToField, angle) |
349 | local numAreas = table.getn(workAreas); |
350 | local areaSum = 0; |
351 | for i=1, numAreas do |
352 | local x = workAreas[i][1]; |
353 | local z = workAreas[i][2]; |
354 | local x1 = workAreas[i][3]; |
355 | local z1 = workAreas[i][4]; |
356 | local x2 = workAreas[i][5]; |
357 | local z2 = workAreas[i][6]; |
358 | areaSum = areaSum + Utils.updateCultivatorArea(x, z, x1, z1, x2, z2, not limitToField, not limitGrassDestructionToField, angle); |
359 | end; |
360 | return areaSum; |
361 | end; |