224 | function AutoLoader:autoLoaderPickupTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
225 | if onEnter then |
226 | -- this happens if a compound child of a deleted compound is entering |
227 | if otherActorId ~= 0 then |
228 | local object = g_currentMission:getNodeObject(otherActorId) |
229 | if object ~= nil then |
230 | if self:getIsAutoLoadingAllowed() and self:getIsValidObject(object) then |
231 | local spec = self.spec_autoLoader |
232 | if spec.triggeredObjects[object] == nil then |
233 | if spec.numTriggeredObjects < spec.maxObjects then |
234 | local firstValidLoadPlace = self:getFirstValidLoadPlace() |
235 | if firstValidLoadPlace ~= -1 then |
236 | local loadPlace = spec.loadPlaces[firstValidLoadPlace] |
237 | local x, y, z = getWorldTranslation(loadPlace.node) |
238 | local objectNodeId = object.nodeId or object.components[1].node |
239 | |
240 | removeFromPhysics(objectNodeId) |
241 | |
242 | setTranslation(objectNodeId, x, y, z) |
243 | setWorldRotation(objectNodeId, getWorldRotation(loadPlace.node)) |
244 | |
245 | addToPhysics(objectNodeId) |
246 | |
247 | local vx, vy, vz = getLinearVelocity(self:getParentComponent(loadPlace.node)) |
248 | setLinearVelocity(objectNodeId, vx, vy, vz) |
249 | |
250 | spec.triggeredObjects[object] = 0 |
251 | spec.numTriggeredObjects = spec.numTriggeredObjects + 1 |
252 | |
253 | if spec.useTensionBelts and self.setAllTensionBeltsActive ~= nil then |
254 | self:setAllTensionBeltsActive(false, false) |
255 | self:setAllTensionBeltsActive(true, false) |
256 | end |
257 | end |
258 | end |
259 | end |
260 | end |
261 | end |
262 | end |
263 | end |
264 | end |
268 | function AutoLoader:autoLoaderTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
269 | local spec = self.spec_autoLoader |
270 | |
271 | if onEnter then |
272 | local object = g_currentMission:getNodeObject(otherActorId) |
273 | if object ~= nil then |
274 | if self:getIsValidObject(object) then |
275 | if spec.triggeredObjects[object] == nil then |
276 | spec.triggeredObjects[object] = 0 |
277 | spec.numTriggeredObjects = spec.numTriggeredObjects + 1 |
278 | end |
279 | |
280 | if spec.triggeredObjects[object] == 0 then |
281 | if object.addDeleteListener ~= nil then |
282 | object:addDeleteListener(self, "onDeleteAutoLoaderObject") |
283 | end |
284 | end |
285 | |
286 | spec.triggeredObjects[object] = spec.triggeredObjects[object] + 1 |
287 | end |
288 | end |
289 | elseif onLeave then |
290 | local object = g_currentMission:getNodeObject(otherActorId) |
291 | if object ~= nil then |
292 | if self:getIsValidObject(object) then |
293 | if spec.triggeredObjects[object] ~= nil then |
294 | spec.triggeredObjects[object] = spec.triggeredObjects[object] - 1 |
295 | |
296 | if spec.triggeredObjects[object] == 0 then |
297 | spec.triggeredObjects[object] = nil |
298 | spec.numTriggeredObjects = spec.numTriggeredObjects - 1 |
299 | |
300 | if object.removeDeleteListener ~= nil then |
301 | object:removeDeleteListener(self) |
302 | end |
303 | end |
304 | |
305 | if next(spec.triggeredObjects) == nil then |
306 | spec.currentPlace = 1 |
307 | end |
308 | end |
309 | end |
310 | end |
311 | end |
312 | end |
185 | function AutoLoader:getFirstValidLoadPlace() |
186 | local spec = self.spec_autoLoader |
187 | |
188 | for i=1, #spec.loadPlaces do |
189 | local loadPlace = spec.loadPlaces[i] |
190 | local x, y, z = getWorldTranslation(loadPlace.node) |
191 | local rx, ry, rz = getWorldRotation(loadPlace.node) |
192 | local offsetX, offsetY, offsetZ = unpack(spec.loadPlaceOffset) |
193 | local sizeX, sizeY, sizeZ = unpack(spec.loadPlaceSize) |
194 | |
195 | -- collision mask : all bits except bit 13, 23, 30 |
196 | spec.foundObject = false |
197 | overlapBox(x + offsetX, y + offsetY + offsetZ, z, rx, ry, rz, sizeX / 2, sizeY / 2, sizeZ / 2, "autoLoaderOverlapCallback", self, 3212828671, true, false, true) |
198 | |
199 | if not spec.foundObject then |
200 | return i |
201 | end |
202 | end |
203 | |
204 | return -1 |
205 | end |
131 | function AutoLoader:getIsValidObject(object) |
132 | local spec = self.spec_autoLoader |
133 | |
134 | if spec.supportedObject ~= nil then |
135 | local objectFilename = object.configFileName or object.i3dFilename |
136 | if objectFilename ~= nil then |
137 | if not string.endsWith(objectFilename, spec.supportedObject) then |
138 | return false |
139 | end |
140 | else |
141 | return false |
142 | end |
143 | end |
144 | |
145 | if object == self then |
146 | return false |
147 | end |
148 | |
149 | if spec.useBales and (not object:isa(Bale) or not object:getAllowPickup()) then |
150 | return false |
151 | end |
152 | |
153 | if not g_currentMission.accessHandler:canFarmAccess(self:getActiveFarm(), object) then |
154 | return false |
155 | end |
156 | |
157 | if spec.fillUnitIndex ~= nil and object.getFillType ~= nil and not self:getFillUnitSupportsFillType(spec.fillUnitIndex, object:getFillType()) then |
158 | return false |
159 | end |
160 | |
161 | return true |
162 | end |
21 | function AutoLoader.initSpecialization() |
22 | local schema = Vehicle.xmlSchema |
23 | schema:setXMLSpecializationType("AutoLoader") |
24 | |
25 | schema:register(XMLValueType.NODE_INDEX, "vehicle.autoLoader.trigger#node", "Trigger node") |
26 | schema:register(XMLValueType.NODE_INDEX, "vehicle.autoLoader.pickupTrigger#node", "Pickup trigger node") |
27 | schema:register(XMLValueType.NODE_INDEX, "vehicle.autoLoader.loadPlaces.loadPlace(?)#node", "Load place node") |
28 | schema:register(XMLValueType.VECTOR_TRANS, "vehicle.autoLoader.loadPlaces#checkOffset", "Check offset from load place node") |
29 | schema:register(XMLValueType.VECTOR_TRANS, "vehicle.autoLoader.loadPlaces#checkSize", "Check size around load place node") |
30 | schema:register(XMLValueType.STRING, "vehicle.autoLoader#supportedObject", "Path to xml of supported object") |
31 | schema:register(XMLValueType.INT, "vehicle.autoLoader#fillUnitIndex", "Fill unit index to check fill type") |
32 | schema:register(XMLValueType.INT, "vehicle.autoLoader#maxObjects", "Max. number of objects to load", "Number of load places") |
33 | schema:register(XMLValueType.BOOL, "vehicle.autoLoader#useBales", "Use for bales", false) |
34 | schema:register(XMLValueType.BOOL, "vehicle.autoLoader#useTensionBelts", "Automatically mount tension belts", "False for mobile, otherwise true") |
35 | |
36 | schema:setXMLSpecializationType() |
37 | end |
66 | function AutoLoader:onLoad(savegame) |
67 | if self.isServer then |
68 | local spec = self.spec_autoLoader |
69 | |
70 | spec.triggerId = self.xmlFile:getValue("vehicle.autoLoader.trigger#node", nil, self.components, self.i3dMappings) |
71 | if spec.triggerId ~= nil then |
72 | addTrigger(spec.triggerId, "autoLoaderTriggerCallback", self) |
73 | end |
74 | |
75 | spec.pickupTriggerId = self.xmlFile:getValue("vehicle.autoLoader.pickupTrigger#node", nil, self.components, self.i3dMappings) |
76 | if spec.pickupTriggerId ~= nil then |
77 | addTrigger(spec.pickupTriggerId, "autoLoaderPickupTriggerCallback", self) |
78 | end |
79 | |
80 | spec.triggeredObjects = {} |
81 | spec.numTriggeredObjects = 0 |
82 | spec.loadPlaces = {} |
83 | |
84 | local i = 0 |
85 | while true do |
86 | local placeKey = string.format("vehicle.autoLoader.loadPlaces.loadPlace(%d)", i) |
87 | if not self.xmlFile:hasProperty(placeKey) then |
88 | break |
89 | end |
90 | |
91 | local entry = {} |
92 | entry.node = self.xmlFile:getValue(placeKey .. "#node", nil, self.components, self.i3dMappings) |
93 | |
94 | if entry.node ~= nil then |
95 | table.insert(spec.loadPlaces, entry) |
96 | end |
97 | |
98 | i = i + 1 |
99 | end |
100 | |
101 | spec.loadPlaceOffset = self.xmlFile:getValue("vehicle.autoLoader.loadPlaces#checkOffset", "0 0 0") |
102 | spec.loadPlaceSize = self.xmlFile:getValue("vehicle.autoLoader.loadPlaces#checkSize", "1 1 1") |
103 | |
104 | spec.supportedObject = self.xmlFile:getValue("vehicle.autoLoader#supportedObject") |
105 | |
106 | spec.fillUnitIndex = self.xmlFile:getValue("vehicle.autoLoader#fillUnitIndex") |
107 | spec.maxObjects = self.xmlFile:getValue("vehicle.autoLoader#maxObjects") or #spec.loadPlaces |
108 | spec.useBales = self.xmlFile:getValue("vehicle.autoLoader#useBales", false) |
109 | spec.useTensionBelts = self.xmlFile:getValue("vehicle.autoLoader#useTensionBelts", not GS_IS_MOBILE_VERSION) |
110 | end |
111 | end |
41 | function AutoLoader.registerFunctions(vehicleType) |
42 | SpecializationUtil.registerFunction(vehicleType, "getIsValidObject", AutoLoader.getIsValidObject) |
43 | SpecializationUtil.registerFunction(vehicleType, "getIsAutoLoadingAllowed", AutoLoader.getIsAutoLoadingAllowed) |
44 | SpecializationUtil.registerFunction(vehicleType, "getFirstValidLoadPlace", AutoLoader.getFirstValidLoadPlace) |
45 | SpecializationUtil.registerFunction(vehicleType, "autoLoaderOverlapCallback", AutoLoader.autoLoaderOverlapCallback) |
46 | SpecializationUtil.registerFunction(vehicleType, "autoLoaderTriggerCallback", AutoLoader.autoLoaderTriggerCallback) |
47 | SpecializationUtil.registerFunction(vehicleType, "autoLoaderPickupTriggerCallback", AutoLoader.autoLoaderPickupTriggerCallback) |
48 | SpecializationUtil.registerFunction(vehicleType, "onDeleteAutoLoaderObject", AutoLoader.onDeleteAutoLoaderObject) |
49 | end |