93 | function SmartAttach:doSmartAttach(targetVehicle, inputJointDescIndex, jointDescIndex, noEventSend) |
94 | SmartAttachEvent.sendEvent(self, targetVehicle, inputJointDescIndex, jointDescIndex, noEventSend) |
95 | |
96 | if self.isServer then |
97 | local attacherVehicle = self:getAttacherVehicle() |
98 | if attacherVehicle ~= nil then |
99 | attacherVehicle:detachImplementByObject(self) |
100 | end |
101 | |
102 | targetVehicle:attachImplement(self, inputJointDescIndex, jointDescIndex, false) |
103 | end |
104 | end |
108 | function SmartAttach:getCanBeSmartAttached() |
109 | local spec = self.spec_smartAttach |
110 | |
111 | local targetVehicle = spec.targetVehicle |
112 | if targetVehicle == nil then |
113 | return false |
114 | end |
115 | |
116 | local activeForInput = self:getIsActiveForInput(true) or spec.targetVehicle:getIsActiveForInput(true) |
117 | if not activeForInput then |
118 | return false |
119 | end |
120 | |
121 | local attacherJoint = targetVehicle:getAttacherJoints()[spec.jointDescIndex].jointTransform |
122 | local inputAttacherJoint = self:getInputAttacherJoints()[spec.inputJointDescIndex].node |
123 | local x1, _, z1 = getWorldTranslation(attacherJoint) |
124 | local x2, _, z2 = getWorldTranslation(inputAttacherJoint) |
125 | |
126 | local distance = MathUtil.vector2Length(x1-x2, z1-z2) |
127 | local yRot = Utils.getYRotationBetweenNodes(attacherJoint, inputAttacherJoint); |
128 | |
129 | return distance < spec.distanceThreshold and math.abs(yRot) < spec.angleThreshold |
130 | end |
36 | function SmartAttach:onLoad(savegame) |
37 | local spec = self.spec_smartAttach |
38 | |
39 | spec.inputJointDescIndex = nil |
40 | local jointTypeStr = getXMLString(self.xmlFile, "vehicle.smartAttach#jointType") |
41 | if jointTypeStr ~= nil then |
42 | local jointType = AttacherJoints.jointTypeNameToInt[jointTypeStr] |
43 | if jointType ~= nil then |
44 | for inputJointDescIndex, inputAttacherJoint in pairs(self:getInputAttacherJoints()) do |
45 | if inputAttacherJoint.jointType == jointType then |
46 | spec.inputJointDescIndex = inputJointDescIndex |
47 | break |
48 | end |
49 | end |
50 | spec.jointType = jointType |
51 | |
52 | if spec.inputJointDescIndex == nil then |
53 | print("Warning: SmartAttach jointType not defined in '"..self.configFileName.."'!") |
54 | end |
55 | else |
56 | print("Warning: invalid jointType " .. jointTypeStr) |
57 | end |
58 | end |
59 | |
60 | local triggerNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.smartAttach#trigger"), self.i3dMappings) |
61 | if triggerNode ~= nil then |
62 | spec.trigger = triggerNode |
63 | addTrigger(spec.trigger, "smartAttachCallback", self) |
64 | end |
65 | |
66 | spec.targetVehicle = nil |
67 | spec.targetVehicleCount = 0 |
68 | spec.jointDescIndex = nil |
69 | spec.activatable = SmartAttachActivatable:new(self) |
70 | |
71 | spec.distanceThreshold = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.smartAttach#distanceThreshold"), 3.5) |
72 | spec.angleThreshold = Utils.getNoNilRad(getXMLFloat(self.xmlFile, "vehicle.smartAttach#angleThreshold"), math.rad(20)) |
73 | end |
149 | function SmartAttach:smartAttachCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
150 | local spec = self.spec_smartAttach |
151 | |
152 | if onEnter then |
153 | local vehicle = g_currentMission.nodeToObject[otherActorId] |
154 | if vehicle ~= nil then |
155 | if spec.targetVehicle == nil then |
156 | if vehicle ~= nil and vehicle ~= self and vehicle.getAttacherJoints ~= nil then |
157 | for i, jointDesc in ipairs(vehicle:getAttacherJoints()) do |
158 | if jointDesc.jointIndex == 0 and jointDesc.jointType == spec.jointType then |
159 | spec.targetVehicle = vehicle |
160 | spec.jointDescIndex = i |
161 | spec.targetVehicleCount = 0 |
162 | |
163 | local name = Utils.getNoNil(self.typeDesc, "") |
164 | local storeItem = g_storeManager:getItemByXMLFilename(self.configFileName:lower()) |
165 | if storeItem ~= nil then |
166 | name = storeItem.name |
167 | end |
168 | |
169 | if self:getAttacherVehicle() == nil then |
170 | spec.activatable.activateText = string.format(g_i18n:getText("action_doSmartAttachGround", self.customEnvironment), name) |
171 | else |
172 | spec.activatable.activateText = string.format(g_i18n:getText("action_doSmartAttachTransform", self.customEnvironment), name) |
173 | end |
174 | |
175 | g_currentMission:addActivatableObject(spec.activatable) |
176 | break |
177 | end |
178 | end |
179 | end |
180 | end |
181 | |
182 | if vehicle == spec.targetVehicle then |
183 | spec.targetVehicleCount = spec.targetVehicleCount + 1 |
184 | end |
185 | end |
186 | elseif onLeave then |
187 | if spec.targetVehicle ~= nil then |
188 | local object = g_currentMission.nodeToObject[otherActorId] |
189 | if object ~= nil and object == spec.targetVehicle then |
190 | spec.targetVehicleCount = spec.targetVehicleCount - 1 |
191 | if spec.targetVehicleCount <= 0 then |
192 | spec.targetVehicle = nil |
193 | g_currentMission:removeActivatableObject(spec.activatable) |
194 | spec.targetVehicleCount = 0 |
195 | end |
196 | end |
197 | end |
198 | end |
199 | end |