Script v1.7.1.0
- AI
- Animals
- Contracts
- Debug
- Economy
- Effects
- Events
- Farms
- GUI
- Handtools
- I3d
- Materials
- Misc
- Objects
- Placeables
- Player
- Shop
- Sounds
- Specializations
- AIConveyorBelt
- AIImplement
- AIVehicle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BunkerSiloCompacter
- BunkerSiloInteractor
- BuyableBale
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- JigglingParts
- Leveler
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- MixerWagon
- Motorized
- Mountable
- Mower
- Pickup
- Pipe
- Plow
- PowerConsumer
- PowerTakeOffs
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StrawBlower
- StumpCutter
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TipOccluder
- Trailer
- TreePlanter
- TreeSaw
- TurnOnVehicle
- Washable
- WaterTrailer
- Wearable
- Weeder
- Wheels
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- Triggers
- Utils
- Vehicles
- Weather
Engine v1.7.1.0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- XML
- general
Foundation Reference
AttacherJoints
DescriptionSpecialization for vehicles with attacherJoints allowing attaching/coupling of toolsFunctions
- actionEventAttach
- actionEventLowerAllImplements
- actionEventLowerImplement
- activateAttachments
- addToPhysics
- addToTotalVehicleList
- addVehicleToAIImplementList
- attachableAddToolCameras
- attachableRemoveToolCameras
- calculateAttacherJointMoveUpperLowerAlpha
- callFunctionOnAllImplements
- createAttachmentJoint
- deactivateAttachments
- deactivateAttachmentsLights
- detachImplement
- detachImplementByObject
- detachingIsPossible
- findVehicleInAttachRange
- getAICollisionTriggers
- getAirConsumerUsage
- getAttachedImplements
- getAttacherJointByJointDescIndex
- getAttacherJointDescFromObject
- getAttacherJointIndexFromImplementIndex
- getAttacherJointIndexFromObject
- getAttacherJoints
- getCanToggleAttach
- getChildVehicles
- getDirectionSnapAngle
- getFillLevelInformation
- getImplementByJointDescIndex
- getImplementByObject
- getImplementFromAttacherJointIndex
- getImplementIndexByJointDescIndex
- getImplementIndexByObject
- getIsDashboardGroupActive
- getIsFoldAllowed
- getIsHardAttachAllowed
- getIsReadyForAutomatedTrainTravel
- getIsWheelFoliageDestructionAllowed
- getObjectFromImplementIndex
- getSelectedImplement
- getTotalMass
- handleLowerImplementByAttacherJointIndex
- handleLowerImplementEvent
- hardAttachImplement
- hardDetachImplement
- initSpecialization
- isDetachAllowed
- loadAttacherJointFromXML
- loadAttachmentsFromXMLFile
- loadDashboardGroupFromXML
- onActivate
- onBeaconLightsVisibilityChanged
- onBrake
- onBrakeLightsVisibilityChanged
- onDeactivate
- onDeactivateLights
- onDelete
- onDraw
- onLeaveVehicle
- onLightsTypesMaskChanged
- onLoad
- onPostLoad
- onPostUpdate
- onPreDelete
- onReadStream
- onRegisterActionEvents
- onReverseDirectionChanged
- onReverseLightsVisibilityChanged
- onStateChange
- onTurnedOff
- onTurnedOn
- onTurnLightStateChanged
- onUpdate
- onUpdateTick
- onWriteStream
- playAttachSound
- playDetachSound
- postAttachImplement
- prerequisitesPresent
- raiseActive
- registerActionEvents
- registerEventListeners
- registerEvents
- registerFunctions
- registerJointType
- registerOverwrittenFunctions
- registerSelectableObjects
- registerSelfLoweringActionEvent
- removeActionEvents
- saveAttachmentsToXMLFile
- saveToXMLFile
- setJointMoveDown
- setSelectedImplementByObject
- startAttacherJointCombo
- updateAttacherJointGraphics
- updateAttacherJointRotation
- updateAttacherJointRotationNodes
actionEventAttach
DescriptionDefinitionactionEventAttach()Code
2910 | function AttacherJoints.actionEventAttach(self, actionName, inputValue, callbackState, isAnalog) |
2911 | -- attach or detach something |
2912 | local info = self.spec_attacherJoints.attachableInfo |
2913 | if info.attachable ~= nil and g_currentMission.accessHandler:canFarmAccess(self:getActiveFarm(), info.attachable) then |
2914 | -- attach |
2915 | if info.attacherVehicle.spec_attacherJoints.attacherJoints[info.attacherVehicleJointDescIndex].jointIndex == 0 then |
2916 | info.attacherVehicle:attachImplement(info.attachable, info.attachableJointDescIndex, info.attacherVehicleJointDescIndex) |
2917 | end |
2918 | else |
2919 | -- detach |
2920 | local object = self:getSelectedVehicle() |
2921 | if object ~= nil and object ~= self and object.isDetachAllowed ~= nil then |
2922 | local detachAllowed, warning, showWarning = object:isDetachAllowed() |
2923 | if detachAllowed then |
2924 | if object.getAttacherVehicle ~= nil then |
2925 | local attacherVehicle = object:getAttacherVehicle() |
2926 | if attacherVehicle ~= nil then |
2927 | attacherVehicle:detachImplementByObject(object) |
2928 | end |
2929 | end |
2930 | elseif showWarning == nil or showWarning then |
2931 | g_currentMission:showBlinkingWarning(warning or g_i18n:getText("warning_detachNotAllowed"), 2000) |
2932 | end |
2933 | end |
2934 | end |
2935 | end |
actionEventLowerAllImplements
DescriptionDefinitionactionEventLowerAllImplements()Code
2948 | function AttacherJoints.actionEventLowerAllImplements(self, actionName, inputValue, callbackState, isAnalog) |
2949 | self:startAttacherJointCombo(true) |
2950 | |
2951 | self:getRootVehicle():raiseStateChange(Vehicle.STATE_CHANGE_LOWER_ALL_IMPLEMENTS) |
2952 | end |
actionEventLowerImplement
DescriptionDefinitionactionEventLowerImplement()Code
2939 | function AttacherJoints.actionEventLowerImplement(self, actionName, inputValue, callbackState, isAnalog) |
2940 | -- self is the implement object to lower, so we call the function on the attacher vehicle |
2941 | if self.getAttacherVehicle ~= nil then |
2942 | self:getAttacherVehicle():handleLowerImplementEvent() |
2943 | end |
2944 | end |
activateAttachments
DescriptionCall "activate" on all attachmentsDefinition
activateAttachments()Code
1822 | function AttacherJoints:activateAttachments() |
1823 | local spec = self.spec_attacherJoints |
1824 | |
1825 | for _,v in pairs(spec.attachedImplements) do |
1826 | if v.object ~= nil then |
1827 | v.object:activate() |
1828 | end |
1829 | end |
1830 | end |
addToPhysics
DescriptionAdd to physicsDefinition
addToPhysics()Return Values
boolean | success | success |
2340 | function AttacherJoints:addToPhysics(superFunc) |
2341 | local spec = self.spec_attacherJoints |
2342 | |
2343 | if not superFunc(self) then |
2344 | return false |
2345 | end |
2346 | |
2347 | for _, implement in pairs(spec.attachedImplements) do |
2348 | if not implement.object.isHardAttached then |
2349 | self:createAttachmentJoint(implement) |
2350 | end |
2351 | end |
2352 | |
2353 | return true |
2354 | end |
addToTotalVehicleList
DescriptionDefinitionaddToTotalVehicleList()Code
2416 | function AttacherJoints:addToTotalVehicleList(superFunc, list) |
2417 | superFunc(self, list) |
2418 | |
2419 | for _, implement in pairs(self:getAttachedImplements()) do |
2420 | implement.object:addToTotalVehicleList(list) |
2421 | end |
2422 | end |
addVehicleToAIImplementList
DescriptionDefinitionaddVehicleToAIImplementList()Code
2406 | function AttacherJoints:addVehicleToAIImplementList(superFunc, list) |
2407 | superFunc(self, list) |
2408 | |
2409 | for _, implement in pairs(self:getAttachedImplements()) do |
2410 | implement.object:addVehicleToAIImplementList(list) |
2411 | end |
2412 | end |
attachableAddToolCameras
DescriptionDefinitionattachableAddToolCameras()Code
2475 | function AttacherJoints:attachableAddToolCameras(superFunc) |
2476 | local spec = self.spec_attacherJoints |
2477 | superFunc(self) |
2478 | |
2479 | for _,implement in pairs(spec.attachedImplements) do |
2480 | if implement.object ~= nil then |
2481 | implement.object:attachableAddToolCameras() |
2482 | end |
2483 | end |
2484 | end |
attachableRemoveToolCameras
DescriptionDefinitionattachableRemoveToolCameras()Code
2488 | function AttacherJoints:attachableRemoveToolCameras(superFunc) |
2489 | local spec = self.spec_attacherJoints |
2490 | superFunc(self) |
2491 | |
2492 | for _,implement in pairs(spec.attachedImplements) do |
2493 | if implement.object ~= nil then |
2494 | implement.object:attachableRemoveToolCameras() |
2495 | end |
2496 | end |
2497 | end |
calculateAttacherJointMoveUpperLowerAlpha
DescriptionCalculate move upper and lower alpha of attacher jointDefinition
calculateAttacherJointMoveUpperLowerAlpha(table jointDesc, table object)Arguments
table | jointDesc | joint desc of used attacher |
table | object | object of attached vehicle |
966 | function AttacherJoints:calculateAttacherJointMoveUpperLowerAlpha(jointDesc, object) |
967 | local objectAtttacherJoint = object.spec_attachable.attacherJoint |
968 | |
969 | if jointDesc.allowsLowering then |
970 | |
971 | local lowerDistanceToGround = jointDesc.lowerDistanceToGround |
972 | local upperDistanceToGround = jointDesc.upperDistanceToGround |
973 | |
974 | if objectAtttacherJoint.heightNode ~= nil and jointDesc.rotationNode ~= nil then |
975 | self:updateAttacherJointRotationNodes(jointDesc, 1) |
976 | |
977 | setRotation(jointDesc.jointTransform, unpack(jointDesc.jointOrigRot)) |
978 | local x, y, z = localToLocal(jointDesc.jointTransform, jointDesc.rootNode, 0, 0, 0) |
979 | local delta = jointDesc.lowerDistanceToGround - y |
980 | local hx, hy, hz = localToLocal(jointDesc.jointTransform, jointDesc.rootNode, objectAtttacherJoint.heightNodeOffset[1], objectAtttacherJoint.heightNodeOffset[2], objectAtttacherJoint.heightNodeOffset[3]) |
981 | lowerDistanceToGround = hy + delta |
982 | |
983 | self:updateAttacherJointRotationNodes(jointDesc, 0) |
984 | x, y, z = localToLocal(jointDesc.jointTransform, jointDesc.rootNode, 0, 0, 0) |
985 | delta = jointDesc.upperDistanceToGround - y |
986 | hx, hy, hz = localToLocal(jointDesc.jointTransform, jointDesc.rootNode, objectAtttacherJoint.heightNodeOffset[1], objectAtttacherJoint.heightNodeOffset[2], objectAtttacherJoint.heightNodeOffset[3]) |
987 | upperDistanceToGround = hy + delta |
988 | end |
989 | |
990 | local upperAlpha = MathUtil.clamp((objectAtttacherJoint.upperDistanceToGround - upperDistanceToGround) / (lowerDistanceToGround - upperDistanceToGround), 0, 1) |
991 | local lowerAlpha = MathUtil.clamp((objectAtttacherJoint.lowerDistanceToGround - upperDistanceToGround) / (lowerDistanceToGround - upperDistanceToGround), 0, 1) |
992 | |
993 | if objectAtttacherJoint.allowsLowering and jointDesc.allowsLowering then |
994 | return upperAlpha, lowerAlpha |
995 | else |
996 | if objectAtttacherJoint.isDefaultLowered then |
997 | return lowerAlpha,lowerAlpha |
998 | else |
999 | return upperAlpha,upperAlpha |
1000 | end |
1001 | end |
1002 | end |
1003 | |
1004 | if objectAtttacherJoint.isDefaultLowered then |
1005 | return 1,1 |
1006 | else |
1007 | return 0,0 |
1008 | end |
1009 | end |
callFunctionOnAllImplements
DescriptionDefinitioncallFunctionOnAllImplements()Code
1809 | function AttacherJoints:callFunctionOnAllImplements(functionName, ...) |
1810 | for _, implement in pairs(self:getAttachedImplements()) do |
1811 | local vehicle = implement.object |
1812 | if vehicle ~= nil then |
1813 | if vehicle[functionName] ~= nil then |
1814 | vehicle[functionName](vehicle, ...) |
1815 | end |
1816 | end |
1817 | end |
1818 | end |
createAttachmentJoint
DescriptionCreate attacher joint between vehicle and implementDefinition
createAttachmentJoint(table implement, boolean noSmoothAttach)Arguments
table | implement | implement to attach |
boolean | noSmoothAttach | dont use smooth attach |
1218 | function AttacherJoints:createAttachmentJoint(implement, noSmoothAttach) |
1219 | |
1220 | local spec = self.spec_attacherJoints |
1221 | local jointDesc = spec.attacherJoints[implement.jointDescIndex] |
1222 | local objectAtttacherJoint = implement.object.spec_attachable.attacherJoint |
1223 | |
1224 | if self.isServer and objectAtttacherJoint ~= nil then |
1225 | if getRigidBodyType(jointDesc.rootNode) ~= "Dynamic" or getRigidBodyType(objectAtttacherJoint.rootNode) ~= "Dynamic" then |
1226 | return |
1227 | end |
1228 | |
1229 | local xNew = jointDesc.jointOrigTrans[1] + jointDesc.jointPositionOffset[1] |
1230 | local yNew = jointDesc.jointOrigTrans[2] + jointDesc.jointPositionOffset[2] |
1231 | local zNew = jointDesc.jointOrigTrans[3] + jointDesc.jointPositionOffset[3] |
1232 | |
1233 | -- transform offset position to world coord and to jointTransform coord to get position offset dependend on angle and position |
1234 | local x,y,z = localToWorld(getParent(jointDesc.jointTransform), xNew, yNew, zNew) |
1235 | local x1,y1,z1 = worldToLocal(jointDesc.jointTransform, x,y,z) |
1236 | |
1237 | -- move jointTransform to offset pos |
1238 | setTranslation(jointDesc.jointTransform, xNew, yNew, zNew) |
1239 | |
1240 | -- transform it to implement position and angle |
1241 | x,y,z = localToWorld(objectAtttacherJoint.node,x1,y1,z1) |
1242 | local x2,y2,z2 = worldToLocal(getParent(objectAtttacherJoint.node), x,y,z) |
1243 | setTranslation(objectAtttacherJoint.node, x2,y2, z2) |
1244 | |
1245 | |
1246 | local constr = JointConstructor:new() |
1247 | constr:setActors(jointDesc.rootNode, objectAtttacherJoint.rootNode) |
1248 | constr:setJointTransforms(jointDesc.jointTransform, objectAtttacherJoint.node) |
1249 | --constr:setBreakable(20, 10) |
1250 | |
1251 | implement.jointRotLimit = {} |
1252 | implement.jointTransLimit = {} |
1253 | |
1254 | implement.lowerRotLimit = {} |
1255 | implement.lowerTransLimit = {} |
1256 | |
1257 | implement.upperRotLimit = {} |
1258 | implement.upperTransLimit = {} |
1259 | |
1260 | if noSmoothAttach == nil or not noSmoothAttach then |
1261 | local dx,dy,dz = localToLocal(objectAtttacherJoint.node, jointDesc.jointTransform, 0,0,0) |
1262 | local _,y,z = localDirectionToLocal(objectAtttacherJoint.node, jointDesc.jointTransform, 0,1,0) |
1263 | local rX = math.atan2(z,y) |
1264 | local x,_,z = localDirectionToLocal(objectAtttacherJoint.node, jointDesc.jointTransform, 0,0,1) |
1265 | local rY = math.atan2(x,z) |
1266 | local x,y,_ = localDirectionToLocal(objectAtttacherJoint.node, jointDesc.jointTransform, 1,0,0) |
1267 | local rZ = math.atan2(y,x) |
1268 | implement.attachingTransLimit = { math.abs(dx), math.abs(dy), math.abs(dz) } |
1269 | implement.attachingRotLimit = { math.abs(rX), math.abs(rY), math.abs(rZ) } |
1270 | implement.attachingTransLimitSpeed = {} |
1271 | implement.attachingRotLimitSpeed = {} |
1272 | for i=1,3 do |
1273 | implement.attachingTransLimitSpeed[i] = implement.attachingTransLimit[i] / 500 |
1274 | implement.attachingRotLimitSpeed[i] = implement.attachingRotLimit[i] / 500 |
1275 | end |
1276 | implement.attachingIsInProgress = true |
1277 | else |
1278 | implement.attachingTransLimit = { 0,0,0 } |
1279 | implement.attachingRotLimit = { 0,0,0 } |
1280 | end |
1281 | |
1282 | for i=1, 3 do |
1283 | local lowerRotLimit = jointDesc.lowerRotLimit[i]*objectAtttacherJoint.lowerRotLimitScale[i] |
1284 | local upperRotLimit = jointDesc.upperRotLimit[i]*objectAtttacherJoint.upperRotLimitScale[i] |
1285 | if objectAtttacherJoint.fixedRotation then |
1286 | lowerRotLimit = 0 |
1287 | upperRotLimit = 0 |
1288 | end |
1289 | |
1290 | local upperTransLimit = jointDesc.lowerTransLimit[i]*objectAtttacherJoint.lowerTransLimitScale[i] |
1291 | local lowerTransLimit = jointDesc.upperTransLimit[i]*objectAtttacherJoint.upperTransLimitScale[i] |
1292 | implement.lowerRotLimit[i] = lowerRotLimit |
1293 | implement.upperRotLimit[i] = upperRotLimit |
1294 | |
1295 | implement.lowerTransLimit[i] = upperTransLimit |
1296 | implement.upperTransLimit[i] = lowerTransLimit |
1297 | |
1298 | if not jointDesc.allowsLowering then |
1299 | implement.upperRotLimit[i] = lowerRotLimit |
1300 | implement.upperTransLimit[i] = upperTransLimit |
1301 | end |
1302 | |
1303 | local rotLimit = lowerRotLimit |
1304 | local transLimit = upperTransLimit |
1305 | if jointDesc.allowsLowering and jointDesc.allowsJointLimitMovement then |
1306 | if objectAtttacherJoint.allowsJointRotLimitMovement then |
1307 | rotLimit = MathUtil.lerp(upperRotLimit, lowerRotLimit, jointDesc.moveAlpha) |
1308 | end |
1309 | if objectAtttacherJoint.allowsJointTransLimitMovement then |
1310 | transLimit = MathUtil.lerp(lowerTransLimit, upperTransLimit, jointDesc.moveAlpha) |
1311 | end |
1312 | end |
1313 | |
1314 | local limitRot = rotLimit |
1315 | local limitTrans = transLimit |
1316 | if noSmoothAttach == nil or not noSmoothAttach then |
1317 | limitRot = math.max(rotLimit, implement.attachingRotLimit[i]) |
1318 | limitTrans = math.max(transLimit, implement.attachingTransLimit[i]) |
1319 | end |
1320 | |
1321 | constr:setRotationLimit(i-1, -limitRot, limitRot) |
1322 | implement.jointRotLimit[i] = limitRot |
1323 | constr:setTranslationLimit(i-1, true, -limitTrans, limitTrans) |
1324 | implement.jointTransLimit[i] = limitTrans |
1325 | end |
1326 | |
1327 | if jointDesc.enableCollision then |
1328 | constr:setEnableCollision(true) |
1329 | else |
1330 | for _, component in pairs(self.components) do |
1331 | if component.node ~= jointDesc.rootNodeBackup and not component.collideWithAttachables then |
1332 | setPairCollision(component.node, objectAtttacherJoint.rootNode, false) |
1333 | end |
1334 | end |
1335 | end |
1336 | |
1337 | local springX = math.max(jointDesc.rotLimitSpring[1], objectAtttacherJoint.rotLimitSpring[1]) |
1338 | local springY = math.max(jointDesc.rotLimitSpring[2], objectAtttacherJoint.rotLimitSpring[2]) |
1339 | local springZ = math.max(jointDesc.rotLimitSpring[3], objectAtttacherJoint.rotLimitSpring[3]) |
1340 | local dampingX = math.max(jointDesc.rotLimitDamping[1], objectAtttacherJoint.rotLimitDamping[1]) |
1341 | local dampingY = math.max(jointDesc.rotLimitDamping[2], objectAtttacherJoint.rotLimitDamping[2]) |
1342 | local dampingZ = math.max(jointDesc.rotLimitDamping[3], objectAtttacherJoint.rotLimitDamping[3]) |
1343 | local forceLimitX = Utils.getMaxJointForceLimit(jointDesc.rotLimitForceLimit[1], objectAtttacherJoint.rotLimitForceLimit[1]) |
1344 | local forceLimitY = Utils.getMaxJointForceLimit(jointDesc.rotLimitForceLimit[2], objectAtttacherJoint.rotLimitForceLimit[2]) |
1345 | local forceLimitZ = Utils.getMaxJointForceLimit(jointDesc.rotLimitForceLimit[3], objectAtttacherJoint.rotLimitForceLimit[3]) |
1346 | constr:setRotationLimitSpring(springX, dampingX, springY, dampingY, springZ, dampingZ) |
1347 | constr:setRotationLimitForceLimit(forceLimitX, forceLimitY, forceLimitZ) |
1348 | |
1349 | local springX = math.max(jointDesc.transLimitSpring[1], objectAtttacherJoint.transLimitSpring[1]) |
1350 | local springY = math.max(jointDesc.transLimitSpring[2], objectAtttacherJoint.transLimitSpring[2]) |
1351 | local springZ = math.max(jointDesc.transLimitSpring[3], objectAtttacherJoint.transLimitSpring[3]) |
1352 | local dampingX = math.max(jointDesc.transLimitDamping[1], objectAtttacherJoint.transLimitDamping[1]) |
1353 | local dampingY = math.max(jointDesc.transLimitDamping[2], objectAtttacherJoint.transLimitDamping[2]) |
1354 | local dampingZ = math.max(jointDesc.transLimitDamping[3], objectAtttacherJoint.transLimitDamping[3]) |
1355 | local forceLimitX = Utils.getMaxJointForceLimit(jointDesc.transLimitForceLimit[1], objectAtttacherJoint.transLimitForceLimit[1]) |
1356 | local forceLimitY = Utils.getMaxJointForceLimit(jointDesc.transLimitForceLimit[2], objectAtttacherJoint.transLimitForceLimit[2]) |
1357 | local forceLimitZ = Utils.getMaxJointForceLimit(jointDesc.transLimitForceLimit[3], objectAtttacherJoint.transLimitForceLimit[3]) |
1358 | constr:setTranslationLimitSpring(springX, dampingX, springY, dampingY, springZ, dampingZ) |
1359 | constr:setTranslationLimitForceLimit(forceLimitX, forceLimitY, forceLimitZ) |
1360 | |
1361 | jointDesc.jointIndex = constr:finalize() |
1362 | |
1363 | -- restore implement attacher joint position (to ensure correct bottom arm alignment) |
1364 | setTranslation(objectAtttacherJoint.node, unpack(objectAtttacherJoint.jointOrigTrans)) |
1365 | else |
1366 | -- set joint index to '1' on client side, so we can check if something is attached |
1367 | jointDesc.jointIndex = 1 |
1368 | end |
1369 | end |
deactivateAttachments
DescriptionCall "deactivate" on all attachmentsDefinition
deactivateAttachments()Code
1834 | function AttacherJoints:deactivateAttachments() |
1835 | local spec = self.spec_attacherJoints |
1836 | |
1837 | for _,v in pairs(spec.attachedImplements) do |
1838 | if v.object ~= nil then |
1839 | v.object:deactivate() |
1840 | end |
1841 | end |
1842 | end |
deactivateAttachmentsLights
DescriptionCall "deactivateLights" on all attachmentsDefinition
deactivateAttachmentsLights()Code
1846 | function AttacherJoints:deactivateAttachmentsLights() |
1847 | local spec = self.spec_attacherJoints |
1848 | |
1849 | for _,v in pairs(spec.attachedImplements) do |
1850 | if v.object ~= nil and v.object.deactivateLights ~= nil then |
1851 | v.object:deactivateLights() |
1852 | end |
1853 | end |
1854 | end |
detachImplement
DescriptionDetach implementDefinition
detachImplement(integer implementIndex, boolean noEventSend)Arguments
integer | implementIndex | index of implement in self.attachedImplements |
boolean | noEventSend | no event send |
boolean | success | success |
1514 | function AttacherJoints:detachImplement(implementIndex, noEventSend) |
1515 | local spec = self.spec_attacherJoints |
1516 | |
1517 | if noEventSend == nil or noEventSend == false then |
1518 | if g_server ~= nil then |
1519 | g_server:broadcastEvent(VehicleDetachEvent:new(self, spec.attachedImplements[implementIndex].object), nil, nil, self) |
1520 | else |
1521 | -- Send detach request to server and return |
1522 | local implement = spec.attachedImplements[implementIndex] |
1523 | if implement.object ~= nil then |
1524 | g_client:getServerConnection():sendEvent(VehicleDetachEvent:new(self, implement.object)) |
1525 | end |
1526 | return |
1527 | end |
1528 | end |
1529 | |
1530 | local implement = spec.attachedImplements[implementIndex] |
1531 | |
1532 | SpecializationUtil.raiseEvent(self, "onPreDetachImplement", implement) |
1533 | implement.object:preDetach(self, implement) |
1534 | |
1535 | local jointDesc |
1536 | if implement.object ~= nil then |
1537 | jointDesc = spec.attacherJoints[implement.jointDescIndex] |
1538 | if jointDesc.transNode ~= nil then |
1539 | setTranslation(jointDesc.transNode, unpack(jointDesc.transNodeOrgTrans)) |
1540 | end |
1541 | if not implement.object.isHardAttached then |
1542 | if self.isServer then |
1543 | if jointDesc.jointIndex ~= 0 then |
1544 | removeJoint(jointDesc.jointIndex) |
1545 | end |
1546 | |
1547 | if not jointDesc.enableCollision then |
1548 | for _, component in pairs(self.components) do |
1549 | if component.node ~= jointDesc.rootNodeBackup and not component.collideWithAttachables then |
1550 | local attacherJoint = implement.object:getActiveInputAttacherJoint() |
1551 | setPairCollision(component.node, attacherJoint.rootNode, true) |
1552 | end |
1553 | end |
1554 | end |
1555 | end |
1556 | end |
1557 | jointDesc.jointIndex = 0 |
1558 | end |
1559 | |
1560 | ObjectChangeUtil.setObjectChanges(jointDesc.changeObjects, false, self, self.setMovingToolDirty) |
1561 | |
1562 | if implement.object ~= nil then |
1563 | local object = implement.object |
1564 | |
1565 | if object.isHardAttached then |
1566 | self:hardDetachImplement(implement) |
1567 | end |
1568 | |
1569 | if self.isClient then |
1570 | if jointDesc.topArm ~= nil then |
1571 | setRotation(jointDesc.topArm.rotationNode, jointDesc.topArm.rotX, jointDesc.topArm.rotY, jointDesc.topArm.rotZ) |
1572 | if jointDesc.topArm.translationNode ~= nil then |
1573 | setTranslation(jointDesc.topArm.translationNode, 0, 0, 0) |
1574 | end |
1575 | if jointDesc.topArm.scaleNode ~= nil then |
1576 | setScale(jointDesc.topArm.scaleNode, 1, 1, 1) |
1577 | end |
1578 | if jointDesc.topArm.toggleVisibility then |
1579 | setVisibility(jointDesc.topArm.rotationNode, false) |
1580 | end |
1581 | end |
1582 | if jointDesc.bottomArm ~= nil then |
1583 | setRotation(jointDesc.bottomArm.rotationNode, jointDesc.bottomArm.rotX, jointDesc.bottomArm.rotY, jointDesc.bottomArm.rotZ) |
1584 | if jointDesc.bottomArm.translationNode ~= nil then |
1585 | setTranslation(jointDesc.bottomArm.translationNode, 0, 0, 0) |
1586 | end |
1587 | if self.setMovingToolDirty ~= nil then |
1588 | self:setMovingToolDirty(jointDesc.bottomArm.rotationNode) |
1589 | end |
1590 | if jointDesc.bottomArm.toolbar ~= nil then |
1591 | setVisibility(jointDesc.bottomArm.toolbar, false) |
1592 | end |
1593 | if jointDesc.bottomArm.toggleVisibility then |
1594 | setVisibility(jointDesc.bottomArm.rotationNode, false) |
1595 | end |
1596 | end |
1597 | end |
1598 | -- restore original translation |
1599 | setTranslation(jointDesc.jointTransform, unpack(jointDesc.jointOrigTrans)) |
1600 | local attacherJoint = object:getActiveInputAttacherJoint() |
1601 | setTranslation(attacherJoint.node, unpack(attacherJoint.jointOrigTrans)) |
1602 | if jointDesc.rotationNode ~= nil then |
1603 | setRotation(jointDesc.rotationNode, jointDesc.rotX, jointDesc.rotY, jointDesc.rotZ) |
1604 | end |
1605 | |
1606 | SpecializationUtil.raiseEvent(self, "onPostDetachImplement", implementIndex) |
1607 | object:postDetach(implementIndex) |
1608 | end |
1609 | |
1610 | table.remove(spec.attachedImplements, implementIndex) |
1611 | |
1612 | self:playDetachSound(jointDesc) |
1613 | |
1614 | local data = {attacherVehicle=self, attachedVehicle=implement.object} |
1615 | implement.object:raiseStateChange(Vehicle.STATE_CHANGE_DETACH, data) |
1616 | local rootVehicle = self:getRootVehicle() |
1617 | rootVehicle:raiseStateChange(Vehicle.STATE_CHANGE_DETACH, data) |
1618 | |
1619 | self:getRootVehicle():updateSelectableObjects() |
1620 | self:getRootVehicle():setSelectedVehicle(self, nil, true) |
1621 | self:getRootVehicle():requestActionEventUpdate() -- do action event update independent of a successful selection (important since we cannot select every vehicle) |
1622 | implement.object:updateSelectableObjects() |
1623 | implement.object:setSelectedVehicle(implement.object, nil, true) |
1624 | implement.object:requestActionEventUpdate() -- do action event update independent of a successful selection (important since we cannot select every vehicle) |
1625 | |
1626 | return true |
1627 | end |
detachImplementByObject
DescriptionDetach implement by object of implementDefinition
detachImplementByObject(table object, boolean noEventSend)Arguments
table | object | object of implement to detach |
boolean | noEventSend | no event send |
boolean | success | success |
1634 | function AttacherJoints:detachImplementByObject(object, noEventSend) |
1635 | local spec = self.spec_attacherJoints |
1636 | |
1637 | for i,implement in ipairs(spec.attachedImplements) do |
1638 | if implement.object == object then |
1639 | self:detachImplement(i, noEventSend) |
1640 | break |
1641 | end |
1642 | end |
1643 | |
1644 | return true |
1645 | end |
detachingIsPossible
DescriptionReturns true if it is possible to detach selected implementDefinition
detachingIsPossible()Return Values
boolean | possibleToDetach | possible to detach selected implement |
1729 | function AttacherJoints:detachingIsPossible() |
1730 | local implement = self:getImplementByObject(self:getSelectedVehicle()) |
1731 | if implement ~= nil then |
1732 | local object = implement.object |
1733 | if object ~= nil and object.attacherVehicle ~= nil and object:isDetachAllowed() then |
1734 | local implementIndex = object.attacherVehicle:getImplementIndexByObject(object) |
1735 | if implementIndex ~= nil then |
1736 | return true |
1737 | end |
1738 | end |
1739 | end |
1740 | return false |
1741 | end |
findVehicleInAttachRange
DescriptionDefinitionfindVehicleInAttachRange()Code
2838 | function AttacherJoints.findVehicleInAttachRange(vehicle, maxDistanceSq, maxAngle) |
2839 | local spec = vehicle.spec_attacherJoints |
2840 | |
2841 | if spec ~= nil then |
2842 | local minDist = math.huge |
2843 | local minDistY = math.huge |
2844 | local attacherVehicle = nil |
2845 | local attacherVehicleJointDescIndex = nil |
2846 | local attachable = nil |
2847 | local attachableJointDescIndex = nil |
2848 | |
2849 | -- first, check if attached implements can attach something |
2850 | if vehicle.getAttachedImplements ~= nil then |
2851 | local implements = vehicle:getAttachedImplements() |
2852 | for _,implement in pairs(implements) do |
2853 | if implement.object ~= nil then |
2854 | attacherVehicle, attacherVehicleJointDescIndex, attachable, attachableJointDescIndex = AttacherJoints.findVehicleInAttachRange(implement.object, maxDistanceSq, maxAngle) |
2855 | if attacherVehicle ~= nil then |
2856 | return attacherVehicle, attacherVehicleJointDescIndex, attachable, attachableJointDescIndex |
2857 | end |
2858 | end |
2859 | end |
2860 | end |
2861 | |
2862 | -- now, check if the current vehicle can attach something |
2863 | for attacherJointIndex,attacherJoint in pairs(spec.attacherJoints) do |
2864 | if spec.attacherJoints[attacherJointIndex].jointIndex == 0 then |
2865 | |
2866 | for _,vehicle2 in pairs(g_currentMission.vehicles) do |
2867 | if vehicle2 ~= vehicle and vehicle2.getInputAttacherJoints ~= nil then |
2868 | |
2869 | if vehicle2:getActiveInputAttacherJointDescIndex() == nil then |
2870 | |
2871 | local inputAttacherJoints = vehicle2:getInputAttacherJoints() |
2872 | if inputAttacherJoints ~= nil then |
2873 | for inputAttacherJointIndex,inputAttacherJoint in pairs(inputAttacherJoints) do |
2874 | |
2875 | if vehicle2:getIsInputAttacherActive(inputAttacherJoint) and attacherJoint.jointType == inputAttacherJoint.jointType then |
2876 | local x,y,z = localToLocal(inputAttacherJoint.node, attacherJoint.jointTransform, 0,0,0) |
2877 | local distSq = MathUtil.vector2LengthSq(x,z) |
2878 | local distSqY = y*y |
2879 | |
2880 | -- we check x-z-distance plus an extra check in y (doubled distance) to better handle height differences |
2881 | if distSq < maxDistanceSq and distSq < minDist and distSqY < maxDistanceSq*2 and distSqY < minDistY then |
2882 | |
2883 | local dx,_,_ = localDirectionToLocal(inputAttacherJoint.node, attacherJoint.jointTransform, 1, 0, 0) |
2884 | if dx > maxAngle then |
2885 | minDist = distSq |
2886 | minDistY = distSqY |
2887 | attacherVehicle = vehicle |
2888 | attacherVehicleJointDescIndex = attacherJointIndex |
2889 | attachable = vehicle2 |
2890 | attachableJointDescIndex = inputAttacherJointIndex |
2891 | end |
2892 | |
2893 | end |
2894 | end |
2895 | end |
2896 | end |
2897 | end |
2898 | end |
2899 | end |
2900 | end |
2901 | end |
2902 | return attacherVehicle, attacherVehicleJointDescIndex, attachable, attachableJointDescIndex |
2903 | end |
2904 | |
2905 | return nil, nil, nil, nil |
2906 | end |
getAICollisionTriggers
DescriptionDefinitiongetAICollisionTriggers()Code
2442 | function AttacherJoints:getAICollisionTriggers(superFunc, collisionTriggers) |
2443 | local spec = self.spec_attacherJoints |
2444 | |
2445 | for _, implement in pairs(spec.attachedImplements) do |
2446 | local object = implement.object |
2447 | if object.getAIImplementCollisionTriggers ~= nil then |
2448 | object:getAIImplementCollisionTriggers(collisionTriggers) |
2449 | end |
2450 | |
2451 | if object.getAICollisionTriggers ~= nil then |
2452 | object:getAICollisionTriggers(collisionTriggers) |
2453 | end |
2454 | end |
2455 | |
2456 | return superFunc(self) |
2457 | end |
getAirConsumerUsage
DescriptionReturns air consumer usage of attached vehiclesDefinition
getAirConsumerUsage()Return Values
float | usage | air usage |
2390 | function AttacherJoints:getAirConsumerUsage(superFunc) |
2391 | local spec = self.spec_attacherJoints |
2392 | local usage = superFunc(self) |
2393 | |
2394 | for _, implement in pairs(spec.attachedImplements) do |
2395 | local object = implement.object |
2396 | if object.getAttachbleAirConsumerUsage ~= nil then |
2397 | usage = usage + object:getAttachbleAirConsumerUsage() |
2398 | end |
2399 | end |
2400 | |
2401 | return usage |
2402 | end |
getAttachedImplements
DescriptionDefinitiongetAttachedImplements()Code
785 | function AttacherJoints:getAttachedImplements() |
786 | return self.spec_attacherJoints.attachedImplements |
787 | end |
getAttacherJointByJointDescIndex
DescriptionDefinitiongetAttacherJointByJointDescIndex()Code
797 | function AttacherJoints:getAttacherJointByJointDescIndex(jointDescIndex) |
798 | return self.spec_attacherJoints.attacherJoints[jointDescIndex] |
799 | end |
getAttacherJointDescFromObject
DescriptionDefinitiongetAttacherJointDescFromObject()Code
825 | function AttacherJoints:getAttacherJointDescFromObject(object) |
826 | local spec = self.spec_attacherJoints |
827 | for _,attachedImplement in pairs(spec.attachedImplements) do |
828 | if attachedImplement.object == object then |
829 | return spec.attacherJoints[attachedImplement.jointDescIndex] |
830 | end |
831 | end |
832 | end |
getAttacherJointIndexFromImplementIndex
DescriptionDefinitiongetAttacherJointIndexFromImplementIndex()Code
836 | function AttacherJoints:getAttacherJointIndexFromImplementIndex(implementIndex) |
837 | local spec = self.spec_attacherJoints |
838 | local attachedImplement = spec.attachedImplements[implementIndex] |
839 | if attachedImplement ~= nil then |
840 | return attachedImplement.jointDescIndex |
841 | end |
842 | return nil |
843 | end |
getAttacherJointIndexFromObject
DescriptionDefinitiongetAttacherJointIndexFromObject()Code
814 | function AttacherJoints:getAttacherJointIndexFromObject(object) |
815 | local spec = self.spec_attacherJoints |
816 | for _,attachedImplement in pairs(spec.attachedImplements) do |
817 | if attachedImplement.object == object then |
818 | return attachedImplement.jointDescIndex |
819 | end |
820 | end |
821 | end |
getAttacherJoints
DescriptionDefinitiongetAttacherJoints()Code
791 | function AttacherJoints:getAttacherJoints() |
792 | return self.spec_attacherJoints.attacherJoints |
793 | end |
getCanToggleAttach
DescriptionDefinitiongetCanToggleAttach()Code
1670 | function AttacherJoints:getCanToggleAttach() |
1671 | return true |
1672 | end |
getChildVehicles
DescriptionInserts all child vehicles into the given tableDefinition
getChildVehicles(table vehicles)Arguments
table | vehicles | child vehicles table |
2377 | function AttacherJoints:getChildVehicles(superFunc, vehicles) |
2378 | local spec = self.spec_attacherJoints |
2379 | |
2380 | for _, implement in pairs(spec.attachedImplements) do |
2381 | implement.object:getChildVehicles(vehicles) |
2382 | end |
2383 | |
2384 | return superFunc(self, vehicles) |
2385 | end |
getDirectionSnapAngle
DescriptionDefinitiongetDirectionSnapAngle()Code
2426 | function AttacherJoints:getDirectionSnapAngle(superFunc) |
2427 | local spec = self.spec_attacherJoints |
2428 | local maxAngle = superFunc(self) |
2429 | |
2430 | for _, implement in pairs(spec.attachedImplements) do |
2431 | local object = implement.object |
2432 | if object.getDirectionSnapAngle ~= nil then |
2433 | maxAngle = math.max(maxAngle + object:getDirectionSnapAngle()) |
2434 | end |
2435 | end |
2436 | |
2437 | return maxAngle |
2438 | end |
getFillLevelInformation
DescriptionDefinitiongetFillLevelInformation()Code
2461 | function AttacherJoints:getFillLevelInformation(superFunc, fillLevelInformations) |
2462 | local spec = self.spec_attacherJoints |
2463 | |
2464 | superFunc(self, fillLevelInformations) |
2465 | |
2466 | for _, implement in pairs(spec.attachedImplements) do |
2467 | if implement.object ~= nil then |
2468 | implement.object:getFillLevelInformation(fillLevelInformations) |
2469 | end |
2470 | end |
2471 | end |
getImplementByJointDescIndex
DescriptionReturns implement by jointDescIndexDefinition
getImplementByJointDescIndex(integer jointDescIndex)Arguments
integer | jointDescIndex | joint desc index |
table | implement | implement |
1763 | function AttacherJoints:getImplementByJointDescIndex(jointDescIndex) |
1764 | local spec = self.spec_attacherJoints |
1765 | |
1766 | for i, implement in pairs(spec.attachedImplements) do |
1767 | if implement.jointDescIndex == jointDescIndex then |
1768 | return implement |
1769 | end |
1770 | end |
1771 | |
1772 | return nil |
1773 | end |
getImplementByObject
DescriptionReturns implement by objectDefinition
getImplementByObject(table object)Arguments
table | object | object of attached implement |
table | implement | implement |
1795 | function AttacherJoints:getImplementByObject(object) |
1796 | local spec = self.spec_attacherJoints |
1797 | |
1798 | for i, implement in pairs(spec.attachedImplements) do |
1799 | if implement.object == object then |
1800 | return implement |
1801 | end |
1802 | end |
1803 | |
1804 | return nil |
1805 | end |
getImplementFromAttacherJointIndex
DescriptionDefinitiongetImplementFromAttacherJointIndex()Code
803 | function AttacherJoints:getImplementFromAttacherJointIndex(attacherJointIndex) |
804 | local spec = self.spec_attacherJoints |
805 | for _,attachedImplement in pairs(spec.attachedImplements) do |
806 | if attachedImplement.jointDescIndex == attacherJointIndex then |
807 | return attachedImplement |
808 | end |
809 | end |
810 | end |
getImplementIndexByJointDescIndex
DescriptionReturns implement index in 'self.attachedImplements' by jointDescIndexDefinition
getImplementIndexByJointDescIndex(integer jointDescIndex)Arguments
integer | jointDescIndex | joint desc index |
integer | index | index of implement |
1747 | function AttacherJoints:getImplementIndexByJointDescIndex(jointDescIndex) |
1748 | local spec = self.spec_attacherJoints |
1749 | |
1750 | for i, implement in pairs(spec.attachedImplements) do |
1751 | if implement.jointDescIndex == jointDescIndex then |
1752 | return i |
1753 | end |
1754 | end |
1755 | |
1756 | return nil |
1757 | end |
getImplementIndexByObject
DescriptionReturns implement index in 'self.attachedImplements' by objectDefinition
getImplementIndexByObject(table object)Arguments
table | object | object of attached implement |
integer | index | index of implement |
1779 | function AttacherJoints:getImplementIndexByObject(object) |
1780 | local spec = self.spec_attacherJoints |
1781 | |
1782 | for i, implement in pairs(spec.attachedImplements) do |
1783 | if implement.object == object then |
1784 | return i |
1785 | end |
1786 | end |
1787 | |
1788 | return nil |
1789 | end |
getIsDashboardGroupActive
DescriptionDefinitiongetIsDashboardGroupActive()Code
2543 | function AttacherJoints:getIsDashboardGroupActive(superFunc, group) |
2544 | local hasAttachment = #group.attacherJointIndices == 0 |
2545 | for _, jointIndex in ipairs(group.attacherJointIndices) do |
2546 | if self:getImplementFromAttacherJointIndex(jointIndex) ~= nil then |
2547 | hasAttachment = true |
2548 | end |
2549 | end |
2550 | |
2551 | return superFunc(self, group) and hasAttachment |
2552 | end |
getIsFoldAllowed
DescriptionDefinitiongetIsFoldAllowed()Code
2583 | function AttacherJoints:getIsFoldAllowed(superFunc, direction, onAiTurnOn) |
2584 | local spec = self.spec_attacherJoints |
2585 | for attacherJointIndex, attacherJoint in ipairs(spec.attacherJoints) do |
2586 | if not attacherJoint.allowFoldingWhileAttached then |
2587 | if attacherJoint.jointIndex ~= 0 then |
2588 | return false |
2589 | end |
2590 | end |
2591 | end |
2592 | |
2593 | return superFunc(self, direction, onAiTurnOn) |
2594 | end |
getIsHardAttachAllowed
DescriptionReturns if attacher joint supports hard attachDefinition
getIsHardAttachAllowed(integer jointDescIndex)Arguments
integer | jointDescIndex | index of joint |
boolean | supportsHardAttach | attacher joint supports hard attach |
1884 | function AttacherJoints:getIsHardAttachAllowed(jointDescIndex) |
1885 | local spec = self.spec_attacherJoints |
1886 | |
1887 | return spec.attacherJoints[jointDescIndex].supportsHardAttach |
1888 | end |
getIsReadyForAutomatedTrainTravel
DescriptionDefinitiongetIsReadyForAutomatedTrainTravel()Code
2515 | function AttacherJoints:getIsReadyForAutomatedTrainTravel(superFunc) |
2516 | local spec = self.spec_attacherJoints |
2517 | for _,implement in pairs(spec.attachedImplements) do |
2518 | if implement.object ~= nil and implement.object.getIsReadyForAutomatedTrainTravel ~= nil then |
2519 | if not implement.object:getIsReadyForAutomatedTrainTravel() then |
2520 | return false |
2521 | end |
2522 | end |
2523 | end |
2524 | |
2525 | return superFunc(self) |
2526 | end |
getIsWheelFoliageDestructionAllowed
DescriptionReturns true if foliage destruction is allowedDefinition
getIsWheelFoliageDestructionAllowed()Return Values
boolean | isAllowed | tfoliage destruction is allowed |
2599 | function AttacherJoints:getIsWheelFoliageDestructionAllowed(superFunc, wheel) |
2600 | if not superFunc(self, wheel) then |
2601 | return false |
2602 | end |
2603 | |
2604 | local spec = self.spec_attacherJoints |
2605 | for _,implement in pairs(spec.attachedImplements) do |
2606 | local object = implement.object |
2607 | if object ~= nil then |
2608 | if object.getBlockFoliageDestruction ~= nil then |
2609 | if object:getBlockFoliageDestruction() then |
2610 | return false |
2611 | end |
2612 | end |
2613 | end |
2614 | end |
2615 | |
2616 | return true |
2617 | end |
getObjectFromImplementIndex
DescriptionDefinitiongetObjectFromImplementIndex()Code
847 | function AttacherJoints:getObjectFromImplementIndex(implementIndex) |
848 | local spec = self.spec_attacherJoints |
849 | local attachedImplement = spec.attachedImplements[implementIndex] |
850 | if attachedImplement ~= nil then |
851 | return attachedImplement.object |
852 | end |
853 | return nil |
854 | end |
getSelectedImplement
DescriptionDefinitiongetSelectedImplement()Code
1655 | function AttacherJoints:getSelectedImplement() |
1656 | local spec = self.spec_attacherJoints |
1657 | |
1658 | -- check if implement is still attached |
1659 | if spec.selectedImplement ~= nil then |
1660 | if spec.selectedImplement.object:getAttacherVehicle() ~= self then |
1661 | return nil |
1662 | end |
1663 | end |
1664 | |
1665 | return spec.selectedImplement |
1666 | end |
getTotalMass
DescriptionReturns total mass of vehicle (optional including attached vehicles)Definition
getTotalMass(boolean onlyGivenVehicle)Arguments
boolean | onlyGivenVehicle | use only the given vehicle, if false or nil it includes all attachables |
float | totalMass | total mass |
2360 | function AttacherJoints:getTotalMass(superFunc, onlyGivenVehicle) |
2361 | local spec = self.spec_attacherJoints |
2362 | local mass = superFunc(self) |
2363 | |
2364 | if onlyGivenVehicle == nil or not onlyGivenVehicle then |
2365 | for _, implement in pairs(spec.attachedImplements) do |
2366 | local object = implement.object |
2367 | mass = mass + object:getTotalMass(onlyGivenVehicle) |
2368 | end |
2369 | end |
2370 | |
2371 | return mass |
2372 | end |
handleLowerImplementByAttacherJointIndex
DescriptionDefinitionhandleLowerImplementByAttacherJointIndex()Code
762 | function AttacherJoints:handleLowerImplementByAttacherJointIndex(attacherJointIndex, direction) |
763 | if attacherJointIndex ~= nil then |
764 | local implement = self:getImplementByJointDescIndex(attacherJointIndex) |
765 | if implement ~= nil then |
766 | local object = implement.object |
767 | local attacherJoints = self:getAttacherJoints() |
768 | local attacherJoint = attacherJoints[attacherJointIndex] |
769 | |
770 | local allowsLowering, warning = object:getAllowsLowering() |
771 | if allowsLowering and attacherJoint.allowsLowering then |
772 | if direction == nil then |
773 | direction = not attacherJoint.moveDown |
774 | end |
775 | self:setJointMoveDown(implement.jointDescIndex, direction, false) |
776 | elseif not allowsLowering and warning ~= nil then |
777 | g_currentMission:showBlinkingWarning(warning, 2000) |
778 | end |
779 | end |
780 | end |
781 | end |
handleLowerImplementEvent
DescriptionDefinitionhandleLowerImplementEvent()Code
744 | function AttacherJoints:handleLowerImplementEvent() |
745 | local implement = self:getImplementByObject(self:getSelectedVehicle()) |
746 | if implement ~= nil then |
747 | local object = implement.object |
748 | if object ~= nil and object.getAttacherVehicle ~= nil then |
749 | |
750 | local attacherVehicle = object:getAttacherVehicle() |
751 | if attacherVehicle ~= nil then |
752 | |
753 | local attacherJointIndex = attacherVehicle:getAttacherJointIndexFromObject(object) |
754 | attacherVehicle:handleLowerImplementByAttacherJointIndex(attacherJointIndex) |
755 | end |
756 | end |
757 | end |
758 | end |
hardAttachImplement
DescriptionHard attach implementDefinition
hardAttachImplement(table implement)Arguments
table | implement | implement to attach |
1374 | function AttacherJoints:hardAttachImplement(implement) |
1375 | local spec = self.spec_attacherJoints |
1376 | |
1377 | local implements = {} |
1378 | local attachedImplements |
1379 | if implement.object.getAttachedImplements ~= nil then |
1380 | attachedImplements = implement.object:getAttachedImplements() |
1381 | end |
1382 | if attachedImplements ~= nil then |
1383 | for i = table.getn(attachedImplements), 1, -1 do |
1384 | local impl = attachedImplements[i] |
1385 | local object = impl.object |
1386 | local jointDescIndex = impl.jointDescIndex |
1387 | local jointDesc = implement.object.spec_attacherJoints.attacherJoints[jointDescIndex] |
1388 | local inputJointDescIndex = object.spec_attachable.inputAttacherJointDescIndex |
1389 | local moveDown = jointDesc.moveDown |
1390 | table.insert(implements, 1, {object=object, implementIndex=i, jointDescIndex=jointDescIndex, inputJointDescIndex=inputJointDescIndex, moveDown=moveDown}) |
1391 | implement.object:detachImplement(1, true) |
1392 | end |
1393 | end |
1394 | |
1395 | local attacherJoint = spec.attacherJoints[implement.jointDescIndex] |
1396 | local implementJoint = implement.object.spec_attachable.attacherJoint |
1397 | |
1398 | local baseVehicleComponentNode = self:getParentComponent(attacherJoint.jointTransform) |
1399 | local attachedVehicleComponentNode = implement.object:getParentComponent(implement.object.spec_attachable.attacherJoint.node) |
1400 | |
1401 | -- remove all components from physics |
1402 | local currentVehicle = self |
1403 | while currentVehicle ~= nil do |
1404 | currentVehicle:removeFromPhysics() |
1405 | currentVehicle = currentVehicle.attacherVehicle |
1406 | end |
1407 | implement.object:removeFromPhysics() |
1408 | |
1409 | -- set valid baseVehicle compound |
1410 | if spec.attacherVehicle == nil then |
1411 | setIsCompound(baseVehicleComponentNode, true) |
1412 | end |
1413 | -- set attachedVehicle to compound child |
1414 | setIsCompoundChild(attachedVehicleComponentNode, true) |
1415 | |
1416 | -- set direction and local position |
1417 | local dirX, dirY, dirZ = localDirectionToLocal(attachedVehicleComponentNode, implementJoint.node, 0, 0, 1) |
1418 | local upX, upY, upZ = localDirectionToLocal(attachedVehicleComponentNode, implementJoint.node, 0, 1, 0) |
1419 | setDirection(attachedVehicleComponentNode, dirX, dirY, dirZ, upX, upY, upZ) |
1420 | local x,y,z = localToLocal(attachedVehicleComponentNode, implementJoint.node, 0, 0, 0) |
1421 | setTranslation(attachedVehicleComponentNode, x, y, z) |
1422 | link(attacherJoint.jointTransform, attachedVehicleComponentNode) |
1423 | |
1424 | -- link visual and set to correct position |
1425 | if implementJoint.visualNode ~= nil and attacherJoint.jointTransformVisual ~= nil then |
1426 | local dirX, dirY, dirZ = localDirectionToLocal(implementJoint.visualNode, implementJoint.node, 0, 0, 1) |
1427 | local upX, upY, upZ = localDirectionToLocal(implementJoint.visualNode, implementJoint.node, 0, 1, 0) |
1428 | setDirection(implementJoint.visualNode, dirX, dirY, dirZ, upX, upY, upZ) |
1429 | local x,y,z = localToLocal(implementJoint.visualNode, implementJoint.node, 0, 0, 0) |
1430 | setTranslation(implementJoint.visualNode, x, y, z) |
1431 | link(attacherJoint.jointTransformVisual, implementJoint.visualNode) |
1432 | end |
1433 | |
1434 | implement.object.isHardAttached = true |
1435 | |
1436 | -- add to physics again |
1437 | local currentVehicle = self |
1438 | while currentVehicle ~= nil do |
1439 | currentVehicle:addToPhysics() |
1440 | currentVehicle = currentVehicle.attacherVehicle |
1441 | end |
1442 | |
1443 | -- set new joint rootNodes |
1444 | for _, attacherJoint in pairs(implement.object.spec_attacherJoints.attacherJoints) do |
1445 | attacherJoint.rootNode = self.rootNode |
1446 | end |
1447 | |
1448 | for _, impl in pairs(implements) do |
1449 | implement.object:attachImplement(impl.object, impl.inputJointDescIndex, impl.jointDescIndex, true, impl.implementIndex, impl.moveDown, true) |
1450 | end |
1451 | |
1452 | if self.isServer then |
1453 | self:raiseDirtyFlags(self.vehicleDirtyFlag) |
1454 | end |
1455 | |
1456 | return true |
1457 | end |
hardDetachImplement
DescriptionHard detach implementDefinition
hardDetachImplement(table implement)Arguments
table | implement | implement to detach |
1462 | function AttacherJoints:hardDetachImplement(implement) |
1463 | -- restore original joint rootNode |
1464 | for _, attacherJoint in pairs(implement.object.spec_attacherJoints.attacherJoints) do |
1465 | attacherJoint.rootNode = attacherJoint.rootNodeBackup |
1466 | end |
1467 | |
1468 | local implementJoint = implement.object.spec_attachable.attacherJoint |
1469 | |
1470 | local attachedVehicleComponentNode = implement.object:getParentComponent(implementJoint.node) |
1471 | |
1472 | local currentVehicle = self |
1473 | while currentVehicle ~= nil do |
1474 | currentVehicle:removeFromPhysics() |
1475 | currentVehicle = currentVehicle.attacherVehicle |
1476 | end |
1477 | --implement.object:removeFromPhysics() |
1478 | |
1479 | setIsCompound(attachedVehicleComponentNode, true) |
1480 | |
1481 | local x,y,z = getWorldTranslation(attachedVehicleComponentNode) |
1482 | setTranslation(attachedVehicleComponentNode, x,y,z) |
1483 | local dirX, dirY, dirZ = localDirectionToWorld(implement.object.rootNode, 0, 0, 1) |
1484 | local upX, upY, upZ = localDirectionToWorld(implement.object.rootNode, 0, 1, 0) |
1485 | setDirection(attachedVehicleComponentNode, dirX, dirY, dirZ, upX, upY, upZ) |
1486 | link(getRootNode(), attachedVehicleComponentNode) |
1487 | |
1488 | if implementJoint.visualNode ~= nil and getParent(implementJoint.visualNode) ~= implementJoint.visualNodeData.parent then |
1489 | link(implementJoint.visualNodeData.parent, implementJoint.visualNode, implementJoint.visualNodeData.index) |
1490 | setRotation(implementJoint.visualNode, implementJoint.visualNodeData.rotation[1], implementJoint.visualNodeData.rotation[2], implementJoint.visualNodeData.rotation[3]) |
1491 | setTranslation(implementJoint.visualNode, implementJoint.visualNodeData.translation[1], implementJoint.visualNodeData.translation[2], implementJoint.visualNodeData.translation[3]) |
1492 | end |
1493 | |
1494 | local currentVehicle = self |
1495 | while currentVehicle ~= nil do |
1496 | currentVehicle:addToPhysics() |
1497 | currentVehicle = currentVehicle.attacherVehicle |
1498 | end |
1499 | implement.object:addToPhysics() |
1500 | implement.object.isHardAttached = false |
1501 | |
1502 | if self.isServer then |
1503 | self:raiseDirtyFlags(self.vehicleDirtyFlag) |
1504 | end |
1505 | |
1506 | return true |
1507 | end |
initSpecialization
DescriptionDefinitioninitSpecialization()Code
21 | function AttacherJoints.initSpecialization() |
22 | g_configurationManager:addConfigurationType("attacherJoint", g_i18n:getText("configuration_attacherJoint"), "attacherJoints", nil, nil, nil, ConfigurationUtil.SELECTOR_MULTIOPTION) |
23 | |
24 | Vehicle.registerStateChange("ATTACH") |
25 | Vehicle.registerStateChange("DETACH") |
26 | Vehicle.registerStateChange("LOWER_ALL_IMPLEMENTS") |
27 | end |
isDetachAllowed
DescriptionReturns true if detach is allowedDefinition
isDetachAllowed()Return Values
boolean | detachAllowed | detach is allowed |
2557 | function AttacherJoints:isDetachAllowed(superFunc) |
2558 | local detachAllowed, warning, showWarning = superFunc(self) |
2559 | if not detachAllowed then |
2560 | return detachAllowed, warning, showWarning |
2561 | end |
2562 | |
2563 | local spec = self.spec_attacherJoints |
2564 | for attacherJointIndex, attacherJoint in ipairs(spec.attacherJoints) do |
2565 | if not attacherJoint.allowDetachingWhileLifted then |
2566 | if not attacherJoint.moveDown then |
2567 | local implement = self:getImplementByJointDescIndex(attacherJointIndex) |
2568 | if implement ~= nil then |
2569 | local inputAttacherJoint = implement.object:getInputAttacherJointByJointDescIndex(implement.inputJointDescIndex) |
2570 | if inputAttacherJoint ~= nil and not inputAttacherJoint.forceAllowDetachWhileLifted then |
2571 | return false, string.format(g_i18n:getText("warning_lowerImplementFirst"), implement.object.typeDesc) |
2572 | end |
2573 | end |
2574 | end |
2575 | end |
2576 | end |
2577 | |
2578 | return true |
2579 | end |
loadAttacherJointFromXML
DescriptionLoad attacher joint from xmlDefinition
loadAttacherJointFromXML(table attacherJoint, integer fileId, string baseName, integer index)Arguments
table | attacherJoint | attacherJoint |
integer | fileId | xml file id |
string | baseName | baseName |
integer | index | index of attacher joint |
1896 | function AttacherJoints:loadAttacherJointFromXML(attacherJoint, xmlFile, baseName, index) |
1897 | local spec = self.spec_attacherJoints |
1898 | |
1899 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#index", baseName .. "#node") -- FS17 |
1900 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#indexVisual", baseName .. "#nodeVisual") -- FS17 |
1901 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#ptoOutputNode", "vehicle.powerTakeOffs.output") -- FS17 to FS19 |
1902 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#lowerDistanceToGround", baseName..".distanceToGround#lower") -- FS17 to FS19 |
1903 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#upperDistanceToGround", baseName..".distanceToGround#upper") -- FS17 to FS19 |
1904 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#rotationNode", baseName..".rotationNode#node") -- FS17 to FS19 |
1905 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#upperRotation", baseName..".rotationNode#upperRotation") -- FS17 to FS19 |
1906 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#lowerRotation", baseName..".rotationNode#lowerRotation") -- FS17 to FS19 |
1907 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#startRotation", baseName..".rotationNode#startRotation") -- FS17 to FS19 |
1908 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#rotationNode2", baseName..".rotationNode2#node") -- FS17 to FS19 |
1909 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#upperRotation2", baseName..".rotationNode2#upperRotation") -- FS17 to FS19 |
1910 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#lowerRotation2", baseName..".rotationNode2#lowerRotation") -- FS17 to FS19 |
1911 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#transNode", baseName..".transNode#node") -- FS17 to FS19 |
1912 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#transNodeMinY", baseName..".transNode#minY") -- FS17 to FS19 |
1913 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#transNodeMaxY", baseName..".transNode#maxY") -- FS17 to FS19 |
1914 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.configFileName, baseName .. "#transNodeHeight", baseName..".transNode#height") -- FS17 to FS19 |
1915 | |
1916 | |
1917 | local node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. "#node"), self.i3dMappings) |
1918 | if node == nil then |
1919 | g_logManager:xmlWarning(self.configFileName, "Missing node for attacherJoint '%s'", baseName) |
1920 | return false |
1921 | end |
1922 | |
1923 | attacherJoint.jointTransform = node |
1924 | |
1925 | attacherJoint.jointTransformVisual = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName .. "#nodeVisual"), self.i3dMappings) |
1926 | attacherJoint.supportsHardAttach = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#supportsHardAttach"), true) |
1927 | |
1928 | local jointTypeStr = getXMLString(xmlFile, baseName.. "#jointType") |
1929 | local jointType |
1930 | if jointTypeStr ~= nil then |
1931 | jointType = AttacherJoints.jointTypeNameToInt[jointTypeStr] |
1932 | if jointType == nil then |
1933 | g_logManager:xmlWarning(self.configFileName, "Invalid jointType '%s' for attacherJoint '%s'!", tostring(jointTypeStr), baseName) |
1934 | end |
1935 | end |
1936 | if jointType == nil then |
1937 | jointType = AttacherJoints.JOINTTYPE_IMPLEMENT |
1938 | end |
1939 | attacherJoint.jointType = jointType |
1940 | attacherJoint.allowsJointLimitMovement = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#allowsJointLimitMovement"), true) |
1941 | attacherJoint.allowsLowering = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#allowsLowering"), true) |
1942 | attacherJoint.isDefaultLowered = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#isDefaultLowered"), false) |
1943 | |
1944 | attacherJoint.allowDetachingWhileLifted = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#allowDetachingWhileLifted"), true) |
1945 | attacherJoint.allowFoldingWhileAttached = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#allowFoldingWhileAttached"), true) |
1946 | |
1947 | if jointType == AttacherJoints.JOINTTYPE_TRAILER or jointType == AttacherJoints.JOINTTYPE_TRAILERLOW then |
1948 | attacherJoint.allowsLowering = false |
1949 | end |
1950 | |
1951 | attacherJoint.canTurnOnImplement = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#canTurnOnImplement"), true) |
1952 | |
1953 | local rotationNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".rotationNode#node"), self.i3dMappings) |
1954 | if rotationNode ~= nil then |
1955 | attacherJoint.rotationNode = rotationNode |
1956 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName..".rotationNode#lowerRotation")) |
1957 | attacherJoint.lowerRotation = { math.rad(Utils.getNoNil(x, 0)), math.rad(Utils.getNoNil(y, 0)), math.rad(Utils.getNoNil(z, 0)) } |
1958 | |
1959 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName..".rotationNode#upperRotation")) |
1960 | local rx,ry,rz = getRotation(rotationNode) |
1961 | attacherJoint.upperRotation = { Utils.getNoNilRad(x, rx), Utils.getNoNilRad(y, ry), Utils.getNoNilRad(z, rz) } |
1962 | |
1963 | local startRot = StringUtil.getRadiansFromString(getXMLString(xmlFile, baseName..".rotationNode#startRotation"), 3) |
1964 | if startRot ~= nil then |
1965 | attacherJoint.rotX, attacherJoint.rotY, attacherJoint.rotZ = startRot[1],startRot[2],startRot[3] |
1966 | else |
1967 | attacherJoint.rotX, attacherJoint.rotY, attacherJoint.rotZ = getRotation(rotationNode) |
1968 | end |
1969 | |
1970 | local lowerValues = {attacherJoint.lowerRotation[1], attacherJoint.lowerRotation[2], attacherJoint.lowerRotation[3]} |
1971 | local upperValues = {attacherJoint.upperRotation[1], attacherJoint.upperRotation[2], attacherJoint.upperRotation[3]} |
1972 | |
1973 | for i=1, 3 do |
1974 | local l = lowerValues[i] |
1975 | local u = upperValues[i] |
1976 | |
1977 | if l > u then |
1978 | upperValues[i] = l |
1979 | lowerValues[i] = u |
1980 | end |
1981 | end |
1982 | |
1983 | attacherJoint.rotX = MathUtil.clamp(attacherJoint.rotX, lowerValues[1], upperValues[1]) |
1984 | attacherJoint.rotY = MathUtil.clamp(attacherJoint.rotY, lowerValues[2], upperValues[2]) |
1985 | attacherJoint.rotZ = MathUtil.clamp(attacherJoint.rotZ, lowerValues[3], upperValues[3]) |
1986 | end |
1987 | local rotationNode2 = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".rotationNode2#node"), self.i3dMappings) |
1988 | if rotationNode2 ~= nil then |
1989 | attacherJoint.rotationNode2 = rotationNode2 |
1990 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName..".rotationNode2#lowerRotation")) |
1991 | if x ~= nil and y ~= nil and z ~= nil then |
1992 | attacherJoint.lowerRotation2 = { math.rad(Utils.getNoNil(x, 0)), math.rad(Utils.getNoNil(y, 0)), math.rad(Utils.getNoNil(z, 0)) } |
1993 | else |
1994 | attacherJoint.lowerRotation2 = { -attacherJoint.lowerRotation[1], -attacherJoint.lowerRotation[2], -attacherJoint.lowerRotation[3] } |
1995 | end |
1996 | |
1997 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName..".rotationNode2#upperRotation")) |
1998 | if x ~= nil and y ~= nil and z ~= nil then |
1999 | attacherJoint.upperRotation2 = { math.rad(Utils.getNoNil(x, 0)), math.rad(Utils.getNoNil(y, 0)), math.rad(Utils.getNoNil(z, 0)) } |
2000 | else |
2001 | attacherJoint.upperRotation2 = { -attacherJoint.upperRotation[1], -attacherJoint.upperRotation[2], -attacherJoint.upperRotation[3] } |
2002 | end |
2003 | end |
2004 | |
2005 | attacherJoint.transNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName..".transNode#node"), self.i3dMappings) |
2006 | if attacherJoint.transNode ~= nil then |
2007 | attacherJoint.transNodeOrgTrans = {getTranslation(attacherJoint.transNode)} |
2008 | attacherJoint.transNodeHeight = Utils.getNoNil(getXMLFloat(xmlFile, baseName..".transNode#height"), 0.12) |
2009 | attacherJoint.transNodeMinY = getXMLFloat(xmlFile, baseName..".transNode#minY") |
2010 | attacherJoint.transNodeMaxY = getXMLFloat(xmlFile, baseName..".transNode#maxY") |
2011 | end |
2012 | |
2013 | -- lowerDistanceToGround is a mandatory attribute if a rotationNode is available |
2014 | if (attacherJoint.rotationNode ~= nil or attacherJoint.transNode ~= nil) and getXMLFloat(xmlFile, baseName..".distanceToGround#lower") == nil then |
2015 | g_logManager:xmlWarning(self.configFileName, "Missing '.distanceToGround#lower' for attacherJoint '%s'. Use console command 'gsVehicleAnalyze' to get correct values!", baseName) |
2016 | end |
2017 | attacherJoint.lowerDistanceToGround = Utils.getNoNil(getXMLFloat(xmlFile, baseName..".distanceToGround#lower"), 0.7) |
2018 | |
2019 | -- upperDistanceToGround is a mandatory attribute if a rotationNode is available |
2020 | if (attacherJoint.rotationNode ~= nil or attacherJoint.transNode ~= nil) and getXMLFloat(xmlFile, baseName..".distanceToGround#upper") == nil then |
2021 | g_logManager:xmlWarning(self.configFileName, "Missing '.distanceToGround#upper' for attacherJoint '%s'. Use console command 'gsVehicleAnalyze' to get correct values!", baseName) |
2022 | end |
2023 | attacherJoint.upperDistanceToGround = Utils.getNoNil(getXMLFloat(xmlFile, baseName..".distanceToGround#upper"), 1.0) |
2024 | |
2025 | if attacherJoint.lowerDistanceToGround > attacherJoint.upperDistanceToGround then |
2026 | g_logManager:xmlWarning(self.configFileName, "distanceToGround#lower may not be larger than distanceToGround#upper for attacherJoint '%s'. Switching values!", baseName) |
2027 | local copy = attacherJoint.lowerDistanceToGround |
2028 | attacherJoint.lowerDistanceToGround = attacherJoint.upperDistanceToGround |
2029 | attacherJoint.upperDistanceToGround = copy |
2030 | end |
2031 | |
2032 | attacherJoint.lowerRotationOffset = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, baseName.."#lowerRotationOffset"), 0)) |
2033 | attacherJoint.upperRotationOffset = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, baseName.."#upperRotationOffset"), 0)) |
2034 | |
2035 | attacherJoint.lockDownRotLimit = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#lockDownRotLimit"), false) |
2036 | attacherJoint.lockUpRotLimit = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#lockUpRotLimit"), false) |
2037 | -- only use translimit in +y. Set -y to 0 |
2038 | attacherJoint.lockDownTransLimit = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#lockDownTransLimit"), true) |
2039 | attacherJoint.lockUpTransLimit = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#lockUpTransLimit"), false) |
2040 | |
2041 | local lowerRotLimitStr = "20 20 20" |
2042 | if jointType ~= AttacherJoints.JOINTTYPE_IMPLEMENT then |
2043 | lowerRotLimitStr = "0 0 0" |
2044 | end |
2045 | local lx, ly, lz = StringUtil.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, baseName.."#lowerRotLimit"), lowerRotLimitStr)) |
2046 | attacherJoint.lowerRotLimit = {} |
2047 | attacherJoint.lowerRotLimit[1] = math.rad(math.abs(Utils.getNoNil(lx, 20))) |
2048 | attacherJoint.lowerRotLimit[2] = math.rad(math.abs(Utils.getNoNil(ly, 20))) |
2049 | attacherJoint.lowerRotLimit[3] = math.rad(math.abs(Utils.getNoNil(lz, 20))) |
2050 | local ux, uy, uz = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#upperRotLimit")) |
2051 | attacherJoint.upperRotLimit = {} |
2052 | attacherJoint.upperRotLimit[1] = math.rad(math.abs(Utils.getNoNil(Utils.getNoNil(ux, lx), 20))) |
2053 | attacherJoint.upperRotLimit[2] = math.rad(math.abs(Utils.getNoNil(Utils.getNoNil(uy, ly), 20))) |
2054 | attacherJoint.upperRotLimit[3] = math.rad(math.abs(Utils.getNoNil(Utils.getNoNil(uz, lz), 20))) |
2055 | |
2056 | local lowerTransLimitStr = "0.5 0.5 0.5" |
2057 | if jointType ~= AttacherJoints.JOINTTYPE_IMPLEMENT then |
2058 | lowerTransLimitStr = "0 0 0" |
2059 | end |
2060 | local lx, ly, lz = StringUtil.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, baseName.."#lowerTransLimit"), lowerTransLimitStr)) |
2061 | attacherJoint.lowerTransLimit = {} |
2062 | attacherJoint.lowerTransLimit[1] = math.abs(Utils.getNoNil(lx, 0)) |
2063 | attacherJoint.lowerTransLimit[2] = math.abs(Utils.getNoNil(ly, 0)) |
2064 | attacherJoint.lowerTransLimit[3] = math.abs(Utils.getNoNil(lz, 0)) |
2065 | local ux, uy, uz = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#upperTransLimit")) |
2066 | attacherJoint.upperTransLimit = {} |
2067 | attacherJoint.upperTransLimit[1] = math.abs(Utils.getNoNil(Utils.getNoNil(ux, lx), 0)) |
2068 | attacherJoint.upperTransLimit[2] = math.abs(Utils.getNoNil(Utils.getNoNil(uy, ly), 0)) |
2069 | attacherJoint.upperTransLimit[3] = math.abs(Utils.getNoNil(Utils.getNoNil(uz, lz), 0)) |
2070 | |
2071 | |
2072 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#jointPositionOffset")) |
2073 | attacherJoint.jointPositionOffset = {} |
2074 | attacherJoint.jointPositionOffset[1] = Utils.getNoNil(x, 0) |
2075 | attacherJoint.jointPositionOffset[2] = Utils.getNoNil(y, 0) |
2076 | attacherJoint.jointPositionOffset[3] = Utils.getNoNil(z, 0) |
2077 | |
2078 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#rotLimitSpring")) |
2079 | attacherJoint.rotLimitSpring = { Utils.getNoNil(x, 0), Utils.getNoNil(y, 0), Utils.getNoNil(z, 0) } |
2080 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#rotLimitDamping")) |
2081 | attacherJoint.rotLimitDamping = { Utils.getNoNil(x, 1), Utils.getNoNil(y, 1), Utils.getNoNil(z, 1) } |
2082 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#rotLimitForceLimit")) |
2083 | attacherJoint.rotLimitForceLimit = { Utils.getNoNil(x, -1), Utils.getNoNil(y, -1), Utils.getNoNil(z, -1) } |
2084 | |
2085 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#transLimitSpring")) |
2086 | attacherJoint.transLimitSpring = { Utils.getNoNil(x, 0), Utils.getNoNil(y, 0), Utils.getNoNil(z, 0) } |
2087 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#transLimitDamping")) |
2088 | attacherJoint.transLimitDamping = { Utils.getNoNil(x, 1), Utils.getNoNil(y, 1), Utils.getNoNil(z, 1) } |
2089 | local x, y, z = StringUtil.getVectorFromString(getXMLString(xmlFile, baseName.."#transLimitForceLimit")) |
2090 | attacherJoint.transLimitForceLimit = { Utils.getNoNil(x, -1), Utils.getNoNil(y, -1), Utils.getNoNil(z, -1) } |
2091 | |
2092 | attacherJoint.moveDefaultTime = Utils.getNoNil(getXMLFloat(xmlFile, baseName.."#moveTime"), 0.5)*1000 |
2093 | attacherJoint.moveTime = attacherJoint.moveDefaultTime |
2094 | |
2095 | attacherJoint.enableCollision = Utils.getNoNil(getXMLBool(xmlFile, baseName.."#enableCollision"), false) |
2096 | |
2097 | local topArmFilename = getXMLString(xmlFile, baseName.. ".topArm#filename") |
2098 | if topArmFilename ~= nil then |
2099 | local baseNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".topArm#baseNode"), self.i3dMappings) |
2100 | if baseNode ~= nil then |
2101 | local i3dNode = g_i3DManager:loadSharedI3DFile(topArmFilename,self.baseDirectory, false, false, false) |
2102 | if i3dNode ~= 0 then |
2103 | local rootNode = getChildAt(i3dNode, 0) |
2104 | link(baseNode, rootNode) |
2105 | delete(i3dNode) |
2106 | setTranslation(rootNode, 0,0,0) |
2107 | local translationNode = getChildAt(rootNode, 0) |
2108 | local referenceNode = getChildAt(translationNode, 0) |
2109 | |
2110 | |
2111 | local topArm = {} |
2112 | topArm.rotationNode = rootNode |
2113 | topArm.rotX, topArm.rotY, topArm.rotZ = 0,0,0 |
2114 | topArm.translationNode = translationNode |
2115 | |
2116 | local _,_,referenceDistance = getTranslation(referenceNode) |
2117 | topArm.referenceDistance = referenceDistance |
2118 | |
2119 | topArm.zScale = 1 |
2120 | local zScale = MathUtil.sign(Utils.getNoNil(getXMLFloat(xmlFile, baseName.. ".topArm#zScale"), 1)) |
2121 | if zScale < 0 then |
2122 | topArm.rotY = math.pi |
2123 | setRotation(rootNode, topArm.rotX, topArm.rotY, topArm.rotZ) |
2124 | end |
2125 | |
2126 | if getNumOfChildren(rootNode) > 1 then |
2127 | topArm.scaleNode = getChildAt(rootNode, 1) |
2128 | local scaleReferenceNode = getChildAt(topArm.scaleNode, 0) |
2129 | local _,_,scaleReferenceDistance = getTranslation(scaleReferenceNode) |
2130 | topArm.scaleReferenceDistance = scaleReferenceDistance |
2131 | end |
2132 | |
2133 | topArm.toggleVisibility = Utils.getNoNil(getXMLBool(xmlFile, baseName.. ".topArm#toggleVisibility"), false) |
2134 | if topArm.toggleVisibility then |
2135 | setVisibility(topArm.rotationNode, false) |
2136 | end |
2137 | |
2138 | local colorValueStr = getXMLString(xmlFile, baseName..".topArm#color") |
2139 | local colorValue = g_brandColorManager:getBrandColorByName(colorValueStr) |
2140 | if colorValue == nil then |
2141 | colorValue = StringUtil.getVectorNFromString(colorValueStr, 3) |
2142 | end |
2143 | |
2144 | local colorValue2Str = getXMLString(xmlFile, baseName..".topArm#color2") |
2145 | local colorValue2 = g_brandColorManager:getBrandColorByName(colorValue2Str) |
2146 | if colorValue2 == nil then |
2147 | colorValue2 = StringUtil.getVectorNFromString(colorValue2Str, 3) |
2148 | end |
2149 | |
2150 | local decalColorStr = getXMLString(xmlFile, baseName..".topArm#decalColor") |
2151 | local decalColor = g_brandColorManager:getBrandColorByName(decalColorStr) |
2152 | if decalColor == nil then |
2153 | decalColor = StringUtil.getVectorNFromString(decalColorStr, 3) |
2154 | end |
2155 | |
2156 | -- on dark colors we use a white decal and on bright colors a black decal |
2157 | if decalColor == nil and colorValue ~= nil then |
2158 | local brightness = MathUtil.getBrightnessFromColor(colorValue[1], colorValue[2], colorValue[3]) |
2159 | brightness = (brightness > 0.075 and 1) or 0 |
2160 | |
2161 | decalColor = {1-brightness, 1-brightness, 1-brightness} |
2162 | end |
2163 | |
2164 | if colorValue ~= nil then |
2165 | local material = getXMLInt(xmlFile, baseName..".topArm#material") |
2166 | I3DUtil.setShaderParameterRec(rootNode, "colorMat0", colorValue[1], colorValue[2], colorValue[3], material or colorValue[4]) |
2167 | end |
2168 | if colorValue2 ~= nil then |
2169 | local material2 = getXMLInt(xmlFile, baseName..".topArm#material2") |
2170 | I3DUtil.setShaderParameterRec(rootNode, "colorMat1", colorValue2[1], colorValue2[2], colorValue2[3], material2 or colorValue2[4]) |
2171 | end |
2172 | if decalColor ~= nil then |
2173 | I3DUtil.setShaderParameterRec(rootNode, "colorMat2", decalColor[1], decalColor[2], decalColor[3], 1) |
2174 | end |
2175 | |
2176 | attacherJoint.topArm = topArm |
2177 | end |
2178 | end |
2179 | else |
2180 | local rotationNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".topArm#rotationNode"), self.i3dMappings) |
2181 | local translationNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".topArm#translationNode"), self.i3dMappings) |
2182 | local referenceNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".topArm#referenceNode"), self.i3dMappings) |
2183 | if rotationNode ~= nil then |
2184 | local topArm = {} |
2185 | topArm.rotationNode = rotationNode |
2186 | topArm.rotX, topArm.rotY, topArm.rotZ = getRotation(rotationNode) |
2187 | if translationNode ~= nil and referenceNode ~= nil then |
2188 | topArm.translationNode = translationNode |
2189 | |
2190 | local x,y,z = getTranslation(translationNode) |
2191 | if math.abs(x) >= 0.0001 or math.abs(y) >= 0.0001 or math.abs(z) >= 0.0001 then |
2192 | g_logManager:xmlWarning(self.configFileName, "TopArm translation of attacherJoint '%s' is not 0/0/0!", baseName) |
2193 | end |
2194 | topArm.referenceDistance = calcDistanceFrom(referenceNode, translationNode) |
2195 | end |
2196 | topArm.zScale = MathUtil.sign(Utils.getNoNil(getXMLFloat(xmlFile, baseName.. ".topArm#zScale"), 1)) |
2197 | topArm.toggleVisibility = Utils.getNoNil(getXMLBool(xmlFile, baseName.. ".topArm#toggleVisibility"), false) |
2198 | if topArm.toggleVisibility then |
2199 | setVisibility(topArm.rotationNode, false) |
2200 | end |
2201 | |
2202 | attacherJoint.topArm = topArm |
2203 | end |
2204 | end |
2205 | |
2206 | local rotationNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".bottomArm#rotationNode"), self.i3dMappings) |
2207 | local translationNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".bottomArm#translationNode"), self.i3dMappings) |
2208 | local referenceNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".bottomArm#referenceNode"), self.i3dMappings) |
2209 | if rotationNode ~= nil then |
2210 | local bottomArm = {} |
2211 | bottomArm.rotationNode = rotationNode |
2212 | bottomArm.lastDirection = {0, 0, 0} |
2213 | local startRot = StringUtil.getRadiansFromString(getXMLString(xmlFile, baseName..".bottomArm#startRotation"), 3) |
2214 | if startRot ~= nil then |
2215 | bottomArm.rotX, bottomArm.rotY, bottomArm.rotZ = startRot[1],startRot[2],startRot[3] |
2216 | else |
2217 | bottomArm.rotX, bottomArm.rotY, bottomArm.rotZ = getRotation(rotationNode) |
2218 | end |
2219 | if translationNode ~= nil and referenceNode ~= nil then |
2220 | bottomArm.translationNode = translationNode |
2221 | |
2222 | local x,y,z = getTranslation(translationNode) |
2223 | if math.abs(x) >= 0.0001 or math.abs(y) >= 0.0001 or math.abs(z) >= 0.0001 then |
2224 | g_logManager:xmlWarning(self.configFileName, "BottomArm translation of attacherJoint '%s' is not 0/0/0!", baseName) |
2225 | end |
2226 | bottomArm.referenceDistance = calcDistanceFrom(referenceNode, translationNode) |
2227 | end |
2228 | bottomArm.zScale = MathUtil.sign(Utils.getNoNil(getXMLFloat(xmlFile, baseName.. ".bottomArm#zScale"), 1)) |
2229 | bottomArm.lockDirection = Utils.getNoNil(getXMLBool(xmlFile, baseName.. ".bottomArm#lockDirection"), true) |
2230 | |
2231 | bottomArm.toggleVisibility = Utils.getNoNil(getXMLBool(xmlFile, baseName.. ".bottomArm#toggleVisibility"), false) |
2232 | if bottomArm.toggleVisibility then |
2233 | setVisibility(bottomArm.rotationNode, false) |
2234 | end |
2235 | |
2236 | if jointType == AttacherJoints.JOINTTYPE_IMPLEMENT then |
2237 | local toolbarFilename = Utils.getNoNil(getXMLString(xmlFile, baseName.. ".toolbar#filename"), "$data/shared/assets/toolbar.i3d") |
2238 | local i3dNode = g_i3DManager:loadSharedI3DFile(toolbarFilename, self.baseDirectory, false, false, false) |
2239 | if i3dNode ~= 0 then |
2240 | local rootNode = getChildAt(i3dNode, 0) |
2241 | link(referenceNode, rootNode) |
2242 | delete(i3dNode) |
2243 | setTranslation(rootNode, 0,0,0) |
2244 | bottomArm.toolbar = rootNode |
2245 | setVisibility(rootNode, false) |
2246 | end |
2247 | end |
2248 | |
2249 | attacherJoint.bottomArm = bottomArm |
2250 | end |
2251 | |
2252 | if self.isClient then |
2253 | attacherJoint.sampleAttach = g_soundManager:loadSampleFromXML(xmlFile, baseName, "attachSound", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
2254 | end |
2255 | |
2256 | attacherJoint.steeringBarLeftNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".steeringBars#leftNode"), self.i3dMappings) |
2257 | attacherJoint.steeringBarRightNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.. ".steeringBars#rightNode"), self.i3dMappings) |
2258 | |
2259 | attacherJoint.changeObjects = {} |
2260 | ObjectChangeUtil.loadObjectChangeFromXML(xmlFile, baseName, attacherJoint.changeObjects, self.components, self) |
2261 | -- ObjectChangeUtil.setObjectChanges(attacherJoint.changeObjects, false, self, self.setMovingToolDirty) |
2262 | |
2263 | attacherJoint.rootNode = Utils.getNoNil(I3DUtil.indexToObject(self.components, getXMLString(xmlFile, baseName.."#rootNode"), self.i3dMappings), self.components[1].node) |
2264 | attacherJoint.rootNodeBackup = attacherJoint.rootNode |
2265 | attacherJoint.jointIndex = 0 |
2266 | |
2267 | local t = getXMLFloat(xmlFile, baseName .. "#comboTime") |
2268 | if t ~= nil then |
2269 | table.insert(spec.attacherJointCombos.joints, {jointIndex = index + 1, time = MathUtil.clamp(t, 0, 1) * spec.attacherJointCombos.duration}) |
2270 | end |
2271 | |
2272 | local schemaKey = baseName.. ".schema" |
2273 | if hasXMLProperty(xmlFile, schemaKey) then |
2274 | local x, y = StringUtil.getVectorFromString(getXMLString(xmlFile, schemaKey .. "#position")) |
2275 | local liftedOffsetX, liftedOffsetY = StringUtil.getVectorFromString(Utils.getNoNil(getXMLString(xmlFile, schemaKey.."#liftedOffset"), "0 5")) |
2276 | |
2277 | self.schemaOverlay:addAttacherJoint(x, y, |
2278 | math.rad(Utils.getNoNil(getXMLFloat(xmlFile, schemaKey .. "#rotation"), 0)), |
2279 | Utils.getNoNil(getXMLBool(xmlFile, schemaKey .. "#invertX"), false), |
2280 | liftedOffsetX, liftedOffsetY) |
2281 | else |
2282 | g_logManager:xmlWarning(self.configFileName, "Missing schema overlay attacherJoint '%s'!", baseName) |
2283 | end |
2284 | |
2285 | return true |
2286 | end |
loadAttachmentsFromXMLFile
DescriptionCalled on loadingDefinition
loadAttachmentsFromXMLFile(table savegame)Arguments
table | savegame | savegame |
703 | function AttacherJoints:loadAttachmentsFromXMLFile(xmlFile, key, idsToVehicle) |
704 | local spec = self.spec_attacherJoints |
705 | |
706 | local i = 0 |
707 | while true do |
708 | local attachmentKey = string.format("%s.attachment(%d)", key, i) |
709 | if not hasXMLProperty(xmlFile, attachmentKey) then |
710 | break |
711 | end |
712 | |
713 | local attachmentId = getXMLString(xmlFile, attachmentKey.."#attachmentId") |
714 | local jointIndex = getXMLInt(xmlFile, attachmentKey.."#jointIndex") |
715 | local inputJointDescIndex = Utils.getNoNil(getXMLInt(xmlFile, attachmentKey.."#inputJointDescIndex"), 1) |
716 | if attachmentId ~= nil and jointIndex ~= nil then |
717 | local attachment = idsToVehicle[attachmentId] |
718 | |
719 | local inputAttacherJoints |
720 | if attachment ~= nil and attachment.getInputAttacherJoints ~= nil then |
721 | inputAttacherJoints = attachment:getInputAttacherJoints() |
722 | end |
723 | local inputAttacherJoint |
724 | if inputAttacherJoints ~= nil then |
725 | inputAttacherJoint = inputAttacherJoints[inputJointDescIndex] |
726 | end |
727 | |
728 | if inputAttacherJoint ~= nil and spec.attacherJoints[jointIndex] ~= nil and spec.attacherJoints[jointIndex].jointIndex == 0 then |
729 | self:attachImplement(attachment, inputJointDescIndex, jointIndex, true, nil, nil, false, true) |
730 | |
731 | local moveDown = getXMLBool(xmlFile, attachmentKey.."#moveDown") |
732 | if moveDown ~= nil then |
733 | self:setJointMoveDown(jointIndex, moveDown, true) |
734 | end |
735 | end |
736 | end |
737 | |
738 | i = i + 1 |
739 | end |
740 | end |
loadDashboardGroupFromXML
DescriptionDefinitionloadDashboardGroupFromXML()Code
2530 | function AttacherJoints:loadDashboardGroupFromXML(superFunc, xmlFile, key, group) |
2531 | if not superFunc(self, xmlFile, key, group) then |
2532 | return false |
2533 | end |
2534 | |
2535 | local attacherJointIndicesString = Utils.getNoNil(getXMLString(xmlFile, key .. "#attacherJointIndices"), "") |
2536 | group.attacherJointIndices = {StringUtil.getVectorFromString(attacherJointIndicesString)} |
2537 | |
2538 | return true |
2539 | end |
onActivate
DescriptionCalled on activateDefinition
onActivate()Code
2667 | function AttacherJoints:onActivate() |
2668 | self:activateAttachments() |
2669 | end |
onBeaconLightsVisibilityChanged
DescriptionDefinitiononBeaconLightsVisibilityChanged()Code
2768 | function AttacherJoints:onBeaconLightsVisibilityChanged(visibility) |
2769 | local spec = self.spec_attacherJoints |
2770 | for _, implement in pairs(spec.attachedImplements) do |
2771 | local vehicle = implement.object |
2772 | if vehicle ~= nil and vehicle.setBeaconLightsVisibility ~= nil then |
2773 | vehicle:setBeaconLightsVisibility(visibility, true, true) |
2774 | end |
2775 | end |
2776 | end |
onBrake
DescriptionDefinitiononBrake()Code
2780 | function AttacherJoints:onBrake(brakePedal) |
2781 | local spec = self.spec_attacherJoints |
2782 | for _, implement in pairs(spec.attachedImplements) do |
2783 | local vehicle = implement.object |
2784 | if vehicle ~= nil and vehicle.brake ~= nil then |
2785 | vehicle:brake(brakePedal) |
2786 | end |
2787 | end |
2788 | end |
onBrakeLightsVisibilityChanged
DescriptionDefinitiononBrakeLightsVisibilityChanged()Code
2744 | function AttacherJoints:onBrakeLightsVisibilityChanged(visibility) |
2745 | local spec = self.spec_attacherJoints |
2746 | for _, implement in pairs(spec.attachedImplements) do |
2747 | local vehicle = implement.object |
2748 | if vehicle ~= nil and vehicle.setBrakeLightsVisibility ~= nil then |
2749 | vehicle:setBrakeLightsVisibility(visibility) |
2750 | end |
2751 | end |
2752 | end |
onDeactivate
DescriptionCalled on deactivateDefinition
onDeactivate()Code
2673 | function AttacherJoints:onDeactivate() |
2674 | self:deactivateAttachments() |
2675 | if self.isClient then |
2676 | local spec = self.spec_attacherJoints |
2677 | g_soundManager:stopSample(spec.samples.hydraulic) |
2678 | spec.isHydraulicSamplePlaying = false |
2679 | end |
2680 | end |
onDeactivateLights
DescriptionCalled on deactivating lightsDefinition
onDeactivateLights()Code
2696 | function AttacherJoints:onDeactivateLights() |
2697 | self:deactivateAttachmentsLights() |
2698 | end |
onDelete
DescriptionCalled on deletingDefinition
onDelete()Code
306 | function AttacherJoints:onDelete() |
307 | local spec = self.spec_attacherJoints |
308 | |
309 | if self.isClient then |
310 | for _, jointDesc in pairs(spec.attacherJoints) do |
311 | g_soundManager:deleteSample(jointDesc.sampleAttach) |
312 | end |
313 | |
314 | g_soundManager:deleteSample(spec.samples.hydraulic) |
315 | g_soundManager:deleteSample(spec.samples.attach) |
316 | end |
317 | end |
onDraw
DescriptionCalled on drawDefinition
onDraw(boolean isActiveForInput, boolean isSelected)Arguments
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
684 | function AttacherJoints:onDraw(isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
685 | local spec = self.spec_attacherJoints |
686 | |
687 | if self == g_currentMission.controlledVehicle then |
688 | -- call draw on all attached implements, selection check is done in the implement |
689 | for _, implement in ipairs(spec.attachedImplements) do |
690 | local object = implement.object |
691 | if object ~= nil then |
692 | if object.draw ~= nil then |
693 | object.draw(object, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
694 | end |
695 | end |
696 | end |
697 | end |
698 | end |
onLeaveVehicle
DescriptionDefinitiononLeaveVehicle()Code
2826 | function AttacherJoints:onLeaveVehicle() |
2827 | local spec = self.spec_attacherJoints |
2828 | for _, implement in pairs(spec.attachedImplements) do |
2829 | local vehicle = implement.object |
2830 | if vehicle ~= nil then |
2831 | SpecializationUtil.raiseEvent(vehicle, "onLeaveRootVehicle") |
2832 | end |
2833 | end |
2834 | end |
onLightsTypesMaskChanged
DescriptionDefinitiononLightsTypesMaskChanged()Code
2720 | function AttacherJoints:onLightsTypesMaskChanged(lightsTypesMask) |
2721 | local spec = self.spec_attacherJoints |
2722 | for _, implement in pairs(spec.attachedImplements) do |
2723 | local vehicle = implement.object |
2724 | if vehicle ~= nil and vehicle.setLightsTypesMask ~= nil then |
2725 | vehicle:setLightsTypesMask(lightsTypesMask, true, true) |
2726 | end |
2727 | end |
2728 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
179 | function AttacherJoints:onLoad(savegame) |
180 | |
181 | local spec = self.spec_attacherJoints |
182 | |
183 | spec.attacherJointCombos = {} |
184 | spec.attacherJointCombos.duration = Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.attacherJoints#comboDuration"), 2) * 1000 |
185 | spec.attacherJointCombos.currentTime = 0 |
186 | spec.attacherJointCombos.direction = -1 |
187 | spec.attacherJointCombos.isRunning = false |
188 | spec.attacherJointCombos.joints = {} |
189 | |
190 | spec.attacherJoints = {} |
191 | local i=0 |
192 | while true do |
193 | local baseName = string.format("vehicle.attacherJoints.attacherJoint(%d)", i) |
194 | if not hasXMLProperty(self.xmlFile, baseName) then |
195 | break |
196 | end |
197 | local attacherJoint = {} |
198 | if self:loadAttacherJointFromXML(attacherJoint, self.xmlFile, baseName, i) then |
199 | table.insert(spec.attacherJoints, attacherJoint) |
200 | attacherJoint.index = #spec.attacherJoints |
201 | end |
202 | i = i + 1 |
203 | end |
204 | |
205 | if self.configurations["attacherJoint"] ~= nil then |
206 | local attacherConfigs = string.format("vehicle.attacherJoints.attacherJointConfigurations.attacherJointConfiguration(%d)", self.configurations["attacherJoint"]-1) |
207 | local i=0 |
208 | while true do |
209 | local baseName = string.format(attacherConfigs..".attacherJoint(%d)", i) |
210 | if not hasXMLProperty(self.xmlFile, baseName) then |
211 | break |
212 | end |
213 | local attacherJoint = {} |
214 | if self:loadAttacherJointFromXML(attacherJoint, self.xmlFile, baseName, i) then |
215 | table.insert(spec.attacherJoints, attacherJoint) |
216 | end |
217 | i = i + 1 |
218 | end |
219 | ObjectChangeUtil.updateObjectChanges(self.xmlFile, "vehicle.attacherJoints.attacherJointConfigurations.attacherJointConfiguration", self.configurations["attacherJoint"], self.components, self) |
220 | end |
221 | |
222 | spec.attachedImplements = {} |
223 | spec.selectedImplement = nil |
224 | |
225 | -- data structure to store information about eventually attachable vehicles |
226 | spec.attachableInfo = {} |
227 | spec.attachableInfo.attacherVehicle = nil |
228 | spec.attachableInfo.attacherVehicleJointDescIndex = nil |
229 | spec.attachableInfo.attachable = nil |
230 | spec.attachableInfo.attachableJointDescIndex = nil |
231 | |
232 | if self.isClient then |
233 | spec.samples = {} |
234 | spec.isHydraulicSamplePlaying = false |
235 | spec.samples.hydraulic = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.attacherJoints.sounds", "hydraulic", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
236 | spec.samples.attach = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.attacherJoints.sounds", "attach", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
237 | end |
238 | |
239 | if self.isClient and g_isDevelopmentVersion then |
240 | for k, attacherJoint in ipairs(spec.attacherJoints) do |
241 | if spec.samples.attach == nil and attacherJoint.sampleAttach == nil then |
242 | g_logManager:xmlDevWarning(self.configFileName, "Missing attach sound for attacherjoint '%d'", k) |
243 | end |
244 | if attacherJoint.rotationNode ~= nil and spec.samples.hydraulic == nil then |
245 | g_logManager:xmlDevWarning(self.configFileName, "Missing hydraulic sound for attacherjoint '%d'", k) |
246 | end |
247 | end |
248 | end |
249 | |
250 | spec.showAttachNotAllowedText = 0 |
251 | end |
onPostLoad
DescriptionCalled after loadingDefinition
onPostLoad(table savegame)Arguments
table | savegame | savegame |
256 | function AttacherJoints:onPostLoad(savegame) |
257 | local spec = self.spec_attacherJoints |
258 | |
259 | for _, attacherJoint in pairs(spec.attacherJoints) do |
260 | attacherJoint.jointOrigRot = { getRotation(attacherJoint.jointTransform) } |
261 | attacherJoint.jointOrigTrans = { getTranslation(attacherJoint.jointTransform) } |
262 | if attacherJoint.transNode ~= nil then |
263 | attacherJoint.transNodeMinY = Utils.getNoNil(attacherJoint.transNodeMinY, attacherJoint.jointOrigTrans[2]) |
264 | attacherJoint.transNodeMaxY = Utils.getNoNil(attacherJoint.transNodeMaxY, attacherJoint.jointOrigTrans[2]) |
265 | _, attacherJoint.transNodeOffsetY, _ = localToLocal(attacherJoint.jointTransform, attacherJoint.transNode, 0, 0, 0) |
266 | _, attacherJoint.transNodeMinY, _ = localToLocal(getParent(attacherJoint.transNode), self.rootNode, 0, attacherJoint.transNodeMinY, 0) |
267 | _, attacherJoint.transNodeMaxY, _ = localToLocal(getParent(attacherJoint.transNode), self.rootNode, 0, attacherJoint.transNodeMaxY, 0) |
268 | end |
269 | |
270 | if attacherJoint.bottomArm ~= nil then |
271 | setRotation(attacherJoint.bottomArm.rotationNode, attacherJoint.bottomArm.rotX, attacherJoint.bottomArm.rotY, attacherJoint.bottomArm.rotZ) |
272 | if self.setMovingToolDirty ~= nil then |
273 | self:setMovingToolDirty(attacherJoint.bottomArm.rotationNode) |
274 | end |
275 | end |
276 | if attacherJoint.rotationNode ~= nil then |
277 | setRotation(attacherJoint.rotationNode, attacherJoint.rotX, attacherJoint.rotY, attacherJoint.rotZ) |
278 | end |
279 | end |
280 | |
281 | if savegame ~= nil and not savegame.resetVehicles then |
282 | if spec.attacherJointCombos ~= nil then |
283 | local comboDirection = getXMLInt(savegame.xmlFile, savegame.key..".attacherJoints#comboDirection") |
284 | if comboDirection ~= nil then |
285 | spec.attacherJointCombos.direction = comboDirection |
286 | if comboDirection == 1 then |
287 | spec.attacherJointCombos.currentTime = spec.attacherJointCombos.duration |
288 | end |
289 | end |
290 | end |
291 | end |
292 | end |
onPostUpdate
DescriptionCalled on after updateDefinition
onPostUpdate(float dt, boolean isActiveForInput, boolean isSelected)Arguments
float | dt | time since last call in ms |
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
443 | function AttacherJoints:onPostUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
444 | local spec = self.spec_attacherJoints |
445 | |
446 | for _,implement in pairs(spec.attachedImplements) do |
447 | if not implement.attachingIsInProgress then |
448 | local attacherJoint = implement.object:getActiveInputAttacherJoint() |
449 | if attacherJoint ~= nil then |
450 | if spec.attacherJoints[implement.jointDescIndex].steeringBarLeftNode ~= nil and attacherJoint.steeringBarLeftMovingPart ~= nil then |
451 | Cylindered.updateMovingPart(self, attacherJoint.steeringBarLeftMovingPart, nil, true) |
452 | end |
453 | if spec.attacherJoints[implement.jointDescIndex].steeringBarRightNode ~= nil and attacherJoint.steeringBarRightMovingPart ~= nil then |
454 | Cylindered.updateMovingPart(self, attacherJoint.steeringBarRightMovingPart, nil, true) |
455 | end |
456 | end |
457 | end |
458 | end |
459 | end |
onPreDelete
DescriptionCalled on before deletingDefinition
onPreDelete()Code
296 | function AttacherJoints:onPreDelete() |
297 | local spec = self.spec_attacherJoints |
298 | |
299 | for i=table.getn(spec.attachedImplements), 1, -1 do |
300 | self:detachImplement(1, true) |
301 | end |
302 | end |
onReadStream
DescriptionCalled on client side on joinDefinition
onReadStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
365 | function AttacherJoints:onReadStream(streamId, connection) |
366 | local numImplements = streamReadInt8(streamId) |
367 | for i=1, numImplements do |
368 | local object = NetworkUtil.readNodeObject(streamId) |
369 | local inputJointDescIndex = streamReadInt8(streamId) |
370 | local jointDescIndex = streamReadInt8(streamId) |
371 | local moveDown = streamReadBool(streamId) |
372 | if object ~= nil then |
373 | self:attachImplement(object, inputJointDescIndex, jointDescIndex, true, i) |
374 | self:setJointMoveDown(jointDescIndex, moveDown, true) |
375 | end |
376 | end |
377 | end |
onRegisterActionEvents
DescriptionDefinitiononRegisterActionEvents()Code
2621 | function AttacherJoints:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
2622 | if self.isClient then |
2623 | local spec = self.spec_attacherJoints |
2624 | self:clearActionEventsTable(spec.actionEvents) |
2625 | |
2626 | -- ignore vehicle selection on 'getIsActiveForInput', so we can select the target vehicle and attach or lower it |
2627 | if isActiveForInputIgnoreSelection then |
2628 | if table.getn(spec.attacherJoints) > 0 then |
2629 | -- only display lower and attach action if selected implement is direct child of vehicle, not sub child |
2630 | local selectedImplement = self:getSelectedImplement() |
2631 | if selectedImplement ~= nil and selectedImplement.object ~= self then |
2632 | for _, attachedImplement in pairs(spec.attachedImplements) do |
2633 | if attachedImplement == selectedImplement then |
2634 | -- custom registration of the action event. This allows us to overwritte it in the implement (e.g in Foldable) |
2635 | selectedImplement.object:registerLoweringActionEvent(spec.actionEvents, InputAction.LOWER_IMPLEMENT, selectedImplement.object, AttacherJoints.actionEventLowerImplement, false, true, false, true, nil, nil, true) |
2636 | end |
2637 | end |
2638 | end |
2639 | |
2640 | local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.LOWER_ALL_IMPLEMENTS, self, AttacherJoints.actionEventLowerAllImplements, false, true, false, true, nil, nil, true) |
2641 | g_inputBinding:setActionEventTextVisibility(actionEventId, false) |
2642 | end |
2643 | |
2644 | if self:getSelectedVehicle() == self then |
2645 | local state, _ = self:registerSelfLoweringActionEvent(spec.actionEvents, InputAction.LOWER_IMPLEMENT, self, AttacherJoints.actionEventLowerImplement, false, true, false, true, nil, nil, true) |
2646 | |
2647 | -- if the selected attacher vehicle can not be lowered and we got only one implement that can be lowered |
2648 | -- we add the lowering action for the first implement |
2649 | if state == nil or not state then |
2650 | if #spec.attachedImplements == 1 then |
2651 | local firstImplement = spec.attachedImplements[1] |
2652 | if firstImplement ~= nil then |
2653 | firstImplement.object:registerLoweringActionEvent(spec.actionEvents, InputAction.LOWER_IMPLEMENT, firstImplement.object, AttacherJoints.actionEventLowerImplement, false, true, false, true, nil, nil, true) |
2654 | end |
2655 | end |
2656 | end |
2657 | end |
2658 | |
2659 | local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.ATTACH, self, AttacherJoints.actionEventAttach, false, true, false, true, nil, nil, true) |
2660 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_HIGH) |
2661 | end |
2662 | end |
2663 | end |
onReverseDirectionChanged
DescriptionDefinitiononReverseDirectionChanged()Code
2684 | function AttacherJoints:onReverseDirectionChanged(direction) |
2685 | local spec = self.spec_attacherJoints |
2686 | |
2687 | if spec.attacherJointCombos ~= nil then |
2688 | for _, joint in pairs(spec.attacherJointCombos.joints) do |
2689 | joint.time = math.abs(joint.time - spec.attacherJointCombos.duration) |
2690 | end |
2691 | end |
2692 | end |
onReverseLightsVisibilityChanged
DescriptionDefinitiononReverseLightsVisibilityChanged()Code
2756 | function AttacherJoints:onReverseLightsVisibilityChanged(visibility) |
2757 | local spec = self.spec_attacherJoints |
2758 | for _, implement in pairs(spec.attachedImplements) do |
2759 | local vehicle = implement.object |
2760 | if vehicle ~= nil and vehicle.setReverseLightsVisibility ~= nil then |
2761 | vehicle:setReverseLightsVisibility(visibility) |
2762 | end |
2763 | end |
2764 | end |
onStateChange
DescriptionDefinitiononStateChange()Code
2702 | function AttacherJoints:onStateChange(state, data) |
2703 | local spec = self.spec_attacherJoints |
2704 | |
2705 | for _, implement in pairs(spec.attachedImplements) do |
2706 | if implement.object ~= nil then |
2707 | implement.object:raiseStateChange(state, data) |
2708 | end |
2709 | end |
2710 | |
2711 | if state == Vehicle.STATE_CHANGE_LOWER_ALL_IMPLEMENTS then |
2712 | if table.getn(spec.attacherJoints) > 0 then |
2713 | self:startAttacherJointCombo() |
2714 | end |
2715 | end |
2716 | end |
onTurnedOff
DescriptionDefinitiononTurnedOff()Code
2809 | function AttacherJoints:onTurnedOff() |
2810 | local spec = self.spec_attacherJoints |
2811 | for _, implement in pairs(spec.attachedImplements) do |
2812 | local vehicle = implement.object |
2813 | if vehicle ~= nil then |
2814 | local turnedOnVehicleSpec = vehicle.spec_turnOnVehicle |
2815 | if turnedOnVehicleSpec then |
2816 | if turnedOnVehicleSpec.turnedOnByAttacherVehicle then |
2817 | vehicle:setIsTurnedOn(false, true) |
2818 | end |
2819 | end |
2820 | end |
2821 | end |
2822 | end |
onTurnedOn
DescriptionDefinitiononTurnedOn()Code
2792 | function AttacherJoints:onTurnedOn() |
2793 | local spec = self.spec_attacherJoints |
2794 | for _, implement in pairs(spec.attachedImplements) do |
2795 | local vehicle = implement.object |
2796 | if vehicle ~= nil then |
2797 | local turnedOnVehicleSpec = vehicle.spec_turnOnVehicle |
2798 | if turnedOnVehicleSpec then |
2799 | if turnedOnVehicleSpec.turnedOnByAttacherVehicle then |
2800 | vehicle:setIsTurnedOn(true, true) |
2801 | end |
2802 | end |
2803 | end |
2804 | end |
2805 | end |
onTurnLightStateChanged
DescriptionDefinitiononTurnLightStateChanged()Code
2732 | function AttacherJoints:onTurnLightStateChanged(state) |
2733 | local spec = self.spec_attacherJoints |
2734 | for _, implement in pairs(spec.attachedImplements) do |
2735 | local vehicle = implement.object |
2736 | if vehicle ~= nil and vehicle.setTurnLightState ~= nil then |
2737 | vehicle:setTurnLightState(state, true, true) |
2738 | end |
2739 | end |
2740 | end |
onUpdate
DescriptionCalled on updateDefinition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)Arguments
float | dt | time since last call in ms |
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
407 | function AttacherJoints:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
408 | local spec = self.spec_attacherJoints |
409 | |
410 | for _, implement in pairs(spec.attachedImplements) do |
411 | if implement.object ~= nil then |
412 | if self.isServer or (self.updateLoopIndex == implement.object.updateLoopIndex) then |
413 | self:updateAttacherJointGraphics(implement, dt) |
414 | end |
415 | end |
416 | end |
417 | |
418 | if not self.isServer and self.getAttacherVehicle ~= nil then |
419 | local attacherVehicle = self:getAttacherVehicle() |
420 | if attacherVehicle ~= nil then |
421 | if self.updateLoopIndex == attacherVehicle.updateLoopIndex then |
422 | local implement = attacherVehicle:getImplementByObject(self) |
423 | if implement ~= nil then |
424 | attacherVehicle:updateAttacherJointGraphics(implement, dt) |
425 | end |
426 | end |
427 | end |
428 | end |
429 | |
430 | if self.isClient then |
431 | spec.showAttachNotAllowedText = math.max(spec.showAttachNotAllowedText - dt, 0) |
432 | if spec.showAttachNotAllowedText > 0 then |
433 | g_currentMission:addExtraPrintText(g_i18n:getText("info_attach_not_allowed")) |
434 | end |
435 | end |
436 | end |
onUpdateTick
DescriptionCalled on update tickDefinition
onUpdateTick(float dt, boolean isActiveForInput, boolean isSelected)Arguments
float | dt | time since last call in ms |
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
466 | function AttacherJoints:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
467 | local spec = self.spec_attacherJoints |
468 | |
469 | local playHydraulicSound = false |
470 | |
471 | for _, implement in pairs(spec.attachedImplements) do |
472 | if implement.object ~= nil then |
473 | local jointDesc = spec.attacherJoints[implement.jointDescIndex] |
474 | |
475 | if not implement.object.isHardAttached then |
476 | if self.isServer then |
477 | if implement.attachingIsInProgress then |
478 | local done = true |
479 | for i=1,3 do |
480 | local lastRotLimit = implement.attachingRotLimit[i] |
481 | local lastTransLimit = implement.attachingTransLimit[i] |
482 | implement.attachingRotLimit[i] = math.max(0, implement.attachingRotLimit[i] - implement.attachingRotLimitSpeed[i] * dt) |
483 | implement.attachingTransLimit[i] = math.max(0, implement.attachingTransLimit[i] - implement.attachingTransLimitSpeed[i] * dt) |
484 | if (implement.attachingRotLimit[i] > 0 or implement.attachingTransLimit[i] > 0) or |
485 | (lastRotLimit > 0 or lastTransLimit > 0) |
486 | then |
487 | done = false |
488 | end |
489 | end |
490 | implement.attachingIsInProgress = not done |
491 | |
492 | if done then |
493 | if implement.object.spec_attachable.attacherJoint.hardAttach and self:getIsHardAttachAllowed(implement.jointDescIndex) then |
494 | self:hardAttachImplement(implement) |
495 | end |
496 | self:postAttachImplement(implement) |
497 | end |
498 | end |
499 | end |
500 | if not implement.attachingIsInProgress then |
501 | local jointFrameInvalid = false |
502 | if jointDesc.allowsLowering then |
503 | local moveAlpha = Utils.getMovedLimitedValue(jointDesc.moveAlpha, jointDesc.lowerAlpha, jointDesc.upperAlpha, jointDesc.moveTime, dt, not jointDesc.moveDown) |
504 | if moveAlpha ~= jointDesc.moveAlpha then |
505 | playHydraulicSound = true |
506 | jointDesc.moveAlpha = moveAlpha |
507 | jointDesc.moveLimitAlpha = 1- (moveAlpha-jointDesc.lowerAlpha) / (jointDesc.upperAlpha-jointDesc.lowerAlpha) |
508 | jointFrameInvalid = true |
509 | self:updateAttacherJointRotationNodes(jointDesc, jointDesc.moveAlpha) |
510 | self:updateAttacherJointRotation(jointDesc, implement.object) |
511 | end |
512 | end |
513 | |
514 | jointFrameInvalid = jointFrameInvalid or jointDesc.jointFrameInvalid |
515 | if jointFrameInvalid then |
516 | jointDesc.jointFrameInvalid = false |
517 | if self.isServer then |
518 | setJointFrame(jointDesc.jointIndex, 0, jointDesc.jointTransform) |
519 | end |
520 | end |
521 | end |
522 | if self.isServer then |
523 | local force = implement.attachingIsInProgress |
524 | if force or (jointDesc.allowsLowering and jointDesc.allowsJointLimitMovement) then |
525 | if jointDesc.jointIndex ~= nil and jointDesc.jointIndex ~= 0 then |
526 | if force or implement.object.spec_attachable.attacherJoint.allowsJointRotLimitMovement then |
527 | for i=1,3 do |
528 | local newRotLimit = MathUtil.lerp( math.max(implement.attachingRotLimit[i], implement.upperRotLimit[i]), |
529 | math.max(implement.attachingRotLimit[i], implement.lowerRotLimit[i]), jointDesc.moveLimitAlpha) |
530 | if force or math.abs(newRotLimit - implement.jointRotLimit[i]) > 0.0005 then |
531 | local rotLimitDown = -newRotLimit |
532 | local rotLimitUp = newRotLimit |
533 | if i == 3 then |
534 | if jointDesc.lockDownRotLimit then |
535 | rotLimitDown = math.min(-implement.attachingRotLimit[i], 0) |
536 | end |
537 | if jointDesc.lockUpRotLimit then |
538 | rotLimitUp = math.max(implement.attachingRotLimit[i], 0) |
539 | end |
540 | end |
541 | setJointRotationLimit(jointDesc.jointIndex, i-1, true, rotLimitDown, rotLimitUp) |
542 | implement.jointRotLimit[i] = newRotLimit |
543 | end |
544 | end |
545 | end |
546 | |
547 | if force or implement.object.spec_attachable.attacherJoint.allowsJointTransLimitMovement then |
548 | for i=1,3 do |
549 | local newTransLimit = MathUtil.lerp( math.max(implement.attachingTransLimit[i], implement.upperTransLimit[i]), |
550 | math.max(implement.attachingTransLimit[i], implement.lowerTransLimit[i]), jointDesc.moveLimitAlpha) |
551 | |
552 | if force or math.abs(newTransLimit - implement.jointTransLimit[i]) > 0.0005 then |
553 | local transLimitDown = -newTransLimit |
554 | local transLimitUp = newTransLimit |
555 | if i == 2 then |
556 | if jointDesc.lockDownTransLimit then |
557 | transLimitDown = math.min(-implement.attachingTransLimit[i], 0) |
558 | end |
559 | if jointDesc.lockUpTransLimit then |
560 | transLimitUp = math.max(implement.attachingTransLimit[i], 0) |
561 | end |
562 | end |
563 | |
564 | setJointTranslationLimit(jointDesc.jointIndex, i-1, true, transLimitDown, transLimitUp) |
565 | implement.jointTransLimit[i] = newTransLimit |
566 | end |
567 | end |
568 | end |
569 | end |
570 | end |
571 | end |
572 | end |
573 | end |
574 | end |
575 | |
576 | if self.isClient and spec.samples.hydraulic ~= nil then |
577 | if playHydraulicSound then |
578 | if not spec.isHydraulicSamplePlaying then |
579 | g_soundManager:playSample(spec.samples.hydraulic) |
580 | spec.isHydraulicSamplePlaying = true |
581 | end |
582 | else |
583 | if spec.isHydraulicSamplePlaying then |
584 | g_soundManager:stopSample(spec.samples.hydraulic) |
585 | spec.isHydraulicSamplePlaying = false |
586 | end |
587 | end |
588 | end |
589 | |
590 | local combos = spec.attacherJointCombos |
591 | if combos ~= nil and combos.isRunning then |
592 | for _, joint in pairs(combos.joints) do |
593 | local doLowering |
594 | if combos.direction == 1 and combos.currentTime >= joint.time then |
595 | doLowering = true |
596 | elseif combos.direction == -1 and combos.currentTime <= combos.duration-joint.time then |
597 | doLowering = false |
598 | end |
599 | |
600 | if doLowering ~= nil then |
601 | local implement = self:getImplementFromAttacherJointIndex(joint.jointIndex) |
602 | if implement ~= nil then |
603 | if implement.object.setLoweredAll ~= nil then |
604 | implement.object:setLoweredAll(doLowering, joint.jointIndex) |
605 | end |
606 | end |
607 | end |
608 | end |
609 | |
610 | if (combos.direction == -1 and combos.currentTime == 0) or |
611 | (combos.direction == 1 and combos.currentTime == combos.duration) then |
612 | combos.isRunning = false |
613 | end |
614 | |
615 | combos.currentTime = MathUtil.clamp(combos.currentTime + dt*combos.direction, 0, combos.duration) |
616 | end |
617 | |
618 | -- find attachables in range |
619 | local info = spec.attachableInfo |
620 | info.attacherVehicle = nil |
621 | |
622 | if self.isClient then |
623 | if spec.actionEvents ~= nil then |
624 | local attachActionEvent = spec.actionEvents[InputAction.ATTACH] |
625 | if attachActionEvent ~= nil then |
626 | local visible = false |
627 | |
628 | if self:getCanToggleAttach() then |
629 | info.attacherVehicle, info.attacherVehicleJointDescIndex, info.attachable, info.attachableJointDescIndex = AttacherJoints.findVehicleInAttachRange(self, AttacherJoints.MAX_ATTACH_DISTANCE_SQ, AttacherJoints.MAX_ATTACH_ANGLE) |
630 | |
631 | local text = "" |
632 | local prio = GS_PRIO_VERY_LOW |
633 | |
634 | local selectedVehicle = self:getSelectedVehicle() |
635 | if selectedVehicle ~= nil and not selectedVehicle.isDeleted and selectedVehicle.isDetachAllowed ~= nil and selectedVehicle:isDetachAllowed() then |
636 | if selectedVehicle:getAttacherVehicle() ~= nil then |
637 | visible = true |
638 | text = g_i18n:getText("action_detach") |
639 | end |
640 | end |
641 | |
642 | if info.attacherVehicle ~= nil then |
643 | if g_currentMission.accessHandler:canFarmAccess(self:getActiveFarm(), info.attachable) then |
644 | visible = true |
645 | text = g_i18n:getText("action_attach") |
646 | g_currentMission:showAttachContext(info.attachable) |
647 | prio = GS_PRIO_VERY_HIGH |
648 | else |
649 | spec.showAttachNotAllowedText = 100 |
650 | end |
651 | end |
652 | |
653 | g_inputBinding:setActionEventText(attachActionEvent.actionEventId, text) |
654 | g_inputBinding:setActionEventTextPriority(attachActionEvent.actionEventId, prio) |
655 | end |
656 | |
657 | g_inputBinding:setActionEventTextVisibility(attachActionEvent.actionEventId, visible) |
658 | end |
659 | |
660 | local lowerActionEvent = spec.actionEvents[InputAction.LOWER_IMPLEMENT] |
661 | if lowerActionEvent ~= nil then |
662 | local showLower = false |
663 | local text = "" |
664 | local selectedImplement = self:getSelectedImplement() |
665 | for _,attachedImplement in pairs(spec.attachedImplements) do |
666 | if attachedImplement == selectedImplement then |
667 | showLower, text = attachedImplement.object:getLoweringActionEventState() |
668 | break |
669 | end |
670 | end |
671 | |
672 | g_inputBinding:setActionEventActive(lowerActionEvent.actionEventId, showLower) |
673 | g_inputBinding:setActionEventText(lowerActionEvent.actionEventId, text) |
674 | g_inputBinding:setActionEventTextPriority(lowerActionEvent.actionEventId, GS_PRIO_NORMAL) |
675 | end |
676 | end |
677 | end |
678 | end |
onWriteStream
DescriptionCalled on server side on joinDefinition
onWriteStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
383 | function AttacherJoints:onWriteStream(streamId, connection) |
384 | local spec = self.spec_attacherJoints |
385 | |
386 | -- write attached implements |
387 | streamWriteInt8(streamId, table.getn(spec.attachedImplements)) |
388 | for i=1, table.getn(spec.attachedImplements) do |
389 | local implement = spec.attachedImplements[i] |
390 | local inputJointDescIndex = implement.object.spec_attachable.inputAttacherJointDescIndex |
391 | local jointDescIndex = implement.jointDescIndex |
392 | local jointDesc = spec.attacherJoints[jointDescIndex] |
393 | local moveDown = jointDesc.moveDown |
394 | NetworkUtil.writeNodeObject(streamId, implement.object) |
395 | streamWriteInt8(streamId, inputJointDescIndex) |
396 | streamWriteInt8(streamId, jointDescIndex) |
397 | streamWriteBool(streamId, moveDown) |
398 | end |
399 | end |
playAttachSound
DescriptionPlay attach soundDefinition
playAttachSound(table jointDesc)Arguments
table | jointDesc | joint desc |
boolean | success | success |
1694 | function AttacherJoints:playAttachSound(jointDesc) |
1695 | local spec = self.spec_attacherJoints |
1696 | |
1697 | if self.isClient then |
1698 | if jointDesc ~= nil and jointDesc.sampleAttach ~= nil then |
1699 | g_soundManager:playSample(jointDesc.sampleAttach) |
1700 | else |
1701 | g_soundManager:playSample(spec.samples.attach) |
1702 | end |
1703 | end |
1704 | |
1705 | return true |
1706 | end |
playDetachSound
DescriptionPlay detach soundDefinition
playDetachSound(table jointDesc)Arguments
table | jointDesc | joint desc |
boolean | success | success |
1712 | function AttacherJoints:playDetachSound(jointDesc) |
1713 | local spec = self.spec_attacherJoints |
1714 | |
1715 | if self.isClient then |
1716 | if jointDesc ~= nil and jointDesc.sampleAttach ~= nil then |
1717 | g_soundManager:playSample(jointDesc.sampleAttach) |
1718 | else |
1719 | g_soundManager:playSample(spec.samples.attach) |
1720 | end |
1721 | end |
1722 | |
1723 | return true |
1724 | end |
postAttachImplement
DescriptionDefinitionpostAttachImplement()Code
1200 | function AttacherJoints:postAttachImplement(implement) |
1201 | |
1202 | local object = implement.object |
1203 | local inputJointDescIndex = implement.inputJointDescIndex |
1204 | local jointDescIndex = implement.jointDescIndex |
1205 | |
1206 | SpecializationUtil.raiseEvent(self, "onPostAttachImplement", object, inputJointDescIndex, jointDescIndex) |
1207 | object:postAttach(self, inputJointDescIndex, jointDescIndex, implement.loadFromSavegame) |
1208 | |
1209 | local data = {attacherVehicle=self, attachedVehicle=implement.object} |
1210 | local rootVehicle = self:getRootVehicle() |
1211 | rootVehicle:raiseStateChange(Vehicle.STATE_CHANGE_ATTACH, data) |
1212 | end |
prerequisitesPresent
DescriptionDefinitionprerequisitesPresent()Code
61 | function AttacherJoints.prerequisitesPresent(specializations) |
62 | return true |
63 | end |
raiseActive
DescriptionDefinitionraiseActive()Code
2290 | function AttacherJoints:raiseActive(superFunc) |
2291 | local spec = self.spec_attacherJoints |
2292 | |
2293 | superFunc(self) |
2294 | for _,implement in pairs(spec.attachedImplements) do |
2295 | if implement.object ~= nil then |
2296 | implement.object:raiseActive() |
2297 | end |
2298 | end |
2299 | end |
registerActionEvents
DescriptionDefinitionregisterActionEvents()Code
2303 | function AttacherJoints:registerActionEvents(superFunc, excludedVehicle) |
2304 | local spec = self.spec_attacherJoints |
2305 | |
2306 | superFunc(self, excludedVehicle) |
2307 | if self ~= excludedVehicle then |
2308 | -- at first we register the inputs of the selected vehicle |
2309 | -- so they got the higest prio and cannot be overwritten by another vehicle |
2310 | local selectedObject = self:getSelectedObject() |
2311 | if selectedObject ~= nil and self ~= selectedObject.vehicle and excludedVehicle ~= selectedObject.vehicle then |
2312 | selectedObject.vehicle:registerActionEvents() |
2313 | end |
2314 | |
2315 | for _,implement in pairs(spec.attachedImplements) do |
2316 | if implement.object ~= nil then |
2317 | implement.object:registerActionEvents(selectedObject.vehicle) |
2318 | end |
2319 | end |
2320 | end |
2321 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
149 | function AttacherJoints.registerEventListeners(vehicleType) |
150 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", AttacherJoints) |
151 | SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", AttacherJoints) |
152 | SpecializationUtil.registerEventListener(vehicleType, "onPreDelete", AttacherJoints) |
153 | SpecializationUtil.registerEventListener(vehicleType, "onDelete", AttacherJoints) |
154 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", AttacherJoints) |
155 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", AttacherJoints) |
156 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", AttacherJoints) |
157 | SpecializationUtil.registerEventListener(vehicleType, "onPostUpdate", AttacherJoints) |
158 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", AttacherJoints) |
159 | SpecializationUtil.registerEventListener(vehicleType, "onDraw", AttacherJoints) |
160 | SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", AttacherJoints) |
161 | SpecializationUtil.registerEventListener(vehicleType, "onStateChange", AttacherJoints) |
162 | SpecializationUtil.registerEventListener(vehicleType, "onLightsTypesMaskChanged", AttacherJoints) |
163 | SpecializationUtil.registerEventListener(vehicleType, "onTurnLightStateChanged", AttacherJoints) |
164 | SpecializationUtil.registerEventListener(vehicleType, "onBrakeLightsVisibilityChanged", AttacherJoints) |
165 | SpecializationUtil.registerEventListener(vehicleType, "onReverseLightsVisibilityChanged", AttacherJoints) |
166 | SpecializationUtil.registerEventListener(vehicleType, "onBeaconLightsVisibilityChanged", AttacherJoints) |
167 | SpecializationUtil.registerEventListener(vehicleType, "onBrake", AttacherJoints) |
168 | SpecializationUtil.registerEventListener(vehicleType, "onTurnedOn", AttacherJoints) |
169 | SpecializationUtil.registerEventListener(vehicleType, "onTurnedOff", AttacherJoints) |
170 | SpecializationUtil.registerEventListener(vehicleType, "onLeaveVehicle", AttacherJoints) |
171 | SpecializationUtil.registerEventListener(vehicleType, "onActivate", AttacherJoints) |
172 | SpecializationUtil.registerEventListener(vehicleType, "onDeactivate", AttacherJoints) |
173 | SpecializationUtil.registerEventListener(vehicleType, "onReverseDirectionChanged", AttacherJoints) |
174 | end |
registerEvents
DescriptionDefinitionregisterEvents()Code
67 | function AttacherJoints.registerEvents(vehicleType) |
68 | SpecializationUtil.registerEvent(vehicleType, "onPreAttachImplement") |
69 | SpecializationUtil.registerEvent(vehicleType, "onPostAttachImplement") |
70 | SpecializationUtil.registerEvent(vehicleType, "onPreDetachImplement") |
71 | SpecializationUtil.registerEvent(vehicleType, "onPostDetachImplement") |
72 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
76 | function AttacherJoints.registerFunctions(vehicleType) |
77 | SpecializationUtil.registerFunction(vehicleType, "saveAttachmentsToXMLFile", AttacherJoints.saveAttachmentsToXMLFile) |
78 | SpecializationUtil.registerFunction(vehicleType, "loadAttachmentsFromXMLFile", AttacherJoints.loadAttachmentsFromXMLFile) |
79 | SpecializationUtil.registerFunction(vehicleType, "handleLowerImplementEvent", AttacherJoints.handleLowerImplementEvent) |
80 | SpecializationUtil.registerFunction(vehicleType, "handleLowerImplementByAttacherJointIndex", AttacherJoints.handleLowerImplementByAttacherJointIndex) |
81 | SpecializationUtil.registerFunction(vehicleType, "getAttachedImplements", AttacherJoints.getAttachedImplements) |
82 | SpecializationUtil.registerFunction(vehicleType, "getAttacherJoints", AttacherJoints.getAttacherJoints) |
83 | SpecializationUtil.registerFunction(vehicleType, "getAttacherJointByJointDescIndex", AttacherJoints.getAttacherJointByJointDescIndex) |
84 | SpecializationUtil.registerFunction(vehicleType, "getImplementFromAttacherJointIndex", AttacherJoints.getImplementFromAttacherJointIndex) |
85 | SpecializationUtil.registerFunction(vehicleType, "getAttacherJointIndexFromObject", AttacherJoints.getAttacherJointIndexFromObject) |
86 | SpecializationUtil.registerFunction(vehicleType, "getAttacherJointDescFromObject", AttacherJoints.getAttacherJointDescFromObject) |
87 | SpecializationUtil.registerFunction(vehicleType, "getAttacherJointIndexFromImplementIndex", AttacherJoints.getAttacherJointIndexFromImplementIndex) |
88 | SpecializationUtil.registerFunction(vehicleType, "getObjectFromImplementIndex", AttacherJoints.getObjectFromImplementIndex) |
89 | SpecializationUtil.registerFunction(vehicleType, "updateAttacherJointGraphics", AttacherJoints.updateAttacherJointGraphics) |
90 | SpecializationUtil.registerFunction(vehicleType, "calculateAttacherJointMoveUpperLowerAlpha", AttacherJoints.calculateAttacherJointMoveUpperLowerAlpha) |
91 | SpecializationUtil.registerFunction(vehicleType, "updateAttacherJointRotation", AttacherJoints.updateAttacherJointRotation) |
92 | SpecializationUtil.registerFunction(vehicleType, "updateAttacherJointRotationNodes", AttacherJoints.updateAttacherJointRotationNodes) |
93 | SpecializationUtil.registerFunction(vehicleType, "attachImplement", AttacherJoints.attachImplement) |
94 | SpecializationUtil.registerFunction(vehicleType, "postAttachImplement", AttacherJoints.postAttachImplement) |
95 | SpecializationUtil.registerFunction(vehicleType, "createAttachmentJoint", AttacherJoints.createAttachmentJoint) |
96 | SpecializationUtil.registerFunction(vehicleType, "hardAttachImplement", AttacherJoints.hardAttachImplement) |
97 | SpecializationUtil.registerFunction(vehicleType, "hardDetachImplement", AttacherJoints.hardDetachImplement) |
98 | SpecializationUtil.registerFunction(vehicleType, "detachImplement", AttacherJoints.detachImplement) |
99 | SpecializationUtil.registerFunction(vehicleType, "detachImplementByObject", AttacherJoints.detachImplementByObject) |
100 | SpecializationUtil.registerFunction(vehicleType, "playAttachSound", AttacherJoints.playAttachSound) |
101 | SpecializationUtil.registerFunction(vehicleType, "playDetachSound", AttacherJoints.playDetachSound) |
102 | SpecializationUtil.registerFunction(vehicleType, "detachingIsPossible", AttacherJoints.detachingIsPossible) |
103 | SpecializationUtil.registerFunction(vehicleType, "getImplementIndexByJointDescIndex", AttacherJoints.getImplementIndexByJointDescIndex) |
104 | SpecializationUtil.registerFunction(vehicleType, "getImplementByJointDescIndex", AttacherJoints.getImplementByJointDescIndex) |
105 | SpecializationUtil.registerFunction(vehicleType, "getImplementIndexByObject", AttacherJoints.getImplementIndexByObject) |
106 | SpecializationUtil.registerFunction(vehicleType, "getImplementByObject", AttacherJoints.getImplementByObject) |
107 | SpecializationUtil.registerFunction(vehicleType, "callFunctionOnAllImplements", AttacherJoints.callFunctionOnAllImplements) |
108 | SpecializationUtil.registerFunction(vehicleType, "activateAttachments", AttacherJoints.activateAttachments) |
109 | SpecializationUtil.registerFunction(vehicleType, "deactivateAttachments", AttacherJoints.deactivateAttachments) |
110 | SpecializationUtil.registerFunction(vehicleType, "deactivateAttachmentsLights", AttacherJoints.deactivateAttachmentsLights) |
111 | SpecializationUtil.registerFunction(vehicleType, "setJointMoveDown", AttacherJoints.setJointMoveDown) |
112 | SpecializationUtil.registerFunction(vehicleType, "getIsHardAttachAllowed", AttacherJoints.getIsHardAttachAllowed) |
113 | SpecializationUtil.registerFunction(vehicleType, "loadAttacherJointFromXML", AttacherJoints.loadAttacherJointFromXML) |
114 | SpecializationUtil.registerFunction(vehicleType, "setSelectedImplementByObject", AttacherJoints.setSelectedImplementByObject) |
115 | SpecializationUtil.registerFunction(vehicleType, "getSelectedImplement", AttacherJoints.getSelectedImplement) |
116 | SpecializationUtil.registerFunction(vehicleType, "getCanToggleAttach", AttacherJoints.getCanToggleAttach) |
117 | SpecializationUtil.registerFunction(vehicleType, "startAttacherJointCombo", AttacherJoints.startAttacherJointCombo) |
118 | SpecializationUtil.registerFunction(vehicleType, "registerSelfLoweringActionEvent", AttacherJoints.registerSelfLoweringActionEvent) |
119 | end |
registerJointType
DescriptionRegistration of attacher joint typeDefinition
registerJointType(string name)Arguments
string | name | name if attacher type |
32 | function AttacherJoints.registerJointType(name) |
33 | local key = "JOINTTYPE_"..string.upper(name) |
34 | if AttacherJoints[key] == nil then |
35 | AttacherJoints.NUM_JOINTTYPES = AttacherJoints.NUM_JOINTTYPES+1 |
36 | AttacherJoints[key] = AttacherJoints.NUM_JOINTTYPES |
37 | AttacherJoints.jointTypeNameToInt[name] = AttacherJoints.NUM_JOINTTYPES |
38 | end |
39 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
123 | function AttacherJoints.registerOverwrittenFunctions(vehicleType) |
124 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "raiseActive", AttacherJoints.raiseActive) |
125 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "registerActionEvents", AttacherJoints.registerActionEvents) |
126 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "removeActionEvents", AttacherJoints.removeActionEvents) |
127 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "addToPhysics", AttacherJoints.addToPhysics) |
128 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getTotalMass", AttacherJoints.getTotalMass) |
129 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getChildVehicles", AttacherJoints.getChildVehicles) |
130 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAirConsumerUsage", AttacherJoints.getAirConsumerUsage) |
131 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "addVehicleToAIImplementList", AttacherJoints.addVehicleToAIImplementList) |
132 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "addToTotalVehicleList", AttacherJoints.addToTotalVehicleList) |
133 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDirectionSnapAngle", AttacherJoints.getDirectionSnapAngle) |
134 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAICollisionTriggers", AttacherJoints.getAICollisionTriggers) |
135 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillLevelInformation", AttacherJoints.getFillLevelInformation) |
136 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "attachableAddToolCameras", AttacherJoints.attachableAddToolCameras) |
137 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "attachableRemoveToolCameras", AttacherJoints.attachableRemoveToolCameras) |
138 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "registerSelectableObjects", AttacherJoints.registerSelectableObjects) |
139 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsReadyForAutomatedTrainTravel", AttacherJoints.getIsReadyForAutomatedTrainTravel) |
140 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadDashboardGroupFromXML", AttacherJoints.loadDashboardGroupFromXML) |
141 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsDashboardGroupActive", AttacherJoints.getIsDashboardGroupActive) |
142 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "isDetachAllowed", AttacherJoints.isDetachAllowed) |
143 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsFoldAllowed", AttacherJoints.getIsFoldAllowed) |
144 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsWheelFoliageDestructionAllowed", AttacherJoints.getIsWheelFoliageDestructionAllowed) |
145 | end |
registerSelectableObjects
DescriptionDefinitionregisterSelectableObjects()Code
2501 | function AttacherJoints:registerSelectableObjects(superFunc, selectableObjects) |
2502 | superFunc(self, selectableObjects) |
2503 | |
2504 | local spec = self.spec_attacherJoints |
2505 | for _,implement in pairs(spec.attachedImplements) do |
2506 | local object = implement.object |
2507 | if object ~= nil then |
2508 | object:registerSelectableObjects(selectableObjects) |
2509 | end |
2510 | end |
2511 | end |
registerSelfLoweringActionEvent
DescriptionDefinitionregisterSelfLoweringActionEvent()Code
1687 | function AttacherJoints:registerSelfLoweringActionEvent(actionEventsTable, inputAction, target, callback, triggerUp, triggerDown, triggerAlways, startActive, callbackState, customIconName, ignoreCollisions) |
1688 | end |
removeActionEvents
DescriptionDefinitionremoveActionEvents()Code
2325 | function AttacherJoints:removeActionEvents(superFunc) |
2326 | local spec = self.spec_attacherJoints |
2327 | |
2328 | superFunc(self) |
2329 | |
2330 | for _,implement in pairs(spec.attachedImplements) do |
2331 | if implement.object ~= nil then |
2332 | implement.object:removeActionEvents() |
2333 | end |
2334 | end |
2335 | end |
saveAttachmentsToXMLFile
DescriptionDefinitionsaveAttachmentsToXMLFile()Code
330 | function AttacherJoints:saveAttachmentsToXMLFile(xmlFile, key, vehiclesToId) |
331 | local spec = self.spec_attacherJoints |
332 | local added = false |
333 | |
334 | local id = vehiclesToId[self] |
335 | if id ~= nil then |
336 | local i = 0 |
337 | for _, implement in ipairs(spec.attachedImplements) do |
338 | local object = implement.object |
339 | if object ~= nil and vehiclesToId[object] ~= nil then |
340 | local attachmentKey = string.format("%s.attachment(%d)", key, i) |
341 | local jointDescIndex = implement.jointDescIndex |
342 | local jointDesc = spec.attacherJoints[jointDescIndex] |
343 | local inputJointDescIndex = object:getActiveInputAttacherJointDescIndex() |
344 | setXMLInt(xmlFile, attachmentKey.."#attachmentId", vehiclesToId[object]) |
345 | setXMLInt(xmlFile, attachmentKey.."#inputJointDescIndex", inputJointDescIndex) |
346 | setXMLInt(xmlFile, attachmentKey.."#jointIndex", jointDescIndex) |
347 | setXMLBool(xmlFile, attachmentKey.."#moveDown", jointDesc.moveDown) |
348 | added = true |
349 | i = i + 1 |
350 | end |
351 | end |
352 | |
353 | if added then |
354 | setXMLInt(xmlFile, key.."#rootVehicleId", id) |
355 | end |
356 | end |
357 | |
358 | return added |
359 | end |
saveToXMLFile
DescriptionDefinitionsaveToXMLFile()Code
321 | function AttacherJoints:saveToXMLFile(xmlFile, key, usedModNames) |
322 | local spec = self.spec_attacherJoints |
323 | if spec.attacherJointCombos ~= nil then |
324 | setXMLInt(xmlFile, key.."#comboDirection", spec.attacherJointCombos.direction) |
325 | end |
326 | end |
setJointMoveDown
DescriptionSet joint move downDefinition
setJointMoveDown(integer jointDescIndex, boolean moveDown, boolean noEventSend)Arguments
integer | jointDescIndex | index of joint desc |
boolean | moveDown | move down |
boolean | noEventSend | no event send |
boolean | success | success |
1862 | function AttacherJoints:setJointMoveDown(jointDescIndex, moveDown, noEventSend) |
1863 | local spec = self.spec_attacherJoints |
1864 | |
1865 | VehicleLowerImplementEvent.sendEvent(self, jointDescIndex, moveDown, noEventSend) |
1866 | local jointDesc = spec.attacherJoints[jointDescIndex] |
1867 | jointDesc.moveDown = moveDown |
1868 | |
1869 | local implementIndex = self:getImplementIndexByJointDescIndex(jointDescIndex) |
1870 | if implementIndex ~= nil then |
1871 | local implement = spec.attachedImplements[implementIndex] |
1872 | if implement.object ~= nil then |
1873 | implement.object:setLowered(moveDown) |
1874 | end |
1875 | end |
1876 | |
1877 | return true |
1878 | end |
setSelectedImplementByObject
DescriptionDefinitionsetSelectedImplementByObject()Code
1649 | function AttacherJoints:setSelectedImplementByObject(object) |
1650 | self.spec_attacherJoints.selectedImplement = self:getImplementByObject(object) |
1651 | end |
startAttacherJointCombo
DescriptionDefinitionstartAttacherJointCombo()Code
1676 | function AttacherJoints:startAttacherJointCombo(force) |
1677 | local spec = self.spec_attacherJoints |
1678 | |
1679 | if not spec.attacherJointCombos.isRunning or force then |
1680 | spec.attacherJointCombos.direction = -spec.attacherJointCombos.direction |
1681 | spec.attacherJointCombos.isRunning = true |
1682 | end |
1683 | end |
updateAttacherJointGraphics
DescriptionUpdate attacher joint graphicsDefinition
updateAttacherJointGraphics(table implement, float dt)Arguments
table | implement | implement |
float | dt | time since last call in ms |
860 | function AttacherJoints:updateAttacherJointGraphics(implement, dt) |
861 | local spec = self.spec_attacherJoints |
862 | |
863 | if implement.object ~= nil then |
864 | local jointDesc = spec.attacherJoints[implement.jointDescIndex] |
865 | |
866 | local attacherJoint = implement.object:getActiveInputAttacherJoint() |
867 | |
868 | if jointDesc.topArm ~= nil and attacherJoint.topReferenceNode ~= nil then |
869 | local ax, ay, az = getWorldTranslation(jointDesc.topArm.rotationNode) |
870 | local bx, by, bz = getWorldTranslation(attacherJoint.topReferenceNode) |
871 | |
872 | local x, y, z = worldDirectionToLocal(getParent(jointDesc.topArm.rotationNode), bx-ax, by-ay, bz-az) |
873 | local distance = MathUtil.vector3Length(x,y,z) |
874 | |
875 | local _, upY, upZ = 0,1,0 |
876 | if math.abs(y) > 0.99*distance then |
877 | -- direction and up is parallel |
878 | upY = 0 |
879 | if y > 0 then |
880 | upZ = 1 |
881 | else |
882 | upZ = -1 |
883 | end |
884 | end |
885 | |
886 | -- different approach I) rotate actual direction of topArm by 90degree around x-axis |
887 | local alpha = math.rad(-90) |
888 | -- check if rotationNode is at back of tractor => inverted rotation direction, could be dismissed by rotating TG in i3d |
889 | local px,py,pz = getWorldTranslation(jointDesc.topArm.rotationNode) |
890 | local _,_,lz = worldToLocal(self.components[1].node, px,py,pz) |
891 | if lz < 0 then |
892 | alpha = math.rad(90) |
893 | end |
894 | |
895 | local dx, dy, dz = localDirectionToWorld(jointDesc.topArm.rotationNode, 0,0,1) |
896 | dx, dy, dz = worldDirectionToLocal(getParent(jointDesc.topArm.rotationNode), dx, dy, dz) |
897 | local upX = dx |
898 | local upY = math.cos(alpha)*dy - math.sin(alpha)*dz |
899 | local upZ = math.sin(alpha)*dy + math.cos(alpha)*dz |
900 | |
901 | setDirection(jointDesc.topArm.rotationNode, x*jointDesc.topArm.zScale, y*jointDesc.topArm.zScale, z*jointDesc.topArm.zScale, upX, upY, upZ) |
902 | if jointDesc.topArm.translationNode ~= nil and not implement.attachingIsInProgress then |
903 | local translation = (distance-jointDesc.topArm.referenceDistance) |
904 | setTranslation(jointDesc.topArm.translationNode, 0, 0, translation*jointDesc.topArm.zScale) |
905 | if jointDesc.topArm.scaleNode ~= nil then |
906 | setScale(jointDesc.topArm.scaleNode, 1, 1, math.max((translation+jointDesc.topArm.scaleReferenceDistance)/jointDesc.topArm.scaleReferenceDistance, 0)) |
907 | end |
908 | end |
909 | end |
910 | if jointDesc.bottomArm ~= nil then |
911 | local ax, ay, az = getWorldTranslation(jointDesc.bottomArm.rotationNode) |
912 | local bx, by, bz = getWorldTranslation(attacherJoint.node) |
913 | |
914 | local x, y, z = worldDirectionToLocal(getParent(jointDesc.bottomArm.rotationNode), bx-ax, by-ay, bz-az) |
915 | local distance = MathUtil.vector3Length(x,y,z) |
916 | local upX, upY, upZ = 0,1,0 |
917 | if math.abs(y) > 0.99*distance then |
918 | -- direction and up is parallel |
919 | upY = 0 |
920 | if y > 0 then |
921 | upZ = 1 |
922 | else |
923 | upZ = -1 |
924 | end |
925 | end |
926 | local dirX = 0 |
927 | if not jointDesc.bottomArm.lockDirection then |
928 | dirX = x*jointDesc.bottomArm.zScale |
929 | end |
930 | if math.abs(jointDesc.bottomArm.lastDirection[1] - dirX) > 0.001 or |
931 | math.abs(jointDesc.bottomArm.lastDirection[2] - y*jointDesc.bottomArm.zScale) > 0.001 or |
932 | math.abs(jointDesc.bottomArm.lastDirection[3] - z*jointDesc.bottomArm.zScale) > 0.001 then |
933 | setDirection(jointDesc.bottomArm.rotationNode, dirX, y*jointDesc.bottomArm.zScale, z*jointDesc.bottomArm.zScale, upX, upY, upZ) |
934 | |
935 | jointDesc.bottomArm.lastDirection[1] = dirX |
936 | jointDesc.bottomArm.lastDirection[2] = y*jointDesc.bottomArm.zScale |
937 | jointDesc.bottomArm.lastDirection[3] = z*jointDesc.bottomArm.zScale |
938 | end |
939 | |
940 | if jointDesc.bottomArm.translationNode ~= nil and not implement.attachingIsInProgress then |
941 | setTranslation(jointDesc.bottomArm.translationNode, 0, 0, (distance-jointDesc.bottomArm.referenceDistance)*jointDesc.bottomArm.zScale) |
942 | end |
943 | if self.setMovingToolDirty ~= nil then |
944 | self:setMovingToolDirty(jointDesc.bottomArm.rotationNode) |
945 | end |
946 | |
947 | if attacherJoint.needsToolbar and jointDesc.bottomArm.toolbar ~= nil then |
948 | local parent = getParent(jointDesc.bottomArm.toolbar) |
949 | |
950 | local _, yDir, zDir = localDirectionToLocal(attacherJoint.node, jointDesc.rootNode, 1, 0, 0) |
951 | local xDir, yDir, zDir = localDirectionToLocal(jointDesc.rootNode, parent, 0, yDir, zDir) |
952 | |
953 | local _, yUp, zUp = localDirectionToLocal(attacherJoint.node, jointDesc.rootNode, 0, 1, 0) |
954 | local xUp, yUp, zUp = localDirectionToLocal(jointDesc.rootNode, parent, 0, yUp, zUp) |
955 | |
956 | setDirection(jointDesc.bottomArm.toolbar, xDir, yDir, zDir, xUp, yUp, zUp) |
957 | end |
958 | end |
959 | end |
960 | end |
updateAttacherJointRotation
DescriptionUpdate attacher joint rotations depending on move alphaDefinition
updateAttacherJointRotation(table jointDesc, table object)Arguments
table | jointDesc | joint desc of used attacher |
table | object | object of attached vehicle |
1015 | function AttacherJoints:updateAttacherJointRotation(jointDesc, object) |
1016 | local objectAtttacherJoint = object.spec_attachable.attacherJoint |
1017 | |
1018 | -- rotate attacher such that |
1019 | local targetRot = MathUtil.lerp(objectAtttacherJoint.upperRotationOffset, objectAtttacherJoint.lowerRotationOffset, jointDesc.moveAlpha) |
1020 | local curRot = MathUtil.lerp(jointDesc.upperRotationOffset, jointDesc.lowerRotationOffset, jointDesc.moveAlpha) |
1021 | local rotDiff = targetRot - curRot |
1022 | |
1023 | setRotation(jointDesc.jointTransform, unpack(jointDesc.jointOrigRot)) |
1024 | rotateAboutLocalAxis(jointDesc.jointTransform, rotDiff, 0, 0, 1) |
1025 | end |
updateAttacherJointRotationNodes
DescriptionDefinitionupdateAttacherJointRotationNodes()Code
1029 | function AttacherJoints:updateAttacherJointRotationNodes(jointDesc, alpha) |
1030 | if jointDesc.rotationNode ~= nil then |
1031 | setRotation(jointDesc.rotationNode, MathUtil.vector3ArrayLerp(jointDesc.upperRotation, jointDesc.lowerRotation, alpha)) |
1032 | end |
1033 | if jointDesc.rotationNode2 ~= nil then |
1034 | setRotation(jointDesc.rotationNode2, MathUtil.vector3ArrayLerp(jointDesc.upperRotation2, jointDesc.lowerRotation2, alpha)) |
1035 | end |
1036 | end |