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 | |
3 | Placeable = {}; |
4 | Placeable_mt = Class(Placeable, Object); |
5 | |
6 | InitStaticObjectClass(Placeable, "Placeable", ObjectIds.OBJECT_PLACEABLE); |
7 | |
8 | function Placeable:new(isServer, isClient, mt) |
9 | if mt == nil then |
10 | mt = Placeable_mt; |
11 | end; |
12 | |
13 | local self = Object:new(isServer, isClient, mt); |
14 | self.nodeId = 0; |
15 | |
16 | self.useRandomYRotation = false; |
17 | self.useManualYRotation = false; |
18 | self.placementSizeX = 1; |
19 | self.placementSizeZ = 1; |
20 | self.placementTestSizeX = 1; |
21 | self.placementTestSizeZ = 1; |
22 | self.pickObjects = {}; |
23 | self.isolated = false; |
24 | self.isDeleted = false; |
25 | self.useMultiRootNode = false; |
26 | |
27 | registerObjectClassName(self, "Placeable"); |
28 | return self; |
29 | end; |
30 | |
31 | function Placeable:delete() |
32 | self.isDeleted = true; |
33 | if self.i3dFilename ~= nil then |
34 | Utils.releaseSharedI3DFile(self.i3dFilename, nil, true); |
35 | end |
36 | unregisterObjectClassName(self); |
37 | g_currentMission:removeItemToSave(self); |
38 | g_currentMission:removePlaceable(self); |
39 | for _, node in pairs(self.pickObjects) do |
40 | g_currentMission:removeNodeObject(node); |
41 | end; |
42 | if self.nodeId ~= 0 and entityExists(self.nodeId) then |
43 | self:setCollisionMask(self.nodeId, 0); |
44 | setVisibility(self.nodeId, false); |
45 | else |
46 | self.nodeId = 0; |
47 | end; |
48 | g_currentMission:addPlaceableToDelete(self, 300); |
49 | end; |
50 | |
51 | function Placeable:deleteFinal() |
52 | if self.nodeId ~= 0 then |
53 | delete(self.nodeId); |
54 | self.nodeId = 0; |
55 | end; |
56 | end; |
57 | |
58 | function Placeable:setCollisionMask(nodeId, mask) |
59 | setCollisionMask(nodeId, mask); |
60 | local numChildren = getNumOfChildren(nodeId); |
61 | for i=0,numChildren-1 do |
62 | local childId = getChildAt(nodeId, i); |
63 | self:setCollisionMask(childId, mask) |
64 | end; |
65 | end; |
66 | |
67 | function Placeable:getIsPlayerInRange(distance, player) |
68 | if self.nodeId ~= 0 then |
69 | distance = Utils.getNoNil(distance, 10); |
70 | if player == nil then |
71 | for _, player in pairs(g_currentMission.players) do |
72 | if self:isInActionDistance(player, self.nodeId, distance) then |
73 | return true, player; |
74 | end; |
75 | end; |
76 | else |
77 | return self:isInActionDistance(player, self.nodeId, distance), player; |
78 | end; |
79 | end |
80 | return false, nil; |
81 | end; |
82 | |
83 | function Placeable:isInActionDistance(player, refNode, distance) |
84 | local x,y,z = getWorldTranslation(refNode); |
85 | local px,py,pz = getWorldTranslation(player.rootNode); |
86 | local dx,dz = px-x, pz-z; |
87 | if dx*dx + dz*dz < distance*distance then |
88 | return true; |
89 | end |
90 | |
91 | return false; |
92 | end; |
93 | |
94 | function Placeable:readStream(streamId, connection) |
95 | Placeable:superClass().readStream(self, streamId, connection); |
96 | if connection:getIsServer() then |
97 | local xmlFilename = Utils.convertFromNetworkFilename(streamReadString(streamId)); |
98 | local x=streamReadFloat32(streamId); |
99 | local y=streamReadFloat32(streamId); |
100 | local z=streamReadFloat32(streamId); |
101 | local rx=Utils.readCompressedAngle(streamId); |
102 | local ry=Utils.readCompressedAngle(streamId); |
103 | local rz=Utils.readCompressedAngle(streamId); |
104 | self:load(xmlFilename, x,y,z, rx,ry,rz, false, false); |
105 | self:finalizePlacement(); |
106 | end; |
107 | end; |
108 | |
109 | function Placeable:writeStream(streamId, connection) |
110 | Placeable:superClass().writeStream(self, streamId, connection); |
111 | if not connection:getIsServer() then |
112 | streamWriteString(streamId, Utils.convertToNetworkFilename(self.xmlFilename)); |
113 | local x,y,z = getTranslation(self.nodeId) |
114 | local x_rot,y_rot,z_rot = getRotation(self.nodeId); |
115 | streamWriteFloat32(streamId, x); |
116 | streamWriteFloat32(streamId, y); |
117 | streamWriteFloat32(streamId, z); |
118 | Utils.writeCompressedAngle(streamId, x_rot); |
119 | Utils.writeCompressedAngle(streamId, y_rot); |
120 | Utils.writeCompressedAngle(streamId, z_rot); |
121 | end; |
122 | end; |
123 | |
124 | function Placeable:readUpdateStream(streamId, timestamp, connection) |
125 | end; |
126 | |
127 | function Placeable:writeUpdateStream(streamId, connection, dirtyMask) |
128 | end; |
129 | |
130 | function Placeable:createNode(i3dFilename) |
131 | self.i3dFilename = i3dFilename; |
132 | local nodeRoot = Utils.loadSharedI3DFile(i3dFilename, nil, false, false); |
133 | if nodeRoot == 0 then |
134 | return false; |
135 | end; |
136 | |
137 | if self.useMultiRootNode then |
138 | link(getRootNode(), nodeRoot); |
139 | self.nodeId = nodeRoot; |
140 | else |
141 | local nodeId = getChildAt(nodeRoot, 0); |
142 | if nodeId == 0 then |
143 | delete(nodeRoot); |
144 | return false; |
145 | end |
146 | link(getRootNode(), nodeId); |
147 | delete(nodeRoot); |
148 | self.nodeId = nodeId; |
149 | end |
150 | |
151 | |
152 | return true; |
153 | end; |
154 | |
155 | function Placeable:load(xmlFilename, x,y,z, rx,ry,rz, initRandom) |
156 | self.xmlFilename = xmlFilename; |
157 | self.customEnvironment, self.baseDirectory = Utils.getModNameAndBaseDirectory(xmlFilename); |
158 | |
159 | local xmlFile = loadXMLFile("TempXML", xmlFilename); |
160 | if xmlFile == 0 then |
161 | return false; |
162 | end; |
163 | local i3dFilename = getXMLString(xmlFile, "placeable.filename"); |
164 | self.placementSizeX = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.placement#sizeX"), self.placementSizeX); |
165 | self.placementSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.placement#sizeZ"), self.placementSizeZ); |
166 | self.placementTestSizeX = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.placement#testSizeX"), self.placementSizeX); |
167 | self.placementTestSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "placeable.placement#testSizeZ"), self.placementSizeZ); |
168 | self.useRandomYRotation = Utils.getNoNil(getXMLBool(xmlFile, "placeable.placement#useRandomYRotation"), self.useRandomYRotation); |
169 | self.useManualYRotation = Utils.getNoNil(getXMLBool(xmlFile, "placeable.placement#useManualYRotation"), self.useManualYRotation); |
170 | self.alignToWorldY = Utils.getNoNil(getXMLBool(xmlFile, "placeable.placement#alignToWorldY"), true); |
171 | |
172 | |
173 | if i3dFilename == nil then |
174 | delete(xmlFile); |
175 | return false; |
176 | end; |
177 | self.i3dFilename = Utils.getFilename(i3dFilename, self.baseDirectory); |
178 | |
179 | if not self:createNode(self.i3dFilename) then |
180 | delete(xmlFile); |
181 | return false; |
182 | end; |
183 | self:initPose(x,y,z, rx,ry,rz, initRandom); |
184 | |
185 | if not self.alignToWorldY then |
186 | self.pos1Node = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.placement#pos1Node")); |
187 | self.pos2Node = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.placement#pos2Node")); |
188 | self.pos3Node = Utils.indexToObject(self.nodeId, getXMLString(xmlFile, "placeable.placement#pos3Node")); |
189 | if self.pos1Node == nil or self.pos2Node == nil or self.pos3Node == nil then |
190 | self.alignToWorldY = true; |
191 | print("Warning: Pos1Node, Pos2Node and Pos3Node has to be set if alignToWorldY is false!"); |
192 | end; |
193 | end; |
194 | |
195 | delete(xmlFile); |
196 | |
197 | return true; |
198 | end; |
199 | |
200 | function Placeable:finalizePlacement() |
201 | if not self.isolated then |
202 | self:alignToTerrain() |
203 | |
204 | addToPhysics(self.nodeId); |
205 | g_currentMission:addItemToSave(self); |
206 | g_currentMission:addPlaceable(self); |
207 | |
208 | self:collectPickObjects(self.nodeId); |
209 | |
210 | for _, node in pairs(self.pickObjects) do |
211 | g_currentMission:addNodeObject(node, self); |
212 | end; |
213 | end; |
214 | end |
215 | |
216 | function Placeable:alignToTerrain() |
217 | if not self.alignToWorldY then |
218 | local x1,y1,z1 = getWorldTranslation(self.nodeId); |
219 | y1 = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x1,y1,z1); |
220 | setTranslation(self.nodeId, x1,y1,z1); |
221 | local x2,y2,z2 = getWorldTranslation(self.pos1Node) |
222 | y2 = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x2,y2,z2); |
223 | local x3,y3,z3 = getWorldTranslation(self.pos2Node) |
224 | y3 = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x3,y3,z3); |
225 | local x4,y4,z4 = getWorldTranslation(self.pos3Node); |
226 | y4 = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x4,y4,z4); |
227 | local dirX = x2 - x1; |
228 | local dirY = y2 - y1; |
229 | local dirZ = z2 - z1; |
230 | local dir2X = x3 - x4; |
231 | local dir2Y = y3 - y4; |
232 | local dir2Z = z3 - z4; |
233 | local upX,upY,upZ = Utils.crossProduct(dir2X, dir2Y, dir2Z, dirX, dirY, dirZ); |
234 | setDirection(self.nodeId, dirX, dirY, dirZ, upX,upY,upZ); |
235 | end; |
236 | end; |
237 | |
238 | function Placeable:initPose(x,y,z, rx,ry,rz, initRandom) |
239 | setTranslation(self.nodeId, x, y, z); |
240 | setRotation(self.nodeId, rx, ry, rz); |
241 | end; |
242 | |
243 | function Placeable:collectPickObjects(node) |
244 | if getRigidBodyType(node) ~= "NoRigidBody" then |
245 | table.insert(self.pickObjects, node); |
246 | end; |
247 | local numChildren = getNumOfChildren(node); |
248 | for i=1, numChildren do |
249 | self:collectPickObjects(getChildAt(node, i-1)); |
250 | end; |
251 | end; |
252 | |
253 | function Placeable:loadFromAttributesAndNodes(xmlFile, key, resetVehicles) |
254 | |
255 | local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, key.."#position")); |
256 | local xRot,yRot,zRot = Utils.getVectorFromString(getXMLString(xmlFile, key.."#rotation")); |
257 | if x == nil or y == nil or z == nil or xRot == nil or yRot == nil or zRot == nil then |
258 | return false; |
259 | end; |
260 | local xmlFilename = getXMLString(xmlFile, key.."#filename"); |
261 | if xmlFilename == nil then |
262 | return false; |
263 | end; |
264 | xmlFilename = Utils.convertFromNetworkFilename(xmlFilename); |
265 | |
266 | if self:load(xmlFilename, x,y,z, xRot, yRot, zRot, false, false) then |
267 | self:finalizePlacement(); |
268 | return true; |
269 | else |
270 | return false; |
271 | end; |
272 | end; |
273 | |
274 | function Placeable:getSaveAttributesAndNodes(nodeIdent) |
275 | |
276 | local x,y,z = getTranslation(self.nodeId); |
277 | local xRot,yRot,zRot = getRotation(self.nodeId); |
278 | local attributes = 'filename="'.. Utils.encodeToHTML(Utils.convertToNetworkFilename(self.xmlFilename))..'" position="'..x..' '..y..' '..z..'" rotation="'..xRot..' '..yRot..' '..zRot..'"'; |
279 | local nodes = ""; |
280 | return attributes, nodes; |
281 | end; |
282 | |
283 | function Placeable:getNeedsSaving() |
284 | return true; |
285 | end; |
286 | |
287 | function Placeable:update(dt) |
288 | end; |
289 | |
290 | function Placeable:updateTick(dt) |
291 | end;
|
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de