Script v1.4.4.0
- Handtools
- Events
- Objects
- Placeables
- AnimatedObjectPlaceable
- BeehivePlaceable
- GreenhousePlaceable
- HayLoftPlaceable
- HeatingPlantPlaceable
- HighPressureWasherPlaceab...
- Placeable
- SolarCollectorPlaceable
- WindTurbinePlaceable
- Triggers
- Utils
- Vehicles
- Specializations
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
GreenhousePlaceable
DescriptionClass for placeable greenhouseParent
PlaceableFunctions
- new
- delete
- deleteFinal
- readStream
- writeStream
- readUpdateStream
- writeUpdateStream
- createNode
- load
- finalizePlacement
- initPose
- loadFromAttributesAndNodes
- getSaveAttributesAndNodes
- update
- updateTick
- getShowInfo
- hourChanged
- setWaterTankFillLevel
- addFillLevelFromTool
- getAllowFillTypeFromTool
- setManureFillLevel
- setIsWaterTankFilling
- addWaterTrailer
- removeWaterTrailer
- onWaterTankTrigger
new
DescriptionCreating placeable greenhouseDefinition
new(boolean isServer, boolean isClient, table customMt)Arguments
boolean | isServer | is server |
boolean | isClient | is client |
table | customMt | custom metatable |
table | instance | Instance of object |
18 | function GreenhousePlaceable:new(isServer, isClient, customMt) |
19 | local mt = customMt; |
20 | if mt == nil then |
21 | mt = GreenhousePlaceable_mt; |
22 | end; |
23 | |
24 | local self = Placeable:new(isServer, isClient, mt); |
25 | |
26 | registerObjectClassName(self, "GreenhousePlaceable"); |
27 | |
28 | self.waterTankCapacity = 1000; |
29 | self.waterTankFillLevel = 1000; |
30 | self.sentWaterTankFillLevel = self.waterTankFillLevel; |
31 | self.waterTankUsagePerHour = 0; |
32 | self.waterTankFillLitersPerSecond = 200; |
33 | self.waterTrailers = {}; |
34 | self.isFruitAlive = true; |
35 | self.displayFruit = false; |
36 | |
37 | self.manureFillLevel = 0; |
38 | self.manureUsagePerHour = 0; |
39 | self.manureCapacity = 200; |
40 | self.manurePlaneMinY = 0; |
41 | self.manurePlaneMaxY = 1; |
42 | self.sentManureFillLevel = self.manureFillLevel; |
43 | |
44 | self.vehiclesInRange = {}; |
45 | self.playerInRange = false; |
46 | |
47 | self.greenhousePlaceableDirtyFlag = self:getNextDirtyFlag(); |
48 | |
49 | self.waterTrailerActivatable = GreenhousePlaceableWaterTankActivatable:new(self); |
50 | |
51 | return self; |
52 | end; |
delete
DescriptionDeleting placeable greenhouseDefinition
delete()Code
56 | function GreenhousePlaceable:delete() |
57 | if self.shovelTarget ~= nil then |
58 | self.shovelTarget:delete() |
59 | end |
60 | |
61 | g_currentMission:removeActivatableObject(self.waterTrailerActivatable); |
62 | unregisterObjectClassName(self); |
63 | g_currentMission.environment:removeHourChangeListener(self); |
64 | |
65 | if self.waterTankTriggerNode ~= nil then |
66 | removeTrigger(self.waterTankTriggerNode); |
67 | end; |
68 | if self.sampleRefuel ~= nil then |
69 | SoundUtil.deleteSample(self.sampleRefuel); |
70 | end; |
71 | |
72 | GreenhousePlaceable:superClass().delete(self); |
73 | end; |
deleteFinal
DescriptionDeleting placeable greenhouse finalDefinition
deleteFinal()Code
77 | function GreenhousePlaceable:deleteFinal() |
78 | GreenhousePlaceable:superClass().deleteFinal(self); |
79 | end; |
readStream
DescriptionCalled on client side on joinDefinition
readStream(integer streamId, table connection)Arguments
integer | streamId | stream ID |
table | connection | connection |
85 | function GreenhousePlaceable:readStream(streamId, connection) |
86 | GreenhousePlaceable:superClass().readStream(self, streamId, connection); |
87 | if connection:getIsServer() then |
88 | local waterTankFillLevel = streamReadUInt8(streamId)/255*self.waterTankCapacity; |
89 | self:setWaterTankFillLevel(waterTankFillLevel); |
90 | local manureFillLevel = streamReadUInt8(streamId)/255*self.manureCapacity; |
91 | self:setManureFillLevel(manureFillLevel); |
92 | end; |
93 | end; |
writeStream
DescriptionCalled on server side on joinDefinition
writeStream(integer streamId, table connection)Arguments
integer | streamId | stream ID |
table | connection | connection |
99 | function GreenhousePlaceable:writeStream(streamId, connection) |
100 | GreenhousePlaceable:superClass().writeStream(self, streamId, connection); |
101 | if not connection:getIsServer() then |
102 | streamWriteUInt8(streamId, math.floor(self.waterTankFillLevel/self.waterTankCapacity * 255)); |
103 | streamWriteUInt8(streamId, math.floor(self.manureFillLevel/self.manureCapacity * 255)); |
104 | end; |
105 | end; |
readUpdateStream
DescriptionCalled on client side on updateDefinition
readUpdateStream(integer streamId, integer timestamp, table connection)Arguments
integer | streamId | stream ID |
integer | timestamp | timestamp |
table | connection | connection |
112 | function GreenhousePlaceable:readUpdateStream(streamId, timestamp, connection) |
113 | GreenhousePlaceable:superClass().readUpdateStream(self, streamId, timestamp, connection); |
114 | if connection:getIsServer() then |
115 | local waterTankFillLevel = streamReadUInt8(streamId)/255*self.waterTankCapacity; |
116 | self:setWaterTankFillLevel(waterTankFillLevel); |
117 | local manureFillLevel = streamReadUInt8(streamId)/255*self.manureCapacity; |
118 | self:setManureFillLevel(manureFillLevel); |
119 | end; |
120 | end; |
writeUpdateStream
DescriptionCalled on server side on updateDefinition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)Arguments
integer | streamId | stream ID |
table | connection | connection |
integer | dirtyMask | dirty mask |
127 | function GreenhousePlaceable:writeUpdateStream(streamId, connection, dirtyMask) |
128 | GreenhousePlaceable:superClass().writeUpdateStream(self, streamId, connection, dirtyMask); |
129 | if not connection:getIsServer() then |
130 | streamWriteUInt8(streamId, math.floor(self.waterTankFillLevel/self.waterTankCapacity * 255)); |
131 | streamWriteUInt8(streamId, math.floor(self.manureFillLevel/self.manureCapacity * 255)); |
132 | end; |
133 | end; |
createNode
DescriptionCreate nodeDefinition
createNode(string i3dFilename)Arguments
string | i3dFilename | i3d file name |
boolean | success | success |
139 | function GreenhousePlaceable:createNode(i3dFilename) |
140 | if not GreenhousePlaceable:superClass().createNode(self, i3dFilename) then |
141 | return false; |
142 | end; |
143 | |
144 | return true; |
145 | end; |
load
DescriptionLoad greenhouseDefinition
load(string xmlFilename, float x, float y, float z, float rx, float ry, float rz, boolean initRandom)Arguments
string | xmlFilename | xml file name |
float | x | x world position |
float | y | z world position |
float | z | z world position |
float | rx | rx world rotation |
float | ry | ry world rotation |
float | rz | rz world rotation |
boolean | initRandom | initialize random |
boolean | success | success |
158 | function GreenhousePlaceable:load(xmlFilename, x,y,z, rx,ry,rz, initRandom) |
159 | if not GreenhousePlaceable:superClass().load(self, xmlFilename, x,y,z, rx,ry,rz, initRandom) then |
160 | return false; |
161 | end; |
162 | |
163 | local xmlFile = loadXMLFile("TempXML", xmlFilename); |
164 | |
165 | local fruitAlive = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.fruit#alive")); |
166 | local fruitDead = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.fruit#dead")); |
167 | if fruitAlive ~= nil then |
168 | self.fruitAlive = fruitAlive; |
169 | end; |
170 | if fruitDead ~= nil then |
171 | self.fruitDead = fruitDead; |
172 | end; |
173 | |
174 | self.waterTankTriggerNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.waterTank#triggerNode")); |
175 | self.waterTankCapacity = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.waterTank#capacity"), self.waterTankCapacity); |
176 | self.waterTankUsagePerHour = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.waterTank#usagePerHour"), self.waterTankUsagePerHour); |
177 | self.waterTankFillLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.waterTank#fillLitersPerSecond"), self.waterTankFillLitersPerSecond); |
178 | if g_client ~= nil then |
179 | self.sampleRefuel = SoundUtil.loadSample(xmlFile, {}, "placeable.waterTank#refuelSound", "$data/maps/sounds/refuel.wav", self.baseDirectory, self.nodeId); |
180 | end; |
181 | |
182 | self.manurePlane = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.manurePlane#node")); |
183 | self.shovelTargetNode = Utils.indexToObject(self.nodeId, Utils.getNoNil(getXMLString(xmlFile, "placeable.manurePlane#shovelTargetIndex"), getXMLString(xmlFile, "placeable.manurePlane#collisionNode"))) |
184 | local minY, maxY = Utils.getVectorFromString(getXMLString(xmlFile, "placeable.manurePlane#minMaxY")); |
185 | if minY ~= nil and maxY ~= nil then |
186 | self.manurePlaneMinY = minY; |
187 | self.manurePlaneMaxY = maxY; |
188 | end; |
189 | self.manureCapacity = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.manurePlane#capacity"), self.manureCapacity); |
190 | self.manureUsagePerHour = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.manurePlane#usagePerHour"), self.manureUsagePerHour); |
191 | |
192 | delete(xmlFile); |
193 | |
194 | self:setWaterTankFillLevel(0); |
195 | self.sentWaterTankFillLevel = self.waterTankFillLevel; |
196 | |
197 | self:setManureFillLevel(0); |
198 | self.sentManureFillLevel = self.manureFillLevel; |
199 | |
200 | return true; |
201 | end; |
finalizePlacement
DescriptionCalled if placeable is placedDefinition
finalizePlacement()Code
205 | function GreenhousePlaceable:finalizePlacement() |
206 | GreenhousePlaceable:superClass().finalizePlacement(self); |
207 | g_currentMission.environment:addHourChangeListener(self); |
208 | if self.waterTankTriggerNode ~= nil then |
209 | addTrigger(self.waterTankTriggerNode, "onWaterTankTrigger", self); |
210 | end |
211 | |
212 | if self.shovelTargetNode ~= nil then |
213 | if self.shovelTargetNode ~= nil then |
214 | self.shovelTarget = ShovelTarget:new(self) |
215 | if not self.shovelTarget:load(self.shovelTargetNode) then |
216 | self.shovelTarget:delete() |
217 | self.shovelTarget = nil |
218 | end |
219 | end |
220 | end; |
221 | end |
initPose
DescriptionInitialize poseDefinition
initPose(float x, float y, float z, float rx, float ry, float rz, boolean initRandom)Arguments
float | x | x world position |
float | y | y world position |
float | z | z world position |
float | rx | rx world rotation |
float | ry | ry world rotation |
float | rz | rz world rotation |
boolean | initRandom | initialize random |
232 | function GreenhousePlaceable:initPose(x,y,z, rx,ry,rz, initRandom) |
233 | GreenhousePlaceable:superClass().initPose(self, x,y,z, rx,ry,rz, initRandom); |
234 | end; |
loadFromAttributesAndNodes
DescriptionLoading from attributes and nodesDefinition
loadFromAttributesAndNodes(integer xmlFile, string key, boolean resetVehicles)Arguments
integer | xmlFile | id of xml object |
string | key | key |
boolean | resetVehicles | reset vehicles |
boolean | success | success |
242 | function GreenhousePlaceable:loadFromAttributesAndNodes(xmlFile, key, resetVehicles) |
243 | |
244 | if not GreenhousePlaceable:superClass().loadFromAttributesAndNodes(self, xmlFile, key, resetVehicles) then |
245 | return false; |
246 | end; |
247 | |
248 | local waterTankFillLevel = getXMLFloat(xmlFile, key.."#waterTankFillLevel"); |
249 | if waterTankFillLevel ~= nil then |
250 | self:setWaterTankFillLevel(waterTankFillLevel); |
251 | end; |
252 | local manureFillLevel = getXMLFloat(xmlFile, key.."#manureFillLevel"); |
253 | if manureFillLevel ~= nil then |
254 | self:setManureFillLevel(manureFillLevel); |
255 | end; |
256 | |
257 | return true; |
258 | end; |
getSaveAttributesAndNodes
DescriptionGet save attributes and nodesDefinition
getSaveAttributesAndNodes(string nodeIdent)Arguments
string | nodeIdent | node ident |
string | attributes | attributes |
string | nodes | nodes |
265 | function GreenhousePlaceable:getSaveAttributesAndNodes(nodeIdent) |
266 | local attributes, nodes = GreenhousePlaceable:superClass().getSaveAttributesAndNodes(self, nodeIdent); |
267 | attributes = attributes .. ' waterTankFillLevel="'..self.waterTankFillLevel..'"'; |
268 | attributes = attributes .. ' manureFillLevel="'..self.manureFillLevel..'"'; |
269 | return attributes, nodes; |
270 | end; |
update
DescriptionUpdateDefinition
update(float dt)Arguments
float | dt | time since last call in ms |
275 | function GreenhousePlaceable:update(dt) |
276 | GreenhousePlaceable:superClass().update(self, dt); |
277 | if self:getShowInfo() then |
278 | g_currentMission:addExtraPrintText(g_i18n:getText("info_waterFillLevel").." "..math.floor(self.waterTankFillLevel).." ("..math.floor(100*self.waterTankFillLevel/self.waterTankCapacity).."%)"); |
279 | g_currentMission:addExtraPrintText(g_i18n:getText("info_manureFillLevel").." "..math.floor(self.manureFillLevel).." ("..math.floor(100*self.manureFillLevel/self.manureCapacity).."%)"); |
280 | end; |
281 | end; |
updateTick
DescriptionupdateTickDefinition
updateTick(float dt)Arguments
float | dt | time since last call in ms |
286 | function GreenhousePlaceable:updateTick(dt) |
287 | if self.isServer then |
288 | |
289 | if self.waterTankFillLevel ~= self.sentWaterTankFillLevel then |
290 | self:raiseDirtyFlags(self.greenhousePlaceableDirtyFlag); |
291 | |
292 | self.sentWaterTankFillLevel = self.waterTankFillLevel; |
293 | end; |
294 | if self.manureFillLevel ~= self.sentManureFillLevel then |
295 | self:raiseDirtyFlags(self.greenhousePlaceableDirtyFlag); |
296 | |
297 | self.sentManureFillLevel = self.manureFillLevel; |
298 | end; |
299 | |
300 | if self.isWaterTankFilling then |
301 | local disableFilling = false; |
302 | local waterFillLevel = self.waterTankFillTrailer:getFillLevel(FillUtil.FILLTYPE_WATER); |
303 | if waterFillLevel > 0 then |
304 | local oldFillLevel = self.waterTankFillLevel; |
305 | |
306 | local delta = self.waterTankFillLitersPerSecond*dt*0.001; |
307 | delta = math.min(delta, waterFillLevel); |
308 | |
309 | self:setWaterTankFillLevel(self.waterTankFillLevel + delta); |
310 | |
311 | local delta = self.waterTankFillLevel - oldFillLevel; |
312 | if delta <= 0 then |
313 | disableFilling = true; |
314 | end; |
315 | self.waterTankFillTrailer:setFillLevel(waterFillLevel - delta, FillUtil.FILLTYPE_WATER, true); |
316 | else |
317 | disableFilling = true; |
318 | end; |
319 | if disableFilling then |
320 | self:setIsWaterTankFilling(false); |
321 | end; |
322 | end; |
323 | |
324 | end; |
325 | end; |
getShowInfo
DescriptionReturns true if info should showDefinition
getShowInfo()Return Values
boolean | showInfo | show info |
330 | function GreenhousePlaceable:getShowInfo() |
331 | if (g_currentMission.controlPlayer and self.playerInRange) then |
332 | return true; |
333 | end; |
334 | if not g_currentMission.controlPlayer then |
335 | for vehicle in pairs(self.vehiclesInRange) do |
336 | if vehicle:getIsActiveForInput() then |
337 | return true; |
338 | end; |
339 | end; |
340 | end; |
341 | return false; |
342 | end; |
hourChanged
DescriptionCalled if hour changedDefinition
hourChanged()Code
346 | function GreenhousePlaceable:hourChanged() |
347 | if self.isServer then |
348 | self:setWaterTankFillLevel(self.waterTankFillLevel - self.waterTankUsagePerHour); |
349 | self:setManureFillLevel(self.manureFillLevel - self.manureUsagePerHour); |
350 | |
351 | if self.isFruitAlive then |
352 | local income = self.incomePerHour; |
353 | if self.manureFillLevel > 0 then |
354 | income = income * 2; |
355 | end; |
356 | g_currentMission:addSharedMoney(income, "propertyIncome"); |
357 | g_currentMission:addMoneyChange(income, EconomyManager.MONEY_TYPE_PROPERTY_INCOME); |
358 | end; |
359 | end; |
360 | end; |
setWaterTankFillLevel
DescriptionSet water tank fill levelDefinition
setWaterTankFillLevel(float fillLevel)Arguments
float | fillLevel | new fill level |
365 | function GreenhousePlaceable:setWaterTankFillLevel(fillLevel) |
366 | self.waterTankFillLevel = Utils.clamp(fillLevel, 0, self.waterTankCapacity); |
367 | |
368 | self.isFruitAlive = self.waterTankFillLevel > 0.0001; |
369 | |
370 | if self.waterTankFillLevel > 0 then |
371 | self.displayFruit = true; |
372 | end; |
373 | |
374 | if self.fruitAlive ~= nil then |
375 | setVisibility(self.fruitAlive, self.isFruitAlive and self.displayFruit); |
376 | end; |
377 | if self.fruitDead ~= nil then |
378 | setVisibility(self.fruitDead, not self.isFruitAlive and self.displayFruit); |
379 | end; |
380 | end; |
addFillLevelFromTool
DescriptionAdd fill level from tool to triggerDefinition
addFillLevelFromTool(table object, float fillDelta, integer fillType, integer toolType)Arguments
table | object | object |
float | fillDelta | delta to fill |
integer | fillType | fill type index |
integer | toolType | tool type index |
float | fillDelta | real fill delta |
389 | function GreenhousePlaceable:addFillLevelFromTool(object, fillDelta, fillType, toolType) |
390 | fillDelta = math.min(fillDelta, self.manureCapacity-self.manureFillLevel) |
391 | |
392 | if fillDelta > 0 then |
393 | self:setManureFillLevel(self.manureFillLevel+fillDelta); |
394 | end; |
395 | |
396 | return fillDelta; |
397 | end |
getAllowFillTypeFromTool
DescriptionReturns if shovel fill type is allowedDefinition
getAllowFillTypeFromTool()Return Values
float | isAllowed | is allowed |
402 | function GreenhousePlaceable:getAllowFillTypeFromTool(fillType) |
403 | return fillType == FillUtil.FILLTYPE_MANURE; |
404 | end; |
setManureFillLevel
DescriptionSet manure fill levelDefinition
setManureFillLevel(float fillLevel)Arguments
float | fillLevel | new fill level |
409 | function GreenhousePlaceable:setManureFillLevel(fillLevel) |
410 | self.manureFillLevel = Utils.clamp(fillLevel, 0, self.manureCapacity); |
411 | |
412 | if self.manurePlane ~= nil then |
413 | setVisibility(self.manurePlane, self.manureFillLevel > 0.0001); |
414 | local x,y,z = getTranslation(self.manurePlane); |
415 | y = self.manurePlaneMinY + self.manureFillLevel/self.manureCapacity * (self.manurePlaneMaxY - self.manurePlaneMinY); |
416 | |
417 | setTranslation(self.manurePlane, x,y,z); |
418 | end; |
419 | end; |
setIsWaterTankFilling
DescriptionSet is water tank fillingDefinition
setIsWaterTankFilling(boolean isWaterTankFilling, table trailer, boolean noEventSend)Arguments
boolean | isWaterTankFilling | is water tank filling |
table | trailer | trailer |
boolean | noEventSend | no event send |
426 | function GreenhousePlaceable:setIsWaterTankFilling(isWaterTankFilling, trailer, noEventSend) |
427 | GreenhouseSetIsWaterTankFillingEvent.sendEvent(self, isWaterTankFilling, trailer, noEventSend) |
428 | if self.isWaterTankFilling ~= isWaterTankFilling then |
429 | self.isWaterTankFilling = isWaterTankFilling; |
430 | self.waterTankFillTrailer = trailer; |
431 | end; |
432 | if self.sampleRefuel ~= nil then |
433 | if isWaterTankFilling then |
434 | SoundUtil.play3DSample(self.sampleRefuel); |
435 | else |
436 | SoundUtil.stop3DSample(self.sampleRefuel); |
437 | end; |
438 | end; |
439 | end; |
addWaterTrailer
DescriptionAdd water trailer in rangeDefinition
addWaterTrailer(table trailer)Arguments
table | trailer | trailer |
444 | function GreenhousePlaceable:addWaterTrailer(trailer) |
445 | if table.getn(self.waterTrailers) == 0 then |
446 | g_currentMission:addActivatableObject(self.waterTrailerActivatable); |
447 | end; |
448 | table.insert(self.waterTrailers, trailer); |
449 | end; |
removeWaterTrailer
DescriptionRemove water trailer in rangeDefinition
removeWaterTrailer(table trailer)Arguments
table | trailer | trailer |
454 | function GreenhousePlaceable:removeWaterTrailer(trailer) |
455 | for i=1, table.getn(self.waterTrailers) do |
456 | if self.waterTrailers[i] == trailer then |
457 | table.remove(self.waterTrailers, i); |
458 | break; |
459 | end; |
460 | end; |
461 | if table.getn(self.waterTrailers) == 0 then |
462 | if self.isServer then |
463 | self:setIsWaterTankFilling(false); |
464 | end; |
465 | g_currentMission:removeActivatableObject(self.waterTrailerActivatable); |
466 | end; |
467 | end; |
onWaterTankTrigger
DescriptionWater tank triggerDefinition
onWaterTankTrigger(integer triggerId, integer otherId, boolean onEnter, boolean onLeave, boolean onStay, integer otherShapeId)Arguments
integer | triggerId | id of trigger |
integer | otherId | id of actor |
boolean | onEnter | on enter |
boolean | onLeave | on leave |
boolean | onStay | on stay |
integer | otherShapeId | id of other actor |
477 | function GreenhousePlaceable:onWaterTankTrigger(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
478 | if onEnter or onLeave then |
479 | |
480 | if g_currentMission.player ~= nil and otherActorId == g_currentMission.player.rootNode then |
481 | if onEnter then |
482 | self.playerInRange = true; |
483 | else |
484 | self.playerInRange = false; |
485 | end; |
486 | else |
487 | local vehicle = g_currentMission.nodeToVehicle[otherActorId]; |
488 | if vehicle ~= nil then |
489 | if onEnter then |
490 | self.vehiclesInRange[vehicle] = true; |
491 | else |
492 | self.vehiclesInRange[vehicle] = nil; |
493 | end; |
494 | end; |
495 | |
496 | |
497 | local trailer = g_currentMission.objectToTrailer[otherShapeId]; |
498 | if trailer ~= nil and trailer:allowFillType(FillUtil.FILLTYPE_WATER, false) then |
499 | if onEnter then |
500 | self:addWaterTrailer(trailer); |
501 | else -- onLeave |
502 | self:removeWaterTrailer(trailer); |
503 | end; |
504 | end; |
505 | end; |
506 | end; |
507 | end; |