LUADOC - Farming Simulator 17

Printable Version

Placeable

Description
Class for placeables
Functions

onCreateGlowMaterial

Description
On create glow material
Definition
onCreateGlowMaterial(empty empty, integer id)
Arguments
emptyemptyempty
integeridid of node
Code
18function Placeable.onCreateGlowMaterial(_, id)
19 if getHasShaderParameter(id, "colorScale") then
20 Placeable.GLOW_MATERIAL = getMaterial(id, 0)
21 end
22end

new

Description
Creating placeable
Definition
new(boolean isServer, boolean isClient, table customMt)
Arguments
booleanisServeris server
booleanisClientis client
tablecustomMtcustom metatable
Return Values
tableinstanceInstance of object
Code
30function Placeable:new(isServer, isClient, mt)
31 if mt == nil then
32 mt = Placeable_mt;
33 end;
34
35 local self = Object:new(isServer, isClient, mt);
36 self.nodeId = 0;
37
38 self.useRandomYRotation = false;
39 self.useManualYRotation = false;
40 self.placementSizeX = 1;
41 self.placementSizeZ = 1;
42 self.placementTestSizeX = 1;
43 self.placementTestSizeZ = 1;
44 self.pickObjects = {};
45 self.isolated = false;
46 self.isDeleted = false;
47 self.useMultiRootNode = false;
48 self.price = 0;
49 self.age = 0
50
51 registerObjectClassName(self, "Placeable");
52 return self;
53end;

delete

Description
Deleting placeable
Definition
delete()
Code
57function Placeable:delete()
58 self.isDeleted = true;
59 if self.i3dFilename ~= nil then
60 Utils.releaseSharedI3DFile(self.i3dFilename, nil, true);
61 end
62 if g_currentMission ~= nil and g_currentMission.environment ~= nil then
63 g_currentMission.environment:removeDayChangeListener(self)
64 g_currentMission.environment:removeWeatherChangeListener(self);
65 g_currentMission.environment:removeHourChangeListener(self);
66 end
67 unregisterObjectClassName(self);
68 g_currentMission:removeItemToSave(self);
69 for _, node in pairs(self.pickObjects) do
70 g_currentMission:removeNodeObject(node);
71 end;
72 if self.nodeId ~= 0 and entityExists(self.nodeId) then
73 self:setCollisionMask(self.nodeId, 0);
74 setVisibility(self.nodeId, false);
75 else
76 self.nodeId = 0;
77 end;
78 if self.door ~= nil then
79 removeTrigger(self.door.triggerNode);
80 end;
81 if self.sampleDoor ~= nil then
82 SoundUtil.deleteSample(self.sampleDoor);
83 end;
84 if self.sampleIdle ~= nil then
85 SoundUtil.deleteSample(self.sampleIdle);
86 end
87
88 g_currentMission:removeOwnedItem(self);
89
90 g_currentMission:addPlaceableToDelete(self, 300);
91end;

deleteFinal

Description
Deleting placeable final
Definition
deleteFinal()
Code
95function Placeable:deleteFinal()
96 if self.nodeId ~= 0 then
97 delete(self.nodeId);
98 self.nodeId = 0;
99 end;
100end;

setCollisionMask

Description
Set collision mask of node and its children
Definition
setCollisionMask(integer nodeId, integer mask)
Arguments
integernodeIdid of node
integermaskcollision mask
Code
106function Placeable:setCollisionMask(nodeId, mask)
107 setCollisionMask(nodeId, mask);
108 local numChildren = getNumOfChildren(nodeId);
109 for i=0,numChildren-1 do
110 local childId = getChildAt(nodeId, i);
111 self:setCollisionMask(childId, mask)
112 end;
113end;

getIsPlayerInRange

Description
Returns true if player is in range
Definition
getIsPlayerInRange(float distance, table player)
Arguments
floatdistancedistance
tableplayerplayer
Return Values
booleanisInRangeis in range
Code
120function Placeable:getIsPlayerInRange(distance, player)
121 if self.nodeId ~= 0 then
122 distance = Utils.getNoNil(distance, 10);
123 if player == nil then
124 for _, player in pairs(g_currentMission.players) do
125 if self:isInActionDistance(player, self.nodeId, distance) then
126 return true, player;
127 end;
128 end;
129 else
130 return self:isInActionDistance(player, self.nodeId, distance), player;
131 end;
132 end
133 return false, nil;
134end;

isInActionDistance

Description
Returns true if player is in range
Definition
isInActionDistance(table player, integer refNode, float distance)
Arguments
tableplayerplayer
integerrefNodeid of reference node
floatdistancedistance
Return Values
booleanisInRangeis in range
Code
142function Placeable:isInActionDistance(player, refNode, distance)
143 local x,_,z = getWorldTranslation(refNode);
144 local px,_,pz = getWorldTranslation(player.rootNode);
145 local dx,dz = px-x, pz-z;
146 if dx*dx + dz*dz < distance*distance then
147 return true;
148 end
149
150 return false;
151end;

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
157function Placeable:readStream(streamId, connection)
158 Placeable:superClass().readStream(self, streamId, connection);
159 if connection:getIsServer() then
160 local configFileName = Utils.convertFromNetworkFilename(streamReadString(streamId));
161 local x=streamReadFloat32(streamId);
162 local y=streamReadFloat32(streamId);
163 local z=streamReadFloat32(streamId);
164 local rx=Utils.readCompressedAngle(streamId);
165 local ry=Utils.readCompressedAngle(streamId);
166 local rz=Utils.readCompressedAngle(streamId);
167 self:load(configFileName, x,y,z, rx,ry,rz, false, false);
168 self.age = streamReadUInt16(streamId);
169 self.price = streamReadInt32(streamId);
170 self:finalizePlacement();
171 end;
172end;

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
178function Placeable:writeStream(streamId, connection)
179 Placeable:superClass().writeStream(self, streamId, connection);
180 if not connection:getIsServer() then
181 streamWriteString(streamId, Utils.convertToNetworkFilename(self.configFileName));
182 local x,y,z = getTranslation(self.nodeId)
183 local x_rot,y_rot,z_rot = getRotation(self.nodeId);
184 streamWriteFloat32(streamId, x);
185 streamWriteFloat32(streamId, y);
186 streamWriteFloat32(streamId, z);
187 Utils.writeCompressedAngle(streamId, x_rot);
188 Utils.writeCompressedAngle(streamId, y_rot);
189 Utils.writeCompressedAngle(streamId, z_rot);
190 streamWriteUInt16(streamId, self.age);
191 streamWriteInt32(streamId, self.price);
192 end;
193end;

createNode

Description
Create node
Definition
createNode(string i3dFilename)
Arguments
stringi3dFilenamei3d file name
Return Values
booleansuccesssuccess
Code
205function Placeable:createNode(i3dFilename)
206 self.i3dFilename = i3dFilename;
207 local nodeRoot = Utils.loadSharedI3DFile(i3dFilename, nil, false, false);
208 if nodeRoot == 0 then
209 return false;
210 end;
211
212 if self.useMultiRootNode then
213 link(getRootNode(), nodeRoot);
214 self.nodeId = nodeRoot;
215 else
216 local nodeId = getChildAt(nodeRoot, 0);
217 if nodeId == 0 then
218 delete(nodeRoot);
219 return false;
220 end
221 link(getRootNode(), nodeId);
222 delete(nodeRoot);
223 self.nodeId = nodeId;
224 end
225
226 if Placeable.GLOW_MATERIAL ~= nil then
227 self.defaultMaterials = {}
228 self:loadDefaultMaterials(self.nodeId, self.defaultMaterials)
229 end
230
231 return true;
232end;

loadDefaultMaterials

Description
Load default materials
Definition
loadDefaultMaterials(integer node, table nodeTable)
Arguments
integernodeid of node
tablenodeTabletable to save the nodes
Code
238function Placeable:loadDefaultMaterials(node, nodeTable)
239 if getHasClassId(node, ClassIds.SHAPE) then
240 nodeTable[node] = getMaterial(node, 0)
241 setMaterial(node, Placeable.GLOW_MATERIAL, 0)
242 end
243
244 local numChildren = getNumOfChildren(node);
245 if numChildren > 0 then
246 for i=0, numChildren-1 do
247 self:loadDefaultMaterials(getChildAt(node, i), nodeTable)
248 end;
249 end;
250end

setIsPlaceable

Description
Set is in placeable mode
Definition
setIsPlaceable(boolean isPlaceable)
Arguments
booleanisPlaceableis in placeable mode
Code
255function Placeable:setIsPlaceable(isPlaceable)
256 if Placeable.GLOW_MATERIAL ~= nil then
257 local color = nil
258 if isPlaceable then
259 color = {0, 1, 0, 1}
260 else
261 color = {1, 0, 0, 1}
262 end
263 for node,_ in pairs(self.defaultMaterials) do
264 setShaderParameter(node, "colorScale", color[1], color[2], color[3], color[3], false)
265 end
266 end
267end

load

Description
Load placeable
Definition
load(string xmlFilename, float x, float y, float z, float rx, float ry, float rz, boolean initRandom)
Arguments
stringxmlFilenamexml file name
floatxx world position
floatyz world position
floatzz world position
floatrxrx world rotation
floatryry world rotation
floatrzrz world rotation
booleaninitRandominitialize random
Return Values
booleansuccesssuccess
Code
280function Placeable:load(xmlFilename, x,y,z, rx,ry,rz, initRandom)
281 self.configFileName = xmlFilename;
282 self.customEnvironment, self.baseDirectory = Utils.getModNameAndBaseDirectory(xmlFilename);
283
284 local xmlFile = loadXMLFile("TempXML", xmlFilename);
285 if xmlFile == 0 then
286 return false;
287 end;
288 local i3dFilename = getXMLString(xmlFile, "placeable.filename");
289 self.placementSizeX = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.placement#sizeX"), self.placementSizeX);
290 self.placementSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.placement#sizeZ"), self.placementSizeZ);
291 self.placementTestSizeX = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.placement#testSizeX"), self.placementSizeX);
292 self.placementTestSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.placement#testSizeZ"), self.placementSizeZ);
293 self.useRandomYRotation = Utils.getNoNil(getXMLBool(xmlFile, "placeable.placement#useRandomYRotation"), self.useRandomYRotation);
294 self.useManualYRotation = Utils.getNoNil(getXMLBool(xmlFile, "placeable.placement#useManualYRotation"), self.useManualYRotation);
295 self.alignToWorldY = Utils.getNoNil(getXMLBool(xmlFile, "placeable.placement#alignToWorldY"), true);
296
297 self.incomePerHour = getXMLFloat(xmlFile, "placeable.incomePerHour" .. g_currentMission.missionInfo.difficulty)
298 -- fallback for old single value format
299 if self.incomePerHour == nil then
300 self.incomePerHour = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.incomePerHour"), 0)
301 if g_currentMission.missionInfo.difficulty == 1 then
302 self.incomePerHour = self.incomePerHour * 1.5
303 elseif g_currentMission.missionInfo.difficulty == 3 then
304 self.incomePerHour = self.incomePerHour / 1.5
305 end
306 end
307
308 local storeItem = StoreItemsUtil.storeItemsByXMLFilename[self.configFileName:lower()]
309 if self.price == 0 or self.price == nil then
310 self.price = StoreItemsUtil.getDefaultPrice(storeItem);
311 end
312
313 if g_currentMission ~= nil and storeItem.canBeSold then
314 g_currentMission.environment:addDayChangeListener(self)
315 end
316
317 if i3dFilename == nil then
318 delete(xmlFile);
319 return false;
320 end;
321 self.i3dFilename = Utils.getFilename(i3dFilename, self.baseDirectory);
322
323 if not self:createNode(self.i3dFilename) then
324 delete(xmlFile);
325 return false;
326 end;
327 self:initPose(x,y,z, rx,ry,rz, initRandom);
328
329 if hasXMLProperty(xmlFile, "placeable.dayNightObjects") then
330 local i = 0
331 while true do
332 local key = string.format("placeable.dayNightObjects.dayNightObject(%d)", i)
333 if not hasXMLProperty(xmlFile, key) then
334 break
335 end
336 local node = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, key.."#index"))
337 if node ~= nil then
338 if self.dayNightObjects == nil then
339 self.dayNightObjects = {}
340 g_currentMission.environment:addWeatherChangeListener(self);
341 end
342 table.insert(self.dayNightObjects, {node=node, visibleDay=Utils.getNoNil(getXMLBool(xmlFile, key.."#visibleDay"), false), visibleNight=Utils.getNoNil(getXMLBool(xmlFile, key.."visibleNight"), true)})
343 end
344 i = i + 1
345 end
346 end
347
348 self.clearAreas = {};
349 local i = 0;
350 while true do
351 local key = string.format("placeable.clearAreas.clearArea(%d)", i);
352 if not hasXMLProperty(xmlFile, key) then
353 break;
354 end;
355 local clearArea = {};
356 if self:loadClearAreaFromXML(clearArea, xmlFile, key) then
357 table.insert(self.clearAreas, clearArea);
358 end;
359 i = i + 1;
360 end;
361
362 if hasXMLProperty(xmlFile, "placeable.tipOcclusionUpdateArea") then
363 local sizeX = getXMLFloat(xmlFile, "placeable.tipOcclusionUpdateArea#sizeX");
364 local sizeZ = getXMLFloat(xmlFile, "placeable.tipOcclusionUpdateArea#sizeZ");
365
366 if sizeX ~= nil and sizeZ ~= nil then
367 local centerX = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.tipOcclusionUpdateArea#centerX"), 0);
368 local centerZ = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.tipOcclusionUpdateArea#centerZ"), 0);
369 self.tipOcclusionUpdateArea = {centerX, centerZ, sizeX, sizeZ};
370 end
371 end
372
373 if not self.alignToWorldY then
374 self.pos1Node = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.placement#pos1Node"));
375 self.pos2Node = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.placement#pos2Node"));
376 self.pos3Node = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.placement#pos3Node"));
377 if self.pos1Node == nil or self.pos2Node == nil or self.pos3Node == nil then
378 self.alignToWorldY = true;
379 print("Warning: Pos1Node, Pos2Node and Pos3Node has to be set when alignToWorldY is false!");
380 end;
381 end;
382
383 local leftDoorNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.door#leftDoorNode"));
384 local rightDoorNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.door#rightDoorNode"));
385 local triggerNode = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.door#triggerNode"));
386 if rightDoorNode ~= nil and leftDoorNode ~= nil and triggerNode ~= nil then
387 local movement = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.door#movement"), 1);
388 local movementSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.door#movementSpeed"), 1)*0.001;
389 self.door = {isMoving=false, isOpening=false,leftDoorNode=leftDoorNode, rightDoorNode=rightDoorNode, triggerNode=triggerNode, movement=movement, movementSpeed=movementSpeed};
390
391 if self.isClient then
392 self.sampleDoor = SoundUtil.loadSample(xmlFile, {}, "placeable.door#soundFilename", "$data/sounds/door_air.wav", self.baseDirectory, self.nodeId);
393 self.sampleDoor.isPlaying = false;
394 end;
395 self.sampleDoorStartTime = -1
396 end;
397
398 if self.isClient then
399 self.sampleIdle = SoundUtil.loadSample(xmlFile, {}, "placeable.idleSound", nil, self.baseDirectory, self.nodeId);
400 end
401
402 delete(xmlFile);
403
404 return true;
405end;

loadClearAreaFromXML

Description
Load a single clearArea from xml
Definition
loadClearAreaFromXML(table clearArea, integer xmlFile, string key)
Arguments
tableclearAreatable containing the clear areas
integerxmlFileid of the xml file
stringkeystring key to the xml element
Return Values
booleansuccesssuccess
Code
413function Placeable:loadClearAreaFromXML(clearArea, xmlFile, key)
414 local start = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, key .. "#startIndex"));
415 local width = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, key .. "#widthIndex"));
416 local height = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, key .. "#heightIndex"));
417
418 if start ~= nil and width ~= nil and height ~= nil then
419 clearArea.start = start;
420 clearArea.width = width;
421 clearArea.height = height;
422 return true;
423 end;
424 return false;
425end;

finalizePlacement

Description
Called if placeable is placed
Definition
finalizePlacement()
Code
429function Placeable:finalizePlacement()
430 if not self.isolated then
431 if Placeable.GLOW_MATERIAL ~= nil then
432 for node, material in pairs(self.defaultMaterials) do
433 setMaterial(node, material, 0)
434 end
435 end
436
437 self:alignToTerrain()
438
439 addToPhysics(self.nodeId);
440 g_currentMission:addItemToSave(self);
441 g_currentMission:addOwnedItem(self);
442 self:collectPickObjects(self.nodeId);
443
444 for _, node in pairs(self.pickObjects) do
445 g_currentMission:addNodeObject(node, self);
446 end;
447
448 local missionInfo = g_currentMission.missionInfo;
449 if self.isServer then
450 if not self.isLoadedFromSavegame or (missionInfo.isValid and not missionInfo:getIsTipCollisionValid(g_currentMission)) then
451 self:setTipOcclusionAreaDirty();
452 end
453 end
454 end;
455
456 if self.door ~= nil then
457 addTrigger(self.door.triggerNode, "onDoorTrigger", self);
458 end;
459
460 -- initially update dayNightObjects
461 self:weatherChanged()
462 g_currentMission.environment:addHourChangeListener(self)
463end

setTipOcclusionAreaDirty

Description
Set tip occlusion area dirty
Definition
setTipOcclusionAreaDirty()
Code
467function Placeable:setTipOcclusionAreaDirty()
468 if self.tipOcclusionUpdateArea ~= nil and self.nodeId ~= 0 then
469 local x, z, sizeX, sizeZ = unpack(self.tipOcclusionUpdateArea);
470 local x1,_,z1 = localToWorld(self.nodeId, x+sizeX*0.5, 0, z+sizeZ*0.5);
471 local x2,_,z2 = localToWorld(self.nodeId, x-sizeX*0.5, 0, z+sizeZ*0.5);
472 local x3,_,z3 = localToWorld(self.nodeId, x+sizeX*0.5, 0, z-sizeZ*0.5);
473 local x4,_,z4 = localToWorld(self.nodeId, x-sizeX*0.5, 0, z-sizeZ*0.5);
474 local minX = math.min(math.min(x1, x2), math.min(x3, x4));
475 local maxX = math.max(math.max(x1, x2), math.max(x3, x4));
476 local minZ = math.min(math.min(z1, z2), math.min(z3, z4));
477 local maxZ = math.max(math.max(z1, z2), math.max(z3, z4));
478 TipUtil.setCollisionMapAreaDirty(minX, minZ, maxX, maxZ);
479 end
480end

alignToTerrain

Description
Align placeable to terrain
Definition
alignToTerrain()
Code
484function Placeable:alignToTerrain()
485 if not self.alignToWorldY then
486 local x1,y1,z1 = getWorldTranslation(self.nodeId);
487 y1 = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x1,y1,z1);
488 setTranslation(self.nodeId, x1,y1,z1);
489 local x2,y2,z2 = getWorldTranslation(self.pos1Node)
490 y2 = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x2,y2,z2);
491 local x3,y3,z3 = getWorldTranslation(self.pos2Node)
492 y3 = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x3,y3,z3);
493 local x4,y4,z4 = getWorldTranslation(self.pos3Node);
494 y4 = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x4,y4,z4);
495 local dirX = x2 - x1;
496 local dirY = y2 - y1;
497 local dirZ = z2 - z1;
498 local dir2X = x3 - x4;
499 local dir2Y = y3 - y4;
500 local dir2Z = z3 - z4;
501 local upX,upY,upZ = Utils.crossProduct(dir2X, dir2Y, dir2Z, dirX, dirY, dirZ);
502 setDirection(self.nodeId, dirX, dirY, dirZ, upX,upY,upZ);
503 end;
504end;

clearFoliageAndTipAreas

Description
Clear foliage and tipAny from clearAreas
Definition
clearFoliageAndTipAreas()
Code
508function Placeable:clearFoliageAndTipAreas()
509 if self.isServer then
510 local numAreas = table.getn(self.clearAreas);
511 for i=1, numAreas do
512 local x,_,z = getWorldTranslation(self.clearAreas[i].start);
513 local x1,_,z1 = getWorldTranslation(self.clearAreas[i].width);
514 local x2,_,z2 = getWorldTranslation(self.clearAreas[i].height);
515 -- clear foliage
516 Utils.updateDestroyCommonArea(x, z, x1, z1, x2, z2, false)
517 Utils.eraseTireTrack(x, z, x1, z1, x2, z2)
518 -- clear tipAny
519 TipUtil.clearArea(x, z, x1, z1, x2, z2)
520 end;
521 end
522end;

initPose

Description
Initialize pose
Definition
initPose(float x, float y, float z, float rx, float ry, float rz, boolean initRandom)
Arguments
floatxx world position
floatyy world position
floatzz world position
floatrxrx world rotation
floatryry world rotation
floatrzrz world rotation
booleaninitRandominitialize random
Code
533function Placeable:initPose(x,y,z, rx,ry,rz, initRandom)
534 setTranslation(self.nodeId, x, y, z);
535 setRotation(self.nodeId, rx, ry, rz);
536end;

collectPickObjects

Description
Collect pick objects
Definition
collectPickObjects(integer node)
Arguments
integernodenode id
Code
541function Placeable:collectPickObjects(node)
542 if getRigidBodyType(node) ~= "NoRigidBody" then
543 table.insert(self.pickObjects, node);
544 end;
545 local numChildren = getNumOfChildren(node);
546 for i=1, numChildren do
547 self:collectPickObjects(getChildAt(node, i-1));
548 end;
549end;

loadFromAttributesAndNodes

Description
Loading from attributes and nodes
Definition
loadFromAttributesAndNodes(integer xmlFile, string key, boolean resetVehicles)
Arguments
integerxmlFileid of xml object
stringkeykey
booleanresetVehiclesreset vehicles
Return Values
booleansuccesssuccess
Code
557function Placeable:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
558
559 local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, key.."#position"));
560 local xRot,yRot,zRot = Utils.getVectorFromString(getXMLString(xmlFile, key.."#rotation"));
561 if x == nil or y == nil or z == nil or xRot == nil or yRot == nil or zRot == nil then
562 return false;
563 end;
564 local xmlFilename = getXMLString(xmlFile, key.."#filename");
565 if xmlFilename == nil then
566 return false;
567 end;
568 xmlFilename = Utils.convertFromNetworkFilename(xmlFilename);
569
570 if self:load(xmlFilename, x,y,z, xRot, yRot, zRot, false, false) then
571 self.age = Utils.getNoNil(getXMLFloat(xmlFile, key.."#age"), 0);
572 self.price = Utils.getNoNil(getXMLInt(xmlFile, key.."#price"), self.price);
573 self.isLoadedFromSavegame = true;
574 self:finalizePlacement();
575 return true;
576 else
577 return false;
578 end;
579end;

getSaveAttributesAndNodes

Description
Get save attributes and nodes
Definition
getSaveAttributesAndNodes(string nodeIdent)
Arguments
stringnodeIdentnode ident
Return Values
stringattributesattributes
stringnodesnodes
Code
586function Placeable:getSaveAttributesAndNodes(nodeIdent)
587 local x,y,z = getTranslation(self.nodeId);
588 local xRot,yRot,zRot = getRotation(self.nodeId);
589 local attributes = 'filename="'.. Utils.encodeToHTML(Utils.convertToNetworkFilename(self.configFileName))..'" position="'..x..' '..y..' '..z..'" rotation="'..xRot..' '..yRot..' '..zRot..'" age="'..tostring(self.age)..'" price="'..tostring(self.price)..'"';
590 local nodes = "";
591 return attributes, nodes;
592end;

update

Description
Update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
602function Placeable:update(dt)
603 if self.door ~= nil then
604 local door = self.door;
605 if door.isMoving then
606 local movement = door.movementSpeed*dt;
607 if door.isOpening then
608 movement = -movement;
609 end;
610 local x,y,z = getTranslation(door.leftDoorNode);
611 z = Utils.clamp(z + movement, -door.movement, 0);
612 if z == 0 or z == -door.movement then
613 door.isMoving = false;
614 end;
615 setTranslation(door.leftDoorNode, x,y,z);
616
617 local x,y,z = getTranslation(door.rightDoorNode);
618 z = Utils.clamp(z - movement, 0, door.movement);
619 if z == 0 or z == door.movement then
620 door.isMoving = false;
621 end;
622 setTranslation(door.rightDoorNode, x,y,z);
623 end;
624 if self.isClient then
625 if self.sampleDoor.isPlaying and (self.sampleDoorStartTime < g_currentMission.time or not self.door.isMoving) then
626 self:playDoorSound(false);
627 end
628 end
629 end;
630
631 if self.sampleIdle ~= nil then
632 if not self.sampleIdle.isPlaying then
633 SoundUtil.play3DSample(self.sampleIdle)
634 self.sampleIdle.isPlaying = true
635 end
636 end
637end;

onDoorTrigger

Description
Door trigger
Definition
onDoorTrigger(integer triggerId, integer otherId, boolean onEnter, boolean onLeave, boolean onStay, integer otherShapeId)
Arguments
integertriggerIdid of trigger
integerotherIdid of actor
booleanonEnteron enter
booleanonLeaveon leave
booleanonStayon stay
integerotherShapeIdid of other actor
Code
650function Placeable:onDoorTrigger(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
651 if onEnter or onLeave then
652 if g_currentMission.players[otherId] ~= nil then
653 if onEnter then
654 if not self.door.isOpening then
655 self.door.isOpening = true;
656 self.door.isMoving = true;
657 self:playDoorSound(true);
658 end
659 elseif onLeave then
660 if self.door.isOpening then
661 self.door.isOpening = false;
662 self.door.isMoving = true;
663 self:playDoorSound(true);
664 end;
665 end;
666 end;
667 end;
668end;

playDoorSound

Description
Play door soundFilename
Definition
playDoorSound(boolean play)
Arguments
booleanplayplay soundFilename
Code
673function Placeable:playDoorSound(play)
674 if self.sampleDoor ~= nil then
675 if play and not self.sampleDoor.isPlaying then
676 SoundUtil.play3DSample(self.sampleDoor);
677 self.sampleDoorStartTime = g_currentMission.time + self.sampleDoor.duration;
678 self.sampleDoor.isPlaying = true;
679 else
680 SoundUtil.stop3DSample(self.sampleDoor);
681 self.sampleDoor.isPlaying = false;
682 end
683 end
684end

getPrice

Description
Returns price
Definition
getPrice()
Return Values
integerpriceprice
Code
689function Placeable:getPrice()
690 return self.price;
691end

onSell

Description
Called on sell
Definition
onSell()
Code
703function Placeable:onSell()
704 if self.isServer then
705 self:setTipOcclusionAreaDirty();
706 end
707end

getDailyUpKeep

Description
Returns daily up keep
Definition
getDailyUpKeep()
Return Values
integerdailyUpKeepdaily up keep
Code
712function Placeable:getDailyUpKeep()
713 local storeItem = StoreItemsUtil.storeItemsByXMLFilename[self.configFileName:lower()]
714 local multiplier = 1
715 if storeItem.lifetime ~= nil and storeItem.lifetime ~= 0 then
716 local ageMultiplier = math.min(self.age/storeItem.lifetime, 1)
717 multiplier = 1 + EconomyManager.MAX_DAILYUPKEEP_MULTIPLIER * ageMultiplier
718 end
719 return StoreItemsUtil.getDailyUpkeep(storeItem, nil) * multiplier
720end

getSellPrice

Description
Returns sell price
Definition
getSellPrice()
Return Values
integersellPricesell price
Code
725function Placeable:getSellPrice()
726 local priceMultiplier = 0.5
727 local maxVehicleAge = StoreItemsUtil.storeItemsByXMLFilename[self.configFileName:lower()].lifetime;
728
729 if maxVehicleAge ~= nil and maxVehicleAge ~= 0 then
730 priceMultiplier = priceMultiplier * math.exp(-3.5 * math.min(self.age/maxVehicleAge, 1))
731 end
732
733 return math.floor(self.price * math.max(priceMultiplier, 0.05));
734end

hourChanged

Description
Called if hour changed
Definition
hourChanged()
Code
738function Placeable:hourChanged()
739 if self.isServer then
740 g_currentMission:addSharedMoney(self.incomePerHour, "propertyIncome");
741 g_currentMission:addMoneyChange(self.incomePerHour, EconomyManager.MONEY_TYPE_PROPERTY_INCOME);
742 end;
743end

dayChanged

Description
Called if day changed
Definition
dayChanged()
Code
747function Placeable:dayChanged()
748 self.age = self.age + 1
749end

weatherChanged

Description
Called if weather changed
Definition
weatherChanged()
Code
753function Placeable:weatherChanged()
754 if g_currentMission ~= nil and g_currentMission.environment ~= nil and self.dayNightObjects ~= nil then
755 for _, dayNightObject in pairs(self.dayNightObjects) do
756 setVisibility(dayNightObject.node, (g_currentMission.environment.isSunOn and dayNightObject.visibleDay) or (dayNightObject.visibleNight and (not g_currentMission.environment.isSunOn and g_currentMission.environment.currentRain == nil)))
757 end
758 end;
759end;

getSpecValueIncomePerHour

Description
Returns value of income per hour
Definition
getSpecValueIncomePerHour(table storeItem, table realItem)
Arguments
tablestoreItemstore item
tablerealItemreal item
Return Values
integerincomePerHourincome per hour
Code
766function Placeable.getSpecValueIncomePerHour(storeItem, realItem)
767 if storeItem.incomePerHour[1] ~= 0 and storeItem.incomePerHour[2] ~= 0 and storeItem.incomePerHour[3] ~= 0 and g_currentMission ~= nil then
768 return string.format(g_i18n:getText("shop_incomeValue"), g_i18n:formatMoney(storeItem.incomePerHour[g_currentMission.missionInfo.difficulty]))
769 end
770 return nil
771end