Sprache Deutsch Language English

Script Dokumentation LS 2015 - GreenhousePlaceable (Patch 1.3)

Script Dokumentation Übersicht

scripts/placeables/GreenhousePlaceable.lua

Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
2
3GreenhousePlaceable = {};
4GreenhousePlaceable_mt = Class(GreenhousePlaceable, Placeable);
5
6InitStaticObjectClass(GreenhousePlaceable, "GreenhousePlaceable", ObjectIds.OBJECT_GREENHOUSE_PLACEABLE);
7
8function GreenhousePlaceable:new(isServer, isClient, customMt)
9 local mt = customMt;
10 if mt == nil then
11 mt = GreenhousePlaceable_mt;
12 end;
13
14 local self = Placeable:new(isServer, isClient, mt);
15
16 registerObjectClassName(self, "GreenhousePlaceable");
17
18 self.incomePerHour = 0;
19
20 self.waterTankCapacity = 1000;
21 self.waterTankFillLevel = 1000;
22 self.sentWaterTankFillLevel = self.waterTankFillLevel;
23 self.waterTankUsagePerHour = 0;
24 self.waterTankFillLitersPerSecond = 200;
25 self.waterTrailers = {};
26 self.isFruitAlive = true;
27 self.displayFruit = false;
28
29 self.manureFillLevel = 0;
30 self.manureUsagePerHour = 0;
31 self.manureCapacity = 200;
32 self.manurePlaneMinY = 0;
33 self.manurePlaneMaxY = 1;
34 self.sentManureFillLevel = self.manureFillLevel;
35
36 self.manurePlaneObject = GreenhousePlaceableManurePlane:new(self);
37
38 self.vehiclesInRange = {};
39 self.playerInRange = false;
40
41 self.greenhousePlaceableDirtyFlag = self:getNextDirtyFlag();
42
43 self.waterTrailerActivatable = GreenhousePlaceableWaterTankActivatable:new(self);
44
45 return self;
46end;
47
48function GreenhousePlaceable:delete()
49 g_currentMission:removeActivatableObject(self.waterTrailerActivatable);
50 unregisterObjectClassName(self);
51 g_currentMission.environment:removeHourChangeListener(self);
52 if self.door ~= nil then
53 removeTrigger(self.door.triggerNode);
54 end;
55 if self.waterTankTriggerNode ~= nil then
56 removeTrigger(self.waterTankTriggerNode);
57 end;
58 if self.manurePlaneCollisionNode ~= nil then
59 g_currentMission:removeNodeObject(self.manurePlaneCollisionNode);
60 end
61
62 GreenhousePlaceable:superClass().delete(self);
63end;
64
65function GreenhousePlaceable:deleteFinal()
66 GreenhousePlaceable:superClass().deleteFinal(self);
67end;
68
69function GreenhousePlaceable:readStream(streamId, connection)
70 GreenhousePlaceable:superClass().readStream(self, streamId, connection);
71 if connection:getIsServer() then
72 local waterTankFillLevel = streamReadUInt8(streamId)/255*self.waterTankCapacity;
73 self:setWaterTankFillLevel(waterTankFillLevel);
74 local manureFillLevel = streamReadUInt8(streamId)/255*self.manureCapacity;
75 self:setManureFillLevel(manureFillLevel);
76 end;
77end;
78
79function GreenhousePlaceable:writeStream(streamId, connection)
80 GreenhousePlaceable:superClass().writeStream(self, streamId, connection);
81 if not connection:getIsServer() then
82 streamWriteUInt8(streamId, math.floor(self.waterTankFillLevel/self.waterTankCapacity * 255));
83 streamWriteUInt8(streamId, math.floor(self.manureFillLevel/self.manureCapacity * 255));
84 end;
85end;
86
87function GreenhousePlaceable:readUpdateStream(streamId, timestamp, connection)
88 GreenhousePlaceable:superClass().readUpdateStream(self, streamId, timestamp, connection);
89 if connection:getIsServer() then
90 local waterTankFillLevel = streamReadUInt8(streamId)/255*self.waterTankCapacity;
91 self:setWaterTankFillLevel(waterTankFillLevel);
92 local manureFillLevel = streamReadUInt8(streamId)/255*self.manureCapacity;
93 self:setManureFillLevel(manureFillLevel);
94 end;
95end;
96
97function GreenhousePlaceable:writeUpdateStream(streamId, connection, dirtyMask)
98 GreenhousePlaceable:superClass().writeUpdateStream(self, streamId, connection, dirtyMask);
99 if not connection:getIsServer() then
100 streamWriteUInt8(streamId, math.floor(self.waterTankFillLevel/self.waterTankCapacity * 255));
101 streamWriteUInt8(streamId, math.floor(self.manureFillLevel/self.manureCapacity * 255));
102 end;
103end;
104
105function GreenhousePlaceable:createNode(i3dFilename)
106 if not GreenhousePlaceable:superClass().createNode(self, i3dFilename) then
107 return false;
108 end;
109
110 return true;
111end;
112
113function GreenhousePlaceable:load(xmlFilename, x,y,z, rx,ry,rz, initRandom)
114 if not GreenhousePlaceable:superClass().load(self, xmlFilename, x,y,z, rx,ry,rz, initRandom) then
115 return false;
116 end;
117
118 local xmlFile = loadXMLFile("TempXML", xmlFilename);
119
120 local fruitAlive = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.fruit#alive"));
121 local fruitDead = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.fruit#dead"));
122 if fruitAlive ~= nil then
123 self.fruitAlive = fruitAlive;
124 end;
125 if fruitDead ~= nil then
126 self.fruitDead = fruitDead;
127 end;
128
129 self.waterTankTriggerNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.waterTank#triggerNode"));
130 self.waterTankCapacity = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.waterTank#capacity"), self.waterTankCapacity);
131 self.waterTankUsagePerHour = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.waterTank#usagePerHour"), self.waterTankUsagePerHour);
132 self.waterTankFillLitersPerSecond = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.waterTank#fillLitersPerSecond"), self.waterTankFillLitersPerSecond);
133 if g_client ~= nil then
134 self.sampleRefuel = Utils.loadSample(xmlFile, {}, "placeable.waterTank#refuelSound", "$data/maps/sounds/refuel.wav", self.baseDirectory, self.nodeId);
135 end;
136
137 self.manurePlane = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.manurePlane#node"));
138 self.manurePlaneCollisionNode = Utils.getNoNil(Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.manurePlane#collisionNode")), self.manurePlane);
139 if self.manurePlane ~= nil then
140 g_currentMission:addNodeObject(self.manurePlaneCollisionNode, self.manurePlaneObject);
141 end;
142 local minY, maxY = Utils.getVectorFromString(getXMLString(xmlFile, "placeable.manurePlane#minMaxY"));
143 if minY ~= nil and maxY ~= nil then
144 self.manurePlaneMinY = minY;
145 self.manurePlaneMaxY = maxY;
146 end;
147 self.manureCapacity = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.manurePlane#capacity"), self.manureCapacity);
148 self.manureUsagePerHour = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.manurePlane#usagePerHour"), self.manureUsagePerHour);
149
150 local leftDoorNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.door#leftDoorNode"));
151 local rightDoorNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.door#rightDoorNode"));
152 local triggerNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.door#triggerNode"));
153 if rightDoorNode ~= nil and leftDoorNode ~= nil and triggerNode ~= nil then
154 local movement = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.door#movement"), 1);
155 local movementSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.door#movementSpeed"), 1)*0.001;
156 self.door = {isMoving=false, isOpening=false,leftDoorNode=leftDoorNode, rightDoorNode=rightDoorNode, triggerNode=triggerNode, movement=movement, movementSpeed=movementSpeed};
157 end;
158
159 local difficultyMultiplier = 2 ^ (3 - g_currentMission.missionStats.difficulty); --4 2 1
160 self.incomePerHour = difficultyMultiplier * Utils.getNoNil(getXMLFloat(xmlFile, "placeable.incomePerHour"), 100);
161
162 delete(xmlFile);
163
164 self:setWaterTankFillLevel(0); --self.waterTankCapacity);
165 self.sentWaterTankFillLevel = self.waterTankFillLevel;
166
167 self:setManureFillLevel(0);
168 self.sentManureFillLevel = self.manureFillLevel;
169
170 return true;
171end;
172
173function GreenhousePlaceable:finalizePlacement()
174 GreenhousePlaceable:superClass().finalizePlacement(self);
175 g_currentMission.environment:addHourChangeListener(self);
176 if self.waterTankTriggerNode ~= nil then
177 addTrigger(self.waterTankTriggerNode, "onWaterTankTrigger", self);
178 end
179 if self.door ~= nil then
180 addTrigger(self.door.triggerNode, "onDoorTrigger", self);
181 end;
182 if g_client ~= nil then
183 Utils.deleteSample(self.sampleRefuel);
184 end;
185end
186
187function GreenhousePlaceable:initPose(x,y,z, rx,ry,rz, initRandom)
188 GreenhousePlaceable:superClass().initPose(self, x,y,z, rx,ry,rz, initRandom);
189end;
190
191function GreenhousePlaceable:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
192
193 if not GreenhousePlaceable:superClass().loadFromAttributesAndNodes(self, xmlFile, key, resetVehicles) then
194 return false;
195 end;
196
197 local waterTankFillLevel = getXMLFloat(xmlFile, key.."#waterTankFillLevel");
198 if waterTankFillLevel ~= nil then
199 self:setWaterTankFillLevel(waterTankFillLevel);
200 end;
201 local manureFillLevel = getXMLFloat(xmlFile, key.."#manureFillLevel");
202 if manureFillLevel ~= nil then
203 self:setManureFillLevel(manureFillLevel);
204 end;
205
206 return true;
207end;
208
209function GreenhousePlaceable:getSaveAttributesAndNodes(nodeIdent)
210 local attributes, nodes = GreenhousePlaceable:superClass().getSaveAttributesAndNodes(self, nodeIdent);
211 attributes = attributes .. ' waterTankFillLevel="'..self.waterTankFillLevel..'"';
212 attributes = attributes .. ' manureFillLevel="'..self.manureFillLevel..'"';
213 return attributes, nodes;
214end;
215
216function GreenhousePlaceable:update(dt)
217 if self.door ~= nil then
218 local door = self.door;
219 if door.isMoving then
220 local movement = door.movementSpeed*dt;
221 if door.isOpening then
222 movement = -movement;
223 end;
224 local x,y,z = getTranslation(door.leftDoorNode);
225 z = Utils.clamp(z + movement, -door.movement, 0);
226 if z == 0 or z == -door.movement then
227 door.isMoving = false;
228 end;
229 setTranslation(door.leftDoorNode, x,y,z);
230
231 local x,y,z = getTranslation(door.rightDoorNode);
232 z = Utils.clamp(z - movement, 0, door.movement);
233 if z == 0 or z == door.movement then
234 door.isMoving = false;
235 end;
236 setTranslation(door.rightDoorNode, x,y,z);
237 end;
238 end;
239 if self:getShowInfo() then
240 g_currentMission:addExtraPrintText(g_i18n:getText("water_fill_level").." "..math.floor(self.waterTankFillLevel).." ("..math.floor(100*self.waterTankFillLevel/self.waterTankCapacity).."%)");
241 g_currentMission:addExtraPrintText(g_i18n:getText("manure_fill_level").." "..math.floor(self.manureFillLevel).." ("..math.floor(100*self.manureFillLevel/self.manureCapacity).."%)");
242 end;
243end;
244
245function GreenhousePlaceable:updateTick(dt)
246 if self.isServer then
247
248 if self.waterTankFillLevel ~= self.sentWaterTankFillLevel then
249 self:raiseDirtyFlags(self.greenhousePlaceableDirtyFlag);
250
251 self.sentWaterTankFillLevel = self.waterTankFillLevel;
252 end;
253 if self.manureFillLevel ~= self.sentManureFillLevel then
254 self:raiseDirtyFlags(self.greenhousePlaceableDirtyFlag);
255
256 self.sentManureFillLevel = self.manureFillLevel;
257 end;
258
259 if self.isWaterTankFilling then
260 local disableFilling = false;
261 local waterFillLevel = self.waterTankFillTrailer:getFillLevel(Fillable.FILLTYPE_WATER);
262 if waterFillLevel > 0 then
263 local oldFillLevel = self.waterTankFillLevel;
264
265 local delta = self.waterTankFillLitersPerSecond*dt*0.001;
266 delta = math.min(delta, waterFillLevel);
267
268 self:setWaterTankFillLevel(self.waterTankFillLevel + delta);
269
270 local delta = self.waterTankFillLevel - oldFillLevel;
271 if delta <= 0 then
272 disableFilling = true;
273 end;
274 self.waterTankFillTrailer:setFillLevel(waterFillLevel - delta, Fillable.FILLTYPE_WATER, true);
275 else
276 disableFilling = true;
277 end;
278 if disableFilling then
279 self:setIsWaterTankFilling(false);
280 end;
281 end;
282
283 end;
284end;
285
286function GreenhousePlaceable:getShowInfo()
287 if (g_currentMission.controlPlayer and self.playerInRange) then
288 return true;
289 end;
290 if not g_currentMission.controlPlayer then
291 for vehicle in pairs(self.vehiclesInRange) do
292 if vehicle:getIsActiveForInput() then
293 return true;
294 end;
295 end;
296 end;
297 return false;
298end;
299
300function GreenhousePlaceable:hourChanged()
301 if self.isServer then
302 self:setWaterTankFillLevel(self.waterTankFillLevel - self.waterTankUsagePerHour);
303 self:setManureFillLevel(self.manureFillLevel - self.manureUsagePerHour);
304
305 if self.isFruitAlive then
306 local income = self.incomePerHour;
307 if self.manureFillLevel > 0 then
308 income = income * 2;
309 end;
310 g_currentMission:addSharedMoney(income, "other");
311 g_currentMission:addMoneyChange(income, FSBaseMission.MONEY_TYPE_HOUR_CHANGED);
312 end;
313 end;
314end;
315
316function GreenhousePlaceable:setWaterTankFillLevel(fillLevel)
317 self.waterTankFillLevel = Utils.clamp(fillLevel, 0, self.waterTankCapacity);
318
319 self.isFruitAlive = self.waterTankFillLevel > 0.0001;
320
321 if self.waterTankFillLevel > 0 then
322 self.displayFruit = true;
323 end;
324
325 if self.fruitAlive ~= nil then
326 setVisibility(self.fruitAlive, self.isFruitAlive and self.displayFruit);
327 end;
328 if self.fruitDead ~= nil then
329 setVisibility(self.fruitDead, not self.isFruitAlive and self.displayFruit);
330 end;
331end;
332
333function GreenhousePlaceable:setManureFillLevel(fillLevel)
334 self.manureFillLevel = Utils.clamp(fillLevel, 0, self.manureCapacity);
335
336 if self.manurePlane ~= nil then
337 setVisibility(self.manurePlane, self.manureFillLevel > 0.0001);
338 local x,y,z = getTranslation(self.manurePlane);
339 y = self.manurePlaneMinY + self.manureFillLevel/self.manureCapacity * (self.manurePlaneMaxY - self.manurePlaneMinY);
340
341 setTranslation(self.manurePlane, x,y,z);
342 end;
343end;
344
345function GreenhousePlaceable:setIsWaterTankFilling(isWaterTankFilling, trailer, noEventSend)
346 GreenhouseSetIsWaterTankFillingEvent.sendEvent(self, isWaterTankFilling, trailer, noEventSend)
347 if self.isWaterTankFilling ~= isWaterTankFilling then
348 self.isWaterTankFilling = isWaterTankFilling;
349 self.waterTankFillTrailer = trailer;
350 end;
351 if g_client ~= nil and self.sampleRefuel ~= nil then
352 if isWaterTankFilling then
353 Utils.play3DSample(self.sampleRefuel);
354 else
355 Utils.stop3DSample(self.sampleRefuel);
356 end;
357 end;
358end;
359
360function GreenhousePlaceable:addWaterTrailer(trailer)
361 if table.getn(self.waterTrailers) == 0 then
362 g_currentMission:addActivatableObject(self.waterTrailerActivatable);
363 end;
364 table.insert(self.waterTrailers, trailer);
365end;
366
367function GreenhousePlaceable:removeWaterTrailer(trailer)
368 for i=1, table.getn(self.waterTrailers) do
369 if self.waterTrailers[i] == trailer then
370 table.remove(self.waterTrailers, i);
371 break;
372 end;
373 end;
374 if table.getn(self.waterTrailers) == 0 then
375 if self.isServer then
376 self:setIsWaterTankFilling(false);
377 end;
378 g_currentMission:removeActivatableObject(self.waterTrailerActivatable);
379 end;
380end;
381
382function GreenhousePlaceable:onDoorTrigger(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
383 if onEnter or onLeave then
384 if g_currentMission.players[otherId] ~= nil then
385 if onEnter then
386 if not self.door.isOpening then
387 self.door.isOpening = true;
388 self.door.isMoving = true;
389 end;
390 elseif onLeave then
391 if self.door.isOpening then
392 self.door.isOpening = false;
393 self.door.isMoving = true;
394 end;
395 end;
396 end;
397 end;
398end;
399
400function GreenhousePlaceable:onWaterTankTrigger(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
401 if onEnter or onLeave then
402
403 if g_currentMission.player ~= nil and otherActorId == g_currentMission.player.rootNode then
404 if onEnter then
405 self.playerInRange = true;
406 else
407 self.playerInRange = false;
408 end;
409 else
410 local vehicle = g_currentMission.nodeToVehicle[otherActorId];
411 if vehicle ~= nil then
412 if onEnter then
413 self.vehiclesInRange[vehicle] = true;
414 else
415 self.vehiclesInRange[vehicle] = nil;
416 end;
417 end;
418
419
420 local trailer = g_currentMission.objectToTrailer[otherShapeId];
421 if trailer ~= nil and trailer.fillTypes ~= nil then
422 if onEnter then
423 self:addWaterTrailer(trailer);
424 else -- onLeave
425 self:removeWaterTrailer(trailer);
426 end;
427 end;
428 end;
429 end;
430end;
431
432
433GreenhousePlaceableWaterTankActivatable = {}
434local GreenhousePlaceableWaterTankActivatable_mt = Class(GreenhousePlaceableWaterTankActivatable);
435
436function GreenhousePlaceableWaterTankActivatable:new(greenhouse)
437 local self = {};
438 setmetatable(self, GreenhousePlaceableWaterTankActivatable_mt);
439
440 self.greenhouse = greenhouse;
441 self.activateText = "unknown";
442
443 self.currentTrailer = nil;
444
445 return self;
446end;
447
448
449function GreenhousePlaceableWaterTankActivatable:getIsActivatable()
450 self.currentTrailer = nil;
451 if self.greenhouse.waterTankFillLevel >= self.greenhouse.waterTankCapacity then
452 return false;
453 end;
454 -- find the first trailer which can be used
455 for _, trailer in pairs(self.greenhouse.waterTrailers) do
456 if trailer:getIsActiveForInput() and trailer:getFillLevel(Fillable.FILLTYPE_WATER) > 0 then
457 self.currentTrailer = trailer;
458 self:updateActivateText();
459 return true;
460 end;
461 end;
462 return false;
463end;
464
465function GreenhousePlaceableWaterTankActivatable:onActivateObject()
466 self.greenhouse:setIsWaterTankFilling(not self.greenhouse.isWaterTankFilling, self.currentTrailer);
467 self:updateActivateText();
468 g_currentMission:addActivatableObject(self);
469end;
470
471function GreenhousePlaceableWaterTankActivatable:drawActivate()
472 -- TODO draw icon
473end;
474
475function GreenhousePlaceableWaterTankActivatable:updateActivateText()
476 if self.greenhouse.isWaterTankFilling then
477 self.activateText = string.format(g_i18n:getText("stop_refill_OBJECT"), g_i18n:getText("TypeDesc_Greenhouse"));
478 else
479 self.activateText = string.format(g_i18n:getText("refill_OBJECT"), g_i18n:getText("TypeDesc_Greenhouse"));
480 end;
481end;
482
483
484
485GreenhousePlaceableManurePlane = {}
486local GreenhousePlaceableManurePlane_mt = Class(GreenhousePlaceableManurePlane);
487
488function GreenhousePlaceableManurePlane:new(greenhouse)
489 local self = {};
490 setmetatable(self, GreenhousePlaceableManurePlane_mt);
491
492 self.greenhouse = greenhouse;
493
494 return self;
495end;
496
497function GreenhousePlaceableManurePlane:getAllowShovelFillType(fillType)
498 return fillType == Fillable.FILLTYPE_MANURE;
499end;
500
501function GreenhousePlaceableManurePlane:addShovelFillLevel(shovel, fillLevelDelta, fillType)
502 if fillType == Fillable.FILLTYPE_MANURE then
503 local oldFillLevel = self.greenhouse.manureFillLevel;
504 self.greenhouse:setManureFillLevel(self.greenhouse.manureFillLevel+fillLevelDelta);
505
506 fillLevelDelta = self.greenhouse.manureFillLevel - oldFillLevel;
507
508 return fillLevelDelta;
509 end;
510 return 0;
511end;
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
Script Dokumentation Übersicht