1282 | function BaleWrapper:doStateChange(id, nearestBaleServerId) |
1283 | local spec = self.spec_baleWrapper |
1284 | |
1285 | if id == BaleWrapper.CHANGE_WRAPPING_START or (spec.baleWrapperState ~= BaleWrapper.STATE_WRAPPER_FINSIHED and id == BaleWrapper.CHANGE_WRAPPER_START_DROP_BALE) then |
1286 | local bale = NetworkUtil.getObject(spec.currentWrapper.currentBale) |
1287 | local baleType = spec.currentWrapper.allowedBaleTypes[spec.currentBaleTypeIndex] |
1288 | if not bale:getSupportsWrapping() or baleType.skipWrapping or bale.wrappingState == 1 then |
1289 | if self.isServer then |
1290 | spec.setWrappingStateFinished = true |
1291 | end |
1292 | |
1293 | return |
1294 | end |
1295 | end |
1296 | |
1297 | if id == BaleWrapper.CHANGE_GRAB_BALE then |
1298 | local bale = NetworkUtil.getObject(nearestBaleServerId) |
1299 | spec.baleGrabber.currentBale = nearestBaleServerId |
1300 | if bale ~= nil then |
1301 | local x,y,z = localToLocal(bale.nodeId, getParent(spec.baleGrabber.grabNode), 0,0,0) |
1302 | setTranslation(spec.baleGrabber.grabNode, x,y,z) |
1303 | bale:mountKinematic(self, spec.baleGrabber.grabNode, 0,0,0, 0,0,0) |
1304 | bale:setCanBeSold(false) |
1305 | spec.baleToMount = nil |
1306 | self:playMoveToWrapper(bale) |
1307 | else |
1308 | spec.baleToMount = {serverId=nearestBaleServerId, linkNode=spec.baleGrabber.grabNode, trans={0,0,0}, rot={0,0,0} } |
1309 | end |
1310 | spec.baleWrapperState = BaleWrapper.STATE_MOVING_BALE_TO_WRAPPER |
1311 | |
1312 | elseif id == BaleWrapper.CHANGE_DROP_BALE_AT_GRABBER then |
1313 | -- drop bale at wrapper |
1314 | local attachNode = spec.currentWrapper.baleNode |
1315 | local bale = NetworkUtil.getObject(spec.baleGrabber.currentBale) |
1316 | if bale ~= nil then |
1317 | bale:mountKinematic(self, attachNode, 0,0,0, 0,0,0) |
1318 | bale:setCanBeSold(false) |
1319 | spec.baleToMount = nil |
1320 | else |
1321 | spec.baleToMount = {serverId=spec.baleGrabber.currentBale, linkNode=attachNode, trans={0,0,0}, rot={0,0,0} } |
1322 | end |
1323 | self:updateWrapNodes(true, false, 0) |
1324 | |
1325 | spec.currentWrapper.currentBale = spec.baleGrabber.currentBale |
1326 | spec.baleGrabber.currentBale = nil |
1327 | |
1328 | if spec.currentWrapper.animations["moveToWrapper"].animName ~= nil then |
1329 | if spec.currentWrapper.animations["moveToWrapper"].reverseAfterMove then |
1330 | self:playAnimation(spec.currentWrapper.animations["moveToWrapper"].animName, -spec.currentWrapper.animations["moveToWrapper"].animSpeed, nil, true) |
1331 | end |
1332 | end |
1333 | |
1334 | spec.baleWrapperState = BaleWrapper.STATE_MOVING_GRABBER_TO_WORK |
1335 | |
1336 | elseif id == BaleWrapper.CHANGE_WRAPPING_START then |
1337 | |
1338 | spec.baleWrapperState = BaleWrapper.STATE_WRAPPER_WRAPPING_BALE |
1339 | if self.isClient then |
1340 | g_soundManager:playSample(spec.currentWrapper.samples.start) |
1341 | g_soundManager:playSample(spec.currentWrapper.samples.wrap, 0, spec.currentWrapper.samples.start) |
1342 | end |
1343 | |
1344 | if spec.currentWrapper.animations["wrapBale"].animName ~= nil then |
1345 | self:playAnimation(spec.currentWrapper.animations["wrapBale"].animName, spec.currentWrapper.animations["wrapBale"].animSpeed, nil, true) |
1346 | end |
1347 | elseif id == BaleWrapper.CHANGE_WRAPPING_BALE_FINSIHED then |
1348 | |
1349 | if self.isClient then |
1350 | g_soundManager:stopSample(spec.currentWrapper.samples.wrap) |
1351 | g_soundManager:stopSample(spec.currentWrapper.samples.stop) |
1352 | if spec.currentWrapper.wrappingSoundEndTime == 1 then |
1353 | g_soundManager:playSample(spec.currentWrapper.samples.stop) |
1354 | end |
1355 | |
1356 | -- if the start sound is still playing (e.g. on loading if the wrapping state is directly set to 1) we stop it |
1357 | if g_soundManager:getIsSamplePlaying(spec.currentWrapper.samples.start) then |
1358 | g_soundManager:stopSample(spec.currentWrapper.samples.start) |
1359 | end |
1360 | end |
1361 | |
1362 | self:updateWrappingState(1, true) |
1363 | spec.baleWrapperState = BaleWrapper.STATE_WRAPPER_FINSIHED |
1364 | |
1365 | local bale = NetworkUtil.getObject(spec.currentWrapper.currentBale) |
1366 | local baleType = spec.currentWrapper.allowedBaleTypes[spec.currentBaleTypeIndex] |
1367 | local skippedWrapping = not bale:getSupportsWrapping() or baleType.skipWrapping |
1368 | if skippedWrapping or bale.wrappingState == 1 then |
1369 | self:updateWrappingState(0, true) |
1370 | end |
1371 | |
1372 | if not skippedWrapping then |
1373 | local animation = spec.currentWrapper.animations["resetWrapping"] |
1374 | if animation.animName ~= nil then |
1375 | self:playAnimation(animation.animName, animation.animSpeed, nil, true) |
1376 | end |
1377 | end |
1378 | elseif id == BaleWrapper.CHANGE_WRAPPER_START_DROP_BALE then |
1379 | |
1380 | self:updateWrapNodes(false, false, 0) |
1381 | if spec.currentWrapper.animations["dropFromWrapper"].animName ~= nil then |
1382 | self:playAnimation(spec.currentWrapper.animations["dropFromWrapper"].animName, spec.currentWrapper.animations["dropFromWrapper"].animSpeed, nil, true) |
1383 | end |
1384 | spec.baleWrapperState = BaleWrapper.STATE_WRAPPER_DROPPING_BALE |
1385 | elseif id == BaleWrapper.CHANGE_WRAPPER_BALE_DROPPED then |
1386 | |
1387 | local bale = NetworkUtil.getObject(spec.currentWrapper.currentBale) |
1388 | if bale ~= nil then |
1389 | bale:unmountKinematic() |
1390 | bale:setCanBeSold(true) |
1391 | |
1392 | local baleType = spec.currentWrapper.allowedBaleTypes[spec.currentBaleTypeIndex] |
1393 | if bale:getSupportsWrapping() and not baleType.skipWrapping then |
1394 | |
1395 | local stats = g_currentMission:farmStats(self:getOwnerFarmId()) |
1396 | local total = stats:updateStats("wrappedBales", 1) |
1397 | g_achievementManager:tryUnlock("WrappedBales", total) |
1398 | |
1399 | if bale.wrappingState < 1 then |
1400 | bale:setWrappingState(1) |
1401 | end |
1402 | end |
1403 | end |
1404 | spec.lastDroppedBale = bale |
1405 | spec.currentWrapper.currentBale = nil |
1406 | spec.currentWrapper.currentTime = 0 |
1407 | if spec.currentWrapper.animations["resetAfterDrop"].animName ~= nil then |
1408 | self:playAnimation(spec.currentWrapper.animations["resetAfterDrop"].animName, spec.currentWrapper.animations["resetAfterDrop"].animSpeed, nil, true) |
1409 | end |
1410 | |
1411 | -- reapply wrapper type to reset the wrapper again to initial state |
1412 | self:setBaleWrapperType(spec.currentWrapper == spec.roundBaleWrapper, spec.currentBaleTypeIndex) |
1413 | |
1414 | spec.baleWrapperState = BaleWrapper.STATE_WRAPPER_RESETTING_PLATFORM |
1415 | |
1416 | elseif id == BaleWrapper.CHANGE_WRAPPER_PLATFORM_RESET then |
1417 | |
1418 | self:updateWrappingState(0) |
1419 | self:updateWrapNodes(false, true, 0) |
1420 | spec.baleWrapperState = BaleWrapper.STATE_NONE |
1421 | |
1422 | elseif id == BaleWrapper.CHANGE_BUTTON_EMPTY then |
1423 | |
1424 | -- Server only code |
1425 | assert(self.isServer) |
1426 | if spec.baleWrapperState == BaleWrapper.STATE_WRAPPER_FINSIHED then |
1427 | g_server:broadcastEvent(BaleWrapperStateEvent.new(self, BaleWrapper.CHANGE_WRAPPER_START_DROP_BALE), true, nil, self) |
1428 | end |
1429 | |
1430 | end |
1431 | end |
50 | function BaleWrapper.initSpecialization() |
51 | g_configurationManager:addConfigurationType("wrappingColor", g_i18n:getText("configuration_wrappingColor"), nil, nil, ConfigurationUtil.getConfigColorSingleItemLoad, ConfigurationUtil.getConfigColorPostLoad, ConfigurationUtil.SELECTOR_COLOR) |
52 | g_configurationManager:addConfigurationType("wrappingAnimation", g_i18n:getText("configuration_wrappingAnimation"), "baleWrapper", nil, nil, nil, ConfigurationUtil.SELECTOR_MULTIOPTION) |
53 | |
54 | g_storeManager:addSpecType("baleWrapperBaleSizeRound", "shopListAttributeIconBaleWrapperBaleSizeRound", BaleWrapper.loadSpecValueBaleSizeRound, BaleWrapper.getSpecValueBaleSizeRound, "vehicle") |
55 | g_storeManager:addSpecType("baleWrapperBaleSizeSquare", "shopListAttributeIconBaleWrapperBaleSizeSquare", BaleWrapper.loadSpecValueBaleSizeSquare, BaleWrapper.getSpecValueBaleSizeSquare, "vehicle") |
56 | |
57 | local schema = Vehicle.xmlSchema |
58 | schema:setXMLSpecializationType("BaleWrapper") |
59 | ConfigurationUtil.registerColorConfigurationXMLPaths(schema, "wrappingColor") |
60 | BaseMaterial.registerBaseMaterialConfigurationsXMLPaths(schema, "wrappingColor") |
61 | |
62 | schema:register(XMLValueType.FLOAT, "vehicle.baleWrapper#foldMinLimit", "Fold min limit (Allow grabbing if folding is between these values)", 0) |
63 | schema:register(XMLValueType.FLOAT, "vehicle.baleWrapper#foldMaxLimit", "Fold max limit (Allow grabbing if folding is between these values)", 1) |
64 | schema:register(XMLValueType.NODE_INDEX, "vehicle.baleWrapper.grabber#node", "Grabber node") |
65 | schema:register(XMLValueType.NODE_INDEX, "vehicle.baleWrapper.grabber#triggerNode", "Grabber trigger node") |
66 | schema:register(XMLValueType.FLOAT, "vehicle.baleWrapper.grabber#nearestDistance", "Distance to bale to grab it", 3.0) |
67 | |
68 | schema:register(XMLValueType.BOOL, "vehicle.baleWrapper.automaticDrop#enabled", "Automatic drop", "true on mobile") |
69 | schema:register(XMLValueType.BOOL, "vehicle.baleWrapper.automaticDrop#toggleable", "Automatic bale drop can be toggled", "false on mobile") |
70 | schema:register(XMLValueType.L10N_STRING, "vehicle.baleWrapper.automaticDrop#textPos", "Positive toggle automatic drop text", "action_toggleAutomaticBaleDropPos") |
71 | schema:register(XMLValueType.L10N_STRING, "vehicle.baleWrapper.automaticDrop#textNeg", "Negative toggle automatic drop text", "action_toggleAutomaticBaleDropNeg") |
72 | |
73 | BaleWrapper.registerWrapperXMLPaths(schema, "vehicle.baleWrapper.roundBaleWrapper") |
74 | BaleWrapper.registerWrapperXMLPaths(schema, "vehicle.baleWrapper.squareBaleWrapper") |
75 | |
76 | local configKey = "vehicle.baleWrapper.wrappingAnimationConfigurations.wrappingAnimationConfiguration(?)" |
77 | for i=1, #BaleWrapper.ANIMATION_NAMES do |
78 | BaleWrapper.registerWrapperAnimationXMLPaths(schema, configKey .. ".roundBaleWrapper", BaleWrapper.ANIMATION_NAMES[i]) |
79 | BaleWrapper.registerWrapperAnimationXMLPaths(schema, configKey .. ".roundBaleWrapper.baleTypes.baleType(?)", BaleWrapper.ANIMATION_NAMES[i]) |
80 | BaleWrapper.registerWrapperAnimationXMLPaths(schema, configKey .. ".squareBaleWrapper", BaleWrapper.ANIMATION_NAMES[i]) |
81 | BaleWrapper.registerWrapperAnimationXMLPaths(schema, configKey .. ".squareBaleWrapper.baleTypes.baleType(?)", BaleWrapper.ANIMATION_NAMES[i]) |
82 | end |
83 | |
84 | ObjectChangeUtil.registerObjectChangeXMLPaths(schema, configKey) |
85 | |
86 | schema:setXMLSpecializationType() |
87 | |
88 | local schemaSavegame = Vehicle.xmlSchemaSavegame |
89 | schemaSavegame:register(XMLValueType.FLOAT, "vehicles.vehicle(?).baleWrapper#wrapperTime", "Bale wrapping time", 0) |
90 | Bale.registerSavegameXMLPaths(schemaSavegame, "vehicles.vehicle(?).baleWrapper.bale") |
91 | end |
560 | function BaleWrapper:loadWrapperAnimationNodesFromXML(target, xmlFile, baseKey, animTime) |
561 | local maxTime = xmlFile:getValue(baseKey .. ".wrappingAnimationNodes#maxTime", animTime / 1000) |
562 | |
563 | target.wrappingAnimationNodes = {} |
564 | target.wrappingAnimationNodes.nodes = {} |
565 | target.wrappingAnimationNodes.nodeToRootNode = {} |
566 | |
567 | xmlFile:iterate(baseKey ..".wrappingAnimationNodes.key", function(index, wrappingAnimationNodeKey) |
568 | local time = xmlFile:getValue(wrappingAnimationNodeKey.."#time") |
569 | local nodeId = xmlFile:getValue(wrappingAnimationNodeKey.."#node", nil, self.components, self.i3dMappings) |
570 | local rootNode = xmlFile:getValue(wrappingAnimationNodeKey.."#rootNode", nil, self.components, self.i3dMappings) |
571 | local linkNode = xmlFile:getValue(wrappingAnimationNodeKey.."#linkNode", nil, self.components, self.i3dMappings) |
572 | |
573 | if time ~= nil and nodeId ~= nil then |
574 | local entry = {} |
575 | entry.time = time / maxTime |
576 | entry.nodeId = nodeId |
577 | entry.linkNode = linkNode |
578 | entry.parent = getParent(nodeId) |
579 | |
580 | entry.translation = xmlFile:getValue(wrappingAnimationNodeKey.."#translation", nil, true) |
581 | |
582 | if rootNode ~= nil then |
583 | target.wrappingAnimationNodes.nodeToRootNode[nodeId] = rootNode |
584 | end |
585 | |
586 | table.insert(target.wrappingAnimationNodes.nodes, entry) |
587 | end |
588 | end) |
589 | |
590 | -- set start translations in a second loop since we link some of the nodes and this would break the index paths |
591 | for j = 1, #target.wrappingAnimationNodes.nodes do |
592 | local wrappingAnimationNode = target.wrappingAnimationNodes.nodes[j] |
593 | if wrappingAnimationNode.time == 0 then |
594 | setTranslation(wrappingAnimationNode.nodeId, unpack(wrappingAnimationNode.translation)) |
595 | |
596 | if wrappingAnimationNode.linkNode ~= nil then |
597 | local x, y, z = localToWorld(wrappingAnimationNode.parent, unpack(wrappingAnimationNode.translation)) |
598 | link(wrappingAnimationNode.linkNode, wrappingAnimationNode.nodeId) |
599 | setWorldTranslation(wrappingAnimationNode.nodeId, x, y, z) |
600 | end |
601 | end |
602 | end |
603 | |
604 | target.wrappingAnimationNodes.referenceNode = xmlFile:getValue(baseKey .. ".wrappingAnimationNodes#referenceNode", nil, self.components, self.i3dMappings) |
605 | target.wrappingAnimationNodes.referenceAxis = xmlFile:getValue(baseKey .. ".wrappingAnimationNodes#referenceAxis", 2) |
606 | target.wrappingAnimationNodes.referenceMinRot = xmlFile:getValue(baseKey .. ".wrappingAnimationNodes#minRot", 0) |
607 | target.wrappingAnimationNodes.referenceMaxRot = xmlFile:getValue(baseKey .. ".wrappingAnimationNodes#maxRot", 0) |
608 | if target.wrappingAnimationNodes.referenceNode ~= nil then |
609 | target.wrappingAnimationNodes.referenceNodeRotation = {getRotation(target.wrappingAnimationNodes.referenceNode)} |
610 | end |
611 | target.wrappingAnimationNodes.lastTime = -1 |
612 | |
613 | target.wrappingAnimationNodes.currentIndex = 0 |
614 | end |
482 | function BaleWrapper:loadWrapperAnimNodesFromXML(target, xmlFile, baseKey) |
483 | target.wrapAnimNodes = {} |
484 | xmlFile:iterate(baseKey .. ".wrapAnimNodes.wrapAnimNode", function(index, key) |
485 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#index", key.."#node") --FS19 to FS22 |
486 | |
487 | local wrapAnimNode = {} |
488 | wrapAnimNode.nodeId = xmlFile:getValue(key.."#node", nil, self.components, self.i3dMappings) |
489 | if wrapAnimNode.nodeId ~= nil then |
490 | wrapAnimNode.useWrapperRot = false |
491 | wrapAnimNode.animCurve = AnimCurve.new(linearInterpolatorN) |
492 | |
493 | local numKeyframes = 0 |
494 | xmlFile:iterate(key..".key", function(_, nodeKey) |
495 | local wrapperRot = xmlFile:getValue(nodeKey.."#wrapperRot") |
496 | local wrapperTime = xmlFile:getValue(nodeKey.."#wrapperTime") |
497 | if wrapperRot == nil and wrapperTime == nil then |
498 | return false |
499 | end |
500 | wrapAnimNode.useWrapperRot = wrapperRot ~= nil |
501 | |
502 | local x, y, z = xmlFile:getValue(nodeKey.."#trans", "0 0 0") |
503 | local rx, ry, rz = xmlFile:getValue(nodeKey.."#rot", "0 0 0") |
504 | local sx, sy, sz = xmlFile:getValue(nodeKey.."#scale", "1 1 1") |
505 | |
506 | if wrapperRot ~= nil then |
507 | wrapAnimNode.animCurve:addKeyframe({x, y, z, rx, ry, rz, sx,sy,sz, time = math.rad(wrapperRot)}) |
508 | else |
509 | wrapAnimNode.animCurve:addKeyframe({x, y, z, rx, ry, rz, sx,sy,sz, time = wrapperTime}) |
510 | end |
511 | |
512 | numKeyframes = numKeyframes + 1 |
513 | end) |
514 | |
515 | if numKeyframes > 0 then |
516 | wrapAnimNode.repeatWrapperRot = xmlFile:getValue(key.."#repeatWrapperRot", false) |
517 | wrapAnimNode.normalizeRotationOnBaleDrop = xmlFile:getValue(key.."#normalizeRotationOnBaleDrop", 0) |
518 | table.insert(target.wrapAnimNodes, wrapAnimNode) |
519 | end |
520 | end |
521 | end) |
522 | end |
618 | function BaleWrapper:loadWrapperFoilAnimationFromXML(target, xmlFile, baseKey, isDefault) |
619 | local wrappingFoilAnimation = {} |
620 | wrappingFoilAnimation.referenceNode = xmlFile:getValue(baseKey .. ".wrappingFoilAnimation#referenceNode", nil, self.components, self.i3dMappings) |
621 | if wrappingFoilAnimation.referenceNode ~= nil then |
622 | wrappingFoilAnimation.referenceAxis = xmlFile:getValue(baseKey .. ".wrappingFoilAnimation#referenceAxis", 2) |
623 | wrappingFoilAnimation.referenceMinRot = xmlFile:getValue(baseKey .. ".wrappingFoilAnimation#minRot", 0) |
624 | wrappingFoilAnimation.referenceMaxRot = xmlFile:getValue(baseKey .. ".wrappingFoilAnimation#maxRot", 0) |
625 | wrappingFoilAnimation.referenceNodeRotation = {0, 0, 0} |
626 | |
627 | wrappingFoilAnimation.clipNode = xmlFile:getValue(baseKey .. ".wrappingFoilAnimation#clipNode", nil, self.components, self.i3dMappings) |
628 | if wrappingFoilAnimation.clipNode ~= nil then |
629 | wrappingFoilAnimation.animationClip = xmlFile:getValue(baseKey .. ".wrappingFoilAnimation#clipName") |
630 | if wrappingFoilAnimation.animationClip ~= nil then |
631 | wrappingFoilAnimation.animationCharSet = getAnimCharacterSet(wrappingFoilAnimation.clipNode) |
632 | wrappingFoilAnimation.animationClipIndex = getAnimClipIndex(wrappingFoilAnimation.animationCharSet, wrappingFoilAnimation.animationClip) |
633 | if wrappingFoilAnimation.animationClipIndex >= 0 then |
634 | wrappingFoilAnimation.animationClipDuration = getAnimClipDuration(wrappingFoilAnimation.animationCharSet, wrappingFoilAnimation.animationClipIndex) |
635 | |
636 | if isDefault then |
637 | clearAnimTrackClip(wrappingFoilAnimation.animationCharSet, 0) |
638 | assignAnimTrackClip(wrappingFoilAnimation.animationCharSet, 0, wrappingFoilAnimation.animationClipIndex) |
639 | |
640 | enableAnimTrack(wrappingFoilAnimation.animationCharSet, 0) |
641 | setAnimTrackTime(wrappingFoilAnimation.animationCharSet, 0, 0, true) |
642 | disableAnimTrack(wrappingFoilAnimation.animationCharSet, 0) |
643 | end |
644 | |
645 | wrappingFoilAnimation.lastTime = 0 |
646 | |
647 | target.wrappingFoilAnimation = wrappingFoilAnimation |
648 | else |
649 | Logging.xmlWarning(self.xmlFile, "Unable to find animation clip '%s' on node '%s' in '%s'", wrappingFoilAnimation.animationClip, getName(wrappingFoilAnimation.clipNode), baseKey..".wrappingFoilAnimation") |
650 | end |
651 | else |
652 | Logging.xmlWarning(self.xmlFile, "Missing clipName for foil animation '%s'", baseKey..".wrappingFoilAnimation") |
653 | end |
654 | else |
655 | Logging.xmlWarning(self.xmlFile, "Missing clipNode for foil animation '%s'", baseKey..".wrappingFoilAnimation") |
656 | end |
657 | end |
658 | end |
339 | function BaleWrapper:loadWrapperFromXML(wrapper, xmlFile, baseKey, wrapperName) |
340 | local spec = self.spec_baleWrapper |
341 | local isRoundBaleWrapper = wrapper == spec.roundBaleWrapper |
342 | |
343 | local wrappingAnimationConfig = Utils.getNoNil(self.configurations["wrappingAnimation"], 1) |
344 | local configKey = string.format("vehicle.baleWrapper.wrappingAnimationConfigurations.wrappingAnimationConfiguration(%d)", wrappingAnimationConfig - 1) |
345 | |
346 | self:loadWrapperAnimationsFromXML(wrapper, xmlFile, baseKey, configKey, "." .. wrapperName .. ".animations") |
347 | |
348 | wrapper.defaultAnimations = wrapper.animations |
349 | |
350 | baseKey = baseKey .. "." .. wrapperName |
351 | |
352 | wrapper.baleNode = xmlFile:getValue(baseKey .. "#baleNode", nil, self.components, self.i3dMappings) |
353 | wrapper.wrapperNode = xmlFile:getValue(baseKey .. "#wrapperNode", nil, self.components, self.i3dMappings) |
354 | wrapper.wrapperRotAxis = xmlFile:getValue(baseKey.."#wrapperRotAxis", 2) |
355 | |
356 | wrapper.animTime = xmlFile:getValue(baseKey .. "#wrappingTime", 5) * 1000 |
357 | wrapper.currentTime = 0 |
358 | wrapper.currentBale = nil |
359 | |
360 | wrapper.allowedBaleTypes = {} |
361 | xmlFile:iterate(baseKey .. ".baleTypes.baleType", function(index, key) |
362 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#fillType") --FS19 to FS22 |
363 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#wrapperBaleFilename") --FS19 to FS22 |
364 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#minBaleDiameter", key.."#diameter") --FS19 to FS22 |
365 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#maxBaleDiameter", key.."#diameter") --FS19 to FS22 |
366 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#minBaleWidth", key.."#width") --FS19 to FS22 |
367 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#maxBaleWidth", key.."#width") --FS19 to FS22 |
368 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#minBaleHeight", key.."#height") --FS19 to FS22 |
369 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#maxBaleHeight", key.."#height") --FS19 to FS22 |
370 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#minBaleLength", key.."#length") --FS19 to FS22 |
371 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, key.."#maxBaleLength", key.."#length") --FS19 to FS22 |
372 | |
373 | local baleType = {} |
374 | baleType.diameter = MathUtil.round(xmlFile:getValue(key.."#diameter", 0), 2) |
375 | baleType.width = MathUtil.round(xmlFile:getValue(key.."#width", 0), 2) |
376 | baleType.height = MathUtil.round(xmlFile:getValue(key.."#height", 0), 2) |
377 | baleType.length = MathUtil.round(xmlFile:getValue(key.."#length", 0), 2) |
378 | |
379 | baleType.wrapDiffuse = xmlFile:getValue(key..".textures#diffuse") |
380 | if baleType.wrapDiffuse ~= nil then |
381 | baleType.wrapDiffuse = Utils.getFilename(baleType.wrapDiffuse, self.baseDirectory) |
382 | end |
383 | |
384 | baleType.wrapNormal = xmlFile:getValue(key..".textures#normal") |
385 | if baleType.wrapNormal ~= nil then |
386 | baleType.wrapNormal = Utils.getFilename(baleType.wrapNormal, self.baseDirectory) |
387 | end |
388 | |
389 | self:loadWrapperAnimationsFromXML(baleType, xmlFile, key, string.format("%s.%s.baleTypes.baleType(%d)", configKey, wrapperName, index - 1), ".animations", wrapper.animations) |
390 | self:loadWrapperFoilAnimationFromXML(baleType, xmlFile, key) |
391 | |
392 | baleType.changeObjects = {} |
393 | ObjectChangeUtil.loadObjectChangeFromXML(self.xmlFile, key, baleType.changeObjects, self.components, self) |
394 | |
395 | baleType.skipWrapping = xmlFile:getValue(key.."#skipWrapping", false) |
396 | |
397 | baleType.forceWhileFolding = xmlFile:getValue(key.."#forceWhileFolding", false) |
398 | if baleType.forceWhileFolding then |
399 | spec.foldedBaleType = {isRoundBaleWrapper=isRoundBaleWrapper, baleTypeIndex=index} |
400 | end |
401 | |
402 | self:loadWrapperStateCurveFromXML(baleType, xmlFile, key) |
403 | |
404 | table.insert(wrapper.allowedBaleTypes, baleType) |
405 | end) |
406 | |
407 | self:loadWrapperAnimCurveFromXML(wrapper, xmlFile, baseKey) |
408 | self:loadWrapperAnimNodesFromXML(wrapper, xmlFile, baseKey) |
409 | |
410 | self:loadWrapperWrapNodesFromXML(wrapper, xmlFile, baseKey) |
411 | self:loadWrapperStateCurveFromXML(wrapper, xmlFile, baseKey) |
412 | self:loadWrapperAnimationNodesFromXML(wrapper, xmlFile, baseKey, wrapper.animTime) |
413 | self:loadWrapperFoilAnimationFromXML(wrapper, xmlFile, baseKey, true) |
414 | wrapper.wrappingFoilAnimationDefault = wrapper.wrappingFoilAnimation |
415 | |
416 | local defaultText = (isRoundBaleWrapper and "action_unloadRoundBale") or "action_unloadSquareBale" |
417 | wrapper.unloadBaleText = xmlFile:getValue(baseKey .. "#unloadBaleText", defaultText, self.customEnvironment) |
418 | |
419 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, baseKey.."#skipWrappingFillTypes", baseKey.."#skipUnsupportedBales") --FS19 to FS22 |
420 | wrapper.skipUnsupportedBales = self.xmlFile:getValue(baseKey.."#skipUnsupportedBales", false) |
421 | |
422 | if self.isClient then |
423 | wrapper.samples = {} |
424 | wrapper.samples.wrap = g_soundManager:loadSampleFromXML(self.xmlFile, baseKey..".sounds", "wrap", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self) |
425 | wrapper.samples.start = g_soundManager:loadSampleFromXML(self.xmlFile, baseKey..".sounds", "start", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
426 | wrapper.samples.stop = g_soundManager:loadSampleFromXML(self.xmlFile, baseKey..".sounds", "stop", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
427 | wrapper.wrappingSoundEndTime = xmlFile:getValue(baseKey .. ".sounds#wrappingEndTime", 1) |
428 | end |
429 | end |
245 | function BaleWrapper:onLoad(savegame) |
246 | local spec = self.spec_baleWrapper |
247 | |
248 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.wrapper", "vehicle.baleWrapper") --FS17 to FS19 |
249 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.baleGrabber", "vehicle.baleWrapper.grabber") --FS17 to FS19 |
250 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.baleWrapper.grabber#index", "vehicle.baleWrapper.grabber#node") --FS17 to FS19 |
251 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.baleWrapper.grabber#index", "vehicle.baleWrapper.grabber#node") --FS17 to FS19 |
252 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.baleWrapper.roundBaleWrapper#baleIndex", "vehicle.baleWrapper.roundBaleWrapper#baleNode") --FS17 to FS19 |
253 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.baleWrapper.roundBaleWrapper#wrapperIndex", "vehicle.baleWrapper.roundBaleWrapper#wrapperNode") --FS17 to FS19 |
254 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.baleWrapper.squareBaleWrapper#baleIndex", "vehicle.baleWrapper.squareBaleWrapper#baleNode") --FS17 to FS19 |
255 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.baleWrapper.squareBaleWrapper#wrapperIndex", "vehicle.baleWrapper.squareBaleWrapper#wrapperNode") --FS17 to FS19 |
256 | |
257 | local baseKey = "vehicle.baleWrapper" |
258 | |
259 | spec.roundBaleWrapper = {} |
260 | self:loadWrapperFromXML(spec.roundBaleWrapper, self.xmlFile, baseKey, "roundBaleWrapper") |
261 | |
262 | spec.squareBaleWrapper = {} |
263 | self:loadWrapperFromXML(spec.squareBaleWrapper, self.xmlFile, baseKey, "squareBaleWrapper") |
264 | |
265 | spec.currentWrapper = {} |
266 | spec.currentWrapperFoldMinLimit = self.xmlFile:getValue(baseKey.."#foldMinLimit", 0) |
267 | spec.currentWrapperFoldMaxLimit = self.xmlFile:getValue(baseKey.."#foldMaxLimit", 1) |
268 | |
269 | spec.currentWrapper = spec.roundBaleWrapper |
270 | self:updateWrapNodes(false, true, 0) |
271 | spec.currentWrapper = spec.squareBaleWrapper |
272 | self:updateWrapNodes(false, true, 0) |
273 | |
274 | spec.currentBaleTypeIndex = 1 |
275 | |
276 | if spec.roundBaleWrapper.baleNode ~= nil then |
277 | self:setBaleWrapperType(true, 1) |
278 | elseif spec.squareBaleWrapper.baleNode ~= nil then |
279 | self:setBaleWrapperType(false, 1) |
280 | end |
281 | |
282 | spec.baleGrabber = {} |
283 | spec.baleGrabber.grabNode = self.xmlFile:getValue(baseKey..".grabber#node", nil, self.components, self.i3dMappings) |
284 | spec.baleGrabber.triggerNode = self.xmlFile:getValue(baseKey..".grabber#triggerNode", nil, self.components, self.i3dMappings) |
285 | if spec.baleGrabber.triggerNode == nil then |
286 | Logging.xmlWarning(self.xmlFile, "Missing bale grab trigger node '%s'. This is required for all bale wrappers.", baseKey..".grabber#triggerNode") |
287 | else |
288 | addTrigger(spec.baleGrabber.triggerNode, "baleGrabberTriggerCallback", self) |
289 | end |
290 | |
291 | spec.baleGrabber.nearestDistance = self.xmlFile:getValue(baseKey..".grabber#nearestDistance", 3.0) |
292 | spec.baleGrabber.balesInTrigger = {} |
293 | |
294 | spec.baleToLoad = nil |
295 | spec.baleToMount = nil |
296 | spec.baleWrapperState = BaleWrapper.STATE_NONE |
297 | spec.grabberIsMoving = false |
298 | spec.hasBaleWrapper = true |
299 | spec.showInvalidBaleWarning = false |
300 | |
301 | spec.automaticDrop = self.xmlFile:getValue("vehicle.baleWrapper.automaticDrop#enabled", Platform.gameplay.automaticBaleDrop) |
302 | spec.toggleableAutomaticDrop = self.xmlFile:getValue("vehicle.baleWrapper.automaticDrop#toggleable", not Platform.gameplay.automaticBaleDrop) |
303 | spec.toggleAutomaticDropTextPos = self.xmlFile:getValue("vehicle.baleWrapper.automaticDrop#textPos", "action_toggleAutomaticBaleDropPos", self.customEnvironment) |
304 | spec.toggleAutomaticDropTextNeg = self.xmlFile:getValue("vehicle.baleWrapper.automaticDrop#textNeg", "action_toggleAutomaticBaleDropNeg", self.customEnvironment) |
305 | |
306 | spec.texts = {} |
307 | spec.texts.warningFoldingWrapping = g_i18n:getText("warning_foldingNotWhileWrapping") |
308 | |
309 | ObjectChangeUtil.updateObjectChanges(self.xmlFile, baseKey .. ".wrappingAnimationConfigurations.wrappingAnimationConfiguration", self.configurations["wrappingAnimation"] or 1, self.components, self) |
310 | end |
663 | function BaleWrapper:onLoadFinished(savegame) |
664 | local spec = self.spec_baleWrapper |
665 | |
666 | if spec.baleToLoad ~= nil then |
667 | local v = spec.baleToLoad |
668 | spec.baleToLoad = nil |
669 | |
670 | local baleObject = Bale.new(self.isServer, self.isClient) |
671 | local x, y, z = unpack(v.translation) |
672 | local rx, ry, rz = unpack(v.rotation) |
673 | if baleObject:loadFromConfigXML(v.filename, x, y, z, rx, ry, rz) then |
674 | baleObject:applyBaleAttributes(v.attributes) |
675 | baleObject:register() |
676 | |
677 | if baleObject.nodeId ~= nil and baleObject.nodeId ~= 0 then |
678 | self:doStateChange(BaleWrapper.CHANGE_GRAB_BALE, NetworkUtil.getObjectId(baleObject)) |
679 | self:doStateChange(BaleWrapper.CHANGE_DROP_BALE_AT_GRABBER) |
680 | |
681 | local wrapperState = math.min(v.wrapperTime / spec.currentWrapper.animTime, 1) |
682 | baleObject:setWrappingState(wrapperState) |
683 | |
684 | self:doStateChange(BaleWrapper.CHANGE_WRAPPING_START) |
685 | spec.currentWrapper.currentTime = v.wrapperTime |
686 | |
687 | local wrapAnimationName = spec.currentWrapper.animations["wrapBale"].animName |
688 | local wrappingTime = spec.currentWrapper.currentTime / spec.currentWrapper.animTime |
689 | self:setAnimationStopTime(wrapAnimationName, wrappingTime) |
690 | AnimatedVehicle.updateAnimationByName(self, wrapAnimationName, 9999999, true) |
691 | self:updateWrappingState(wrappingTime) |
692 | |
693 | if wrappingTime < 1 then |
694 | self:playAnimation(wrapAnimationName, spec.currentWrapper.animations["wrapBale"].animSpeed, self:getAnimationTime(wrapAnimationName), true, false) |
695 | end |
696 | end |
697 | end |
698 | end |
699 | end |
769 | function BaleWrapper:onReadStream(streamId, connection) |
770 | if connection:getIsServer() then |
771 | local spec = self.spec_baleWrapper |
772 | |
773 | local isRoundBaleWrapper = streamReadBool(streamId) |
774 | local baleTypeIndex = streamReadUIntN(streamId, 8) |
775 | |
776 | self:setBaleWrapperType(isRoundBaleWrapper, baleTypeIndex) |
777 | |
778 | local wrapperState = streamReadUIntN(streamId, BaleWrapper.STATE_NUM_BITS) |
779 | if wrapperState >= BaleWrapper.STATE_MOVING_BALE_TO_WRAPPER then |
780 | local baleServerId |
781 | local isRoundBale |
782 | if wrapperState ~= BaleWrapper.STATE_WRAPPER_RESETTING_PLATFORM then |
783 | baleServerId = NetworkUtil.readNodeObjectId(streamId) |
784 | isRoundBale = streamReadBool(streamId) |
785 | end |
786 | |
787 | if wrapperState == BaleWrapper.STATE_MOVING_BALE_TO_WRAPPER then |
788 | self:doStateChange(BaleWrapper.CHANGE_GRAB_BALE, baleServerId) |
789 | AnimatedVehicle.updateAnimations(self, 99999999, true) |
790 | elseif wrapperState == BaleWrapper.STATE_MOVING_GRABBER_TO_WORK then |
791 | self.baleGrabber.currentBale = baleServerId |
792 | |
793 | self:doStateChange(BaleWrapper.CHANGE_DROP_BALE_AT_GRABBER) |
794 | AnimatedVehicle.updateAnimations(self, 99999999, true) |
795 | |
796 | elseif wrapperState ~= BaleWrapper.STATE_WRAPPER_RESETTING_PLATFORM then |
797 | spec.currentWrapper = (isRoundBale and spec.roundBaleWrapper) or spec.squareBaleWrapper |
798 | self:setBaleWrapperType(isRoundBale, baleTypeIndex) |
799 | |
800 | local attachNode = spec.currentWrapper.baleNode |
801 | spec.baleToMount = {serverId=baleServerId, linkNode=attachNode, trans={0,0,0}, rot={0,0,0} } |
802 | self:updateWrapNodes(true, false, 0) |
803 | spec.currentWrapper.currentBale = baleServerId |
804 | |
805 | if wrapperState == BaleWrapper.STATE_WRAPPER_WRAPPING_BALE then |
806 | local wrapperTime = streamReadFloat32(streamId) |
807 | spec.currentWrapper.currentTime = wrapperTime |
808 | self:updateWrappingState(spec.currentWrapper.currentTime / spec.currentWrapper.animTime, true) |
809 | else |
810 | spec.currentWrapper.currentTime = spec.currentWrapper.animTime |
811 | self:updateWrappingState(1, true) |
812 | |
813 | self:doStateChange(BaleWrapper.CHANGE_WRAPPING_BALE_FINSIHED) |
814 | AnimatedVehicle.updateAnimations(self, 99999999, true) |
815 | if wrapperState >= BaleWrapper.STATE_WRAPPER_DROPPING_BALE then |
816 | self:doStateChange(BaleWrapper.CHANGE_WRAPPER_START_DROP_BALE) |
817 | AnimatedVehicle.updateAnimations(self, 99999999, true) |
818 | end |
819 | end |
820 | else |
821 | -- simply set the state but do nothing else |
822 | spec.baleWrapperState = BaleWrapper.STATE_WRAPPER_RESETTING_PLATFORM |
823 | end |
824 | end |
825 | end |
826 | end |
865 | function BaleWrapper:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
866 | local spec = self.spec_baleWrapper |
867 | |
868 | if spec.baleToMount ~= nil then |
869 | local bale = NetworkUtil.getObject(spec.baleToMount.serverId) |
870 | if bale ~= nil then |
871 | local x,y,z = unpack(spec.baleToMount.trans) |
872 | local rx,ry,rz = unpack(spec.baleToMount.rot) |
873 | bale:mountKinematic(self, spec.baleToMount.linkNode, x,y,z, rx,ry,rz) |
874 | bale:setCanBeSold(false) |
875 | spec.baleToMount = nil |
876 | |
877 | if spec.baleWrapperState == BaleWrapper.STATE_MOVING_BALE_TO_WRAPPER then |
878 | self:playMoveToWrapper(bale) |
879 | end |
880 | end |
881 | end |
882 | |
883 | if spec.baleWrapperState == BaleWrapper.STATE_WRAPPER_WRAPPING_BALE then |
884 | local wrapper = spec.currentWrapper |
885 | |
886 | wrapper.currentTime = math.min(wrapper.currentTime + dt, spec.currentWrapper.animTime) |
887 | local wrappingTime = wrapper.currentTime / wrapper.animTime |
888 | self:updateWrappingState(wrappingTime) |
889 | self:raiseActive() |
890 | |
891 | if self.isClient then |
892 | if wrapper.wrappingSoundEndTime <= wrappingTime then |
893 | if g_soundManager:getIsSamplePlaying(wrapper.samples.wrap) then |
894 | g_soundManager:stopSample(wrapper.samples.wrap) |
895 | g_soundManager:playSample(wrapper.samples.stop) |
896 | end |
897 | else |
898 | if not g_soundManager:getIsSamplePlaying(wrapper.samples.wrap) then |
899 | g_soundManager:playSample(wrapper.samples.wrap) |
900 | end |
901 | end |
902 | end |
903 | end |
904 | end |
911 | function BaleWrapper:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
912 | local spec = self.spec_baleWrapper |
913 | |
914 | spec.showInvalidBaleWarning = false |
915 | |
916 | if self:allowsGrabbingBale() then |
917 | if spec.baleGrabber.grabNode ~= nil and spec.baleGrabber.currentBale == nil then |
918 | -- find nearest bale |
919 | local nearestBaleWrappable, nearestBale, nearestBaleTypeIndex = BaleWrapper.getBaleInRange(self, spec.baleGrabber.grabNode, spec.baleGrabber.nearestDistance) |
920 | if nearestBale then |
921 | if nearestBaleWrappable ~= nil or (nearestBale.isRoundbale and spec.roundBaleWrapper.skipUnsupportedBales or spec.squareBaleWrapper.skipUnsupportedBales) then |
922 | if self.isServer then |
923 | self:pickupWrapperBale(nearestBaleWrappable or nearestBale, nearestBaleTypeIndex) |
924 | end |
925 | else |
926 | if self.isClient then |
927 | if nearestBale and spec.lastDroppedBale ~= nearestBale then |
928 | spec.showInvalidBaleWarning = true |
929 | end |
930 | end |
931 | end |
932 | end |
933 | end |
934 | end |
935 | if self.isServer then |
936 | if spec.baleWrapperState ~= BaleWrapper.STATE_NONE then |
937 | if spec.baleWrapperState == BaleWrapper.STATE_MOVING_BALE_TO_WRAPPER then |
938 | if not self:getIsAnimationPlaying(spec.currentWrapper.animations["moveToWrapper"].animName) then |
939 | g_server:broadcastEvent(BaleWrapperStateEvent.new(self, BaleWrapper.CHANGE_DROP_BALE_AT_GRABBER), true, nil, self) |
940 | end |
941 | elseif spec.baleWrapperState == BaleWrapper.STATE_MOVING_GRABBER_TO_WORK then |
942 | if not self:getIsAnimationPlaying(spec.currentWrapper.animations["moveToWrapper"].animName) then |
943 | local bale = NetworkUtil.getObject(spec.currentWrapper.currentBale) |
944 | if bale ~= nil and not bale.supportsWrapping then |
945 | g_server:broadcastEvent(BaleWrapperStateEvent.new(self, BaleWrapper.CHANGE_WRAPPER_START_DROP_BALE), true, nil, self) |
946 | else |
947 | g_server:broadcastEvent(BaleWrapperStateEvent.new(self, BaleWrapper.CHANGE_WRAPPING_START), true, nil, self) |
948 | end |
949 | end |
950 | elseif spec.baleWrapperState == BaleWrapper.STATE_WRAPPER_DROPPING_BALE then |
951 | if not self:getIsAnimationPlaying(spec.currentWrapper.animations["dropFromWrapper"].animName) then |
952 | g_server:broadcastEvent(BaleWrapperStateEvent.new(self, BaleWrapper.CHANGE_WRAPPER_BALE_DROPPED), true, nil, self) |
953 | end |
954 | elseif spec.baleWrapperState == BaleWrapper.STATE_WRAPPER_RESETTING_PLATFORM then |
955 | if not self:getIsAnimationPlaying(spec.currentWrapper.animations["resetAfterDrop"].animName) then |
956 | g_server:broadcastEvent(BaleWrapperStateEvent.new(self, BaleWrapper.CHANGE_WRAPPER_PLATFORM_RESET), true, nil, self) |
957 | end |
958 | end |
959 | end |
960 | |
961 | if spec.automaticDrop or self:getIsAIActive() then |
962 | local isPowered, _ = self:getIsPowered() |
963 | if isPowered then |
964 | if spec.baleWrapperState == BaleWrapper.STATE_WRAPPER_FINSIHED then |
965 | self:doStateChange(BaleWrapper.CHANGE_BUTTON_EMPTY) |
966 | end |
967 | end |
968 | end |
969 | end |
970 | |
971 | BaleWrapper.updateActionEvents(self) |
972 | |
973 | if spec.setWrappingStateFinished then |
974 | g_server:broadcastEvent(BaleWrapperStateEvent.new(self, BaleWrapper.CHANGE_WRAPPING_BALE_FINSIHED), true, nil, self) |
975 | spec.setWrappingStateFinished = false |
976 | end |
977 | end |
195 | function BaleWrapper.registerFunctions(vehicleType) |
196 | SpecializationUtil.registerFunction(vehicleType, "loadWrapperFromXML", BaleWrapper.loadWrapperFromXML) |
197 | SpecializationUtil.registerFunction(vehicleType, "loadWrapperAnimationsFromXML", BaleWrapper.loadWrapperAnimationsFromXML) |
198 | SpecializationUtil.registerFunction(vehicleType, "loadWrapperAnimCurveFromXML", BaleWrapper.loadWrapperAnimCurveFromXML) |
199 | SpecializationUtil.registerFunction(vehicleType, "loadWrapperAnimNodesFromXML", BaleWrapper.loadWrapperAnimNodesFromXML) |
200 | SpecializationUtil.registerFunction(vehicleType, "loadWrapperWrapNodesFromXML", BaleWrapper.loadWrapperWrapNodesFromXML) |
201 | SpecializationUtil.registerFunction(vehicleType, "loadWrapperStateCurveFromXML", BaleWrapper.loadWrapperStateCurveFromXML) |
202 | SpecializationUtil.registerFunction(vehicleType, "loadWrapperAnimationNodesFromXML", BaleWrapper.loadWrapperAnimationNodesFromXML) |
203 | SpecializationUtil.registerFunction(vehicleType, "loadWrapperFoilAnimationFromXML", BaleWrapper.loadWrapperFoilAnimationFromXML) |
204 | |
205 | SpecializationUtil.registerFunction(vehicleType, "baleGrabberTriggerCallback", BaleWrapper.baleGrabberTriggerCallback) |
206 | SpecializationUtil.registerFunction(vehicleType, "allowsGrabbingBale", BaleWrapper.allowsGrabbingBale) |
207 | SpecializationUtil.registerFunction(vehicleType, "pickupWrapperBale", BaleWrapper.pickupWrapperBale) |
208 | SpecializationUtil.registerFunction(vehicleType, "getIsBaleWrappable", BaleWrapper.getIsBaleWrappable) |
209 | SpecializationUtil.registerFunction(vehicleType, "updateWrappingState", BaleWrapper.updateWrappingState) |
210 | SpecializationUtil.registerFunction(vehicleType, "doStateChange", BaleWrapper.doStateChange) |
211 | SpecializationUtil.registerFunction(vehicleType, "updateWrapNodes", BaleWrapper.updateWrapNodes) |
212 | SpecializationUtil.registerFunction(vehicleType, "playMoveToWrapper", BaleWrapper.playMoveToWrapper) |
213 | SpecializationUtil.registerFunction(vehicleType, "setBaleWrapperType", BaleWrapper.setBaleWrapperType) |
214 | SpecializationUtil.registerFunction(vehicleType, "getMatchingBaleTypeIndex", BaleWrapper.getMatchingBaleTypeIndex) |
215 | SpecializationUtil.registerFunction(vehicleType, "setBaleWrapperAutomaticDrop", BaleWrapper.setBaleWrapperAutomaticDrop) |
216 | end |
95 | function BaleWrapper.registerWrapperXMLPaths(schema, basePath) |
96 | for i=1, #BaleWrapper.ANIMATION_NAMES do |
97 | BaleWrapper.registerWrapperAnimationXMLPaths(schema, basePath, BaleWrapper.ANIMATION_NAMES[i]) |
98 | BaleWrapper.registerWrapperAnimationXMLPaths(schema, basePath .. ".baleTypes.baleType(?)", BaleWrapper.ANIMATION_NAMES[i]) |
99 | end |
100 | |
101 | schema:register(XMLValueType.STRING, basePath .. ".baleTypes.baleType(?)#fillType", "Fill type name") |
102 | schema:register(XMLValueType.FLOAT, basePath .. ".baleTypes.baleType(?)#diameter", "Bale diameter", 0) |
103 | schema:register(XMLValueType.FLOAT, basePath .. ".baleTypes.baleType(?)#width", "Bale width", 0) |
104 | schema:register(XMLValueType.FLOAT, basePath .. ".baleTypes.baleType(?)#height", "Bale height", 0) |
105 | schema:register(XMLValueType.FLOAT, basePath .. ".baleTypes.baleType(?)#length", "Bale length", 0) |
106 | schema:register(XMLValueType.STRING, basePath .. ".baleTypes.baleType(?).textures#diffuse", "Path to wrap diffuse map") |
107 | schema:register(XMLValueType.STRING, basePath .. ".baleTypes.baleType(?).textures#normal", "Path to wrap normal map") |
108 | schema:register(XMLValueType.BOOL, basePath .. ".baleTypes.baleType(?)#skipWrapping", "Bale is picked up, but not wrapped", false) |
109 | schema:register(XMLValueType.BOOL, basePath .. ".baleTypes.baleType(?)#forceWhileFolding", "Force this bale type while wrapper is folded", false) |
110 | |
111 | schema:register(XMLValueType.FLOAT, basePath .. ".baleTypes.baleType(?).wrappingState.key(?)#time", "Time of wrapping (0-1)") |
112 | schema:register(XMLValueType.FLOAT, basePath .. ".baleTypes.baleType(?).wrappingState.key(?)#wrappingState", "Wrapping state for shader") |
113 | |
114 | ObjectChangeUtil.registerObjectChangeXMLPaths(schema, basePath .. ".baleTypes.baleType(?)") |
115 | BaleWrapper.registerWrapperFoilAnimationXMLPaths(schema, basePath .. ".baleTypes.baleType(?)") |
116 | |
117 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#baleNode", "Bale Node") |
118 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#wrapperNode", "Wrapper Node") |
119 | schema:register(XMLValueType.INT, basePath .. "#wrapperRotAxis", "Wrapper rotation axis", 2) |
120 | |
121 | schema:register(XMLValueType.FLOAT, basePath .. ".wrapperAnimation.key(?)#time", "Key time") |
122 | schema:register(XMLValueType.VECTOR_ROT, basePath .. ".wrapperAnimation.key(?)#baleRot", "Bale rotation") |
123 | schema:register(XMLValueType.VECTOR_ROT, basePath .. ".wrapperAnimation.key(?)#wrapperRot", "Wrapper rotation", "0 0 0") |
124 | |
125 | schema:register(XMLValueType.FLOAT, basePath .. "#wrappingTime", "Wrapping duration", 5) |
126 | |
127 | schema:register(XMLValueType.NODE_INDEX, basePath .. ".wrapAnimNodes.wrapAnimNode(?)#node", "Wrap node") |
128 | schema:register(XMLValueType.BOOL, basePath .. ".wrapAnimNodes.wrapAnimNode(?)#repeatWrapperRot", "Repeat wrapper rotation, so wrapper rotation is always between 0 and 360", false) |
129 | schema:register(XMLValueType.INT, basePath .. ".wrapAnimNodes.wrapAnimNode(?)#normalizeRotationOnBaleDrop", "Normalize rotation on bale drop", 0) |
130 | |
131 | schema:register(XMLValueType.FLOAT, basePath .. ".wrapAnimNodes.wrapAnimNode(?).key(?)#wrapperRot", "Wrapper rotation") |
132 | schema:register(XMLValueType.FLOAT, basePath .. ".wrapAnimNodes.wrapAnimNode(?).key(?)#wrapperTime", "Wrapper time") |
133 | schema:register(XMLValueType.VECTOR_TRANS, basePath .. ".wrapAnimNodes.wrapAnimNode(?).key(?)#trans", "Trans", "0 0 0") |
134 | schema:register(XMLValueType.VECTOR_ROT, basePath .. ".wrapAnimNodes.wrapAnimNode(?).key(?)#rot", "Rotation", "0 0 0") |
135 | schema:register(XMLValueType.VECTOR_SCALE, basePath .. ".wrapAnimNodes.wrapAnimNode(?).key(?)#scale", "Scale", "1 1 1") |
136 | |
137 | schema:register(XMLValueType.NODE_INDEX, basePath .. ".wrapNodes.wrapNode(?)#node", "Wrap node") |
138 | schema:register(XMLValueType.BOOL, basePath .. ".wrapNodes.wrapNode(?)#wrapVisibility", "Visibility while wrapping", false) |
139 | schema:register(XMLValueType.BOOL, basePath .. ".wrapNodes.wrapNode(?)#emptyVisibility", "Visibility while empty", false) |
140 | schema:register(XMLValueType.FLOAT, basePath .. ".wrapNodes.wrapNode(?)#maxWrapperRot", "Max. wrapper rotation") |
141 | |
142 | schema:register(XMLValueType.FLOAT, basePath .. ".wrappingState.key(?)#time", "Time of wrapping (0-1)") |
143 | schema:register(XMLValueType.FLOAT, basePath .. ".wrappingState.key(?)#wrappingState", "Wrapping state for shader") |
144 | |
145 | |
146 | schema:register(XMLValueType.FLOAT, basePath .. ".wrappingAnimationNodes#maxTime", "Max. time of animation nodes", "Wrapper anim time") |
147 | schema:register(XMLValueType.NODE_INDEX, basePath .. ".wrappingAnimationNodes.key(?)#node", "Animation node") |
148 | schema:register(XMLValueType.NODE_INDEX, basePath .. ".wrappingAnimationNodes.key(?)#rootNode", "Reference node for rotation") |
149 | schema:register(XMLValueType.NODE_INDEX, basePath .. ".wrappingAnimationNodes.key(?)#linkNode", "Node will be linked to this node while key is activated") |
150 | schema:register(XMLValueType.FLOAT, basePath .. ".wrappingAnimationNodes.key(?)#time", "Time to activate key") |
151 | schema:register(XMLValueType.VECTOR_TRANS, basePath .. ".wrappingAnimationNodes.key(?)#translation", "Translation of key") |
152 | |
153 | schema:register(XMLValueType.NODE_INDEX, basePath .. ".wrappingAnimationNodes#referenceNode", "Reference node") |
154 | schema:register(XMLValueType.INT, basePath .. ".wrappingAnimationNodes#referenceAxis", "Reference axis", 1) |
155 | schema:register(XMLValueType.ANGLE, basePath .. ".wrappingAnimationNodes#minRot", "Min. rotation", 0) |
156 | schema:register(XMLValueType.ANGLE, basePath .. ".wrappingAnimationNodes#maxRot", "Max. rotation", 0) |
157 | |
158 | BaleWrapper.registerWrapperFoilAnimationXMLPaths(schema, basePath) |
159 | |
160 | schema:register(XMLValueType.NODE_INDEX, basePath .. ".wrappingCollisions.collision(?)#node", "Collision node") |
161 | schema:register(XMLValueType.INT, basePath .. ".wrappingCollisions.collision(?)#activeCollisionMask", "Collision mask active") |
162 | schema:register(XMLValueType.INT, basePath .. ".wrappingCollisions.collision(?)#inActiveCollisionMask", "Collision mask in active") |
163 | |
164 | schema:register(XMLValueType.L10N_STRING, basePath .. "#unloadBaleText", "Unload bale text", "'action_unloadRoundBale' for round bales and 'action_unloadSquareBale' for square bales") |
165 | schema:register(XMLValueType.BOOL, basePath .. "#skipUnsupportedBales", "Skip unsupported bales (pick them up and drop them instantly)") |
166 | |
167 | SoundManager.registerSampleXMLPaths(schema, basePath .. ".sounds", "wrap") |
168 | SoundManager.registerSampleXMLPaths(schema, basePath .. ".sounds", "start") |
169 | SoundManager.registerSampleXMLPaths(schema, basePath .. ".sounds", "stop") |
170 | schema:register(XMLValueType.FLOAT, basePath .. ".sounds#wrappingEndTime", "Wrapping time to play end wrapping sound", 1) |
171 | end |
1044 | function BaleWrapper:updateWrapNodes(isWrapping, isEmpty, t, wrapperRot) |
1045 | local spec = self.spec_baleWrapper |
1046 | |
1047 | if wrapperRot == nil then |
1048 | wrapperRot = 0 |
1049 | end |
1050 | |
1051 | for _, wrapNode in pairs(spec.currentWrapper.wrapNodes) do |
1052 | local doShow = true |
1053 | if wrapNode.maxWrapperRot ~= nil then |
1054 | doShow = wrapperRot < wrapNode.maxWrapperRot |
1055 | end |
1056 | setVisibility(wrapNode.nodeId, doShow and ((isWrapping and wrapNode.wrapVisibility) or (isEmpty and wrapNode.emptyVisibility))) |
1057 | end |
1058 | |
1059 | if isWrapping then |
1060 | local wrapperRotRepeat = MathUtil.sign(wrapperRot) * (wrapperRot % math.pi) |
1061 | if wrapperRotRepeat < 0 then |
1062 | wrapperRotRepeat = wrapperRotRepeat + math.pi |
1063 | end |
1064 | |
1065 | for _,wrapAnimNode in pairs(spec.currentWrapper.wrapAnimNodes) do |
1066 | local v |
1067 | if wrapAnimNode.useWrapperRot then |
1068 | local rot = wrapperRot |
1069 | if wrapAnimNode.repeatWrapperRot then |
1070 | rot = wrapperRotRepeat |
1071 | end |
1072 | v = wrapAnimNode.animCurve:get(rot) |
1073 | else |
1074 | v = wrapAnimNode.animCurve:get(t) |
1075 | end |
1076 | if v ~= nil then |
1077 | setTranslation(wrapAnimNode.nodeId, v[1], v[2], v[3]) |
1078 | setRotation(wrapAnimNode.nodeId, v[4], v[5], v[6]) |
1079 | setScale(wrapAnimNode.nodeId, v[7], v[8], v[9]) |
1080 | end |
1081 | end |
1082 | else |
1083 | if not isEmpty then |
1084 | for _,wrapAnimNode in pairs(spec.currentWrapper.wrapAnimNodes) do |
1085 | if wrapAnimNode.normalizeRotationOnBaleDrop ~= 0 then |
1086 | local rot = { getRotation(wrapAnimNode.nodeId) } |
1087 | for i=1,3 do |
1088 | rot[i] = wrapAnimNode.normalizeRotationOnBaleDrop * MathUtil.sign(rot[i]) * ( rot[i] % (2*math.pi) ) |
1089 | end |
1090 | setRotation(wrapAnimNode.nodeId, rot[1],rot[2],rot[3]) |
1091 | end |
1092 | end |
1093 | end |
1094 | end |
1095 | end |
1101 | function BaleWrapper:updateWrappingState(wrappingTime, noEventSend) |
1102 | local spec = self.spec_baleWrapper |
1103 | local wrapper = spec.currentWrapper |
1104 | |
1105 | local foilTime = 0 |
1106 | if wrapper.wrappingFoilAnimation ~= nil then |
1107 | local wrappingFoilAnimation = wrapper.wrappingFoilAnimation |
1108 | |
1109 | wrappingFoilAnimation.referenceNodeRotation[1], wrappingFoilAnimation.referenceNodeRotation[2], wrappingFoilAnimation.referenceNodeRotation[3] = getRotation(wrappingFoilAnimation.referenceNode) |
1110 | local rotation = wrappingFoilAnimation.referenceNodeRotation[wrappingFoilAnimation.referenceAxis] |
1111 | foilTime = (rotation - wrappingFoilAnimation.referenceMinRot) / (wrappingFoilAnimation.referenceMaxRot - wrappingFoilAnimation.referenceMinRot) |
1112 | if foilTime > 0 and foilTime < 1 then |
1113 | if foilTime ~= wrappingFoilAnimation.lastTime then |
1114 | local oldClipIndex = getAnimTrackAssignedClip(wrappingFoilAnimation.animationCharSet, 0) |
1115 | if oldClipIndex ~= wrappingFoilAnimation.animationClipIndex then |
1116 | clearAnimTrackClip(wrappingFoilAnimation.animationCharSet, 0) |
1117 | assignAnimTrackClip(wrappingFoilAnimation.animationCharSet, 0, wrappingFoilAnimation.animationClipIndex) |
1118 | end |
1119 | |
1120 | enableAnimTrack(wrappingFoilAnimation.animationCharSet, 0) |
1121 | setAnimTrackTime(wrappingFoilAnimation.animationCharSet, 0, foilTime * wrappingFoilAnimation.animationClipDuration, true) |
1122 | disableAnimTrack(wrappingFoilAnimation.animationCharSet, 0) |
1123 | |
1124 | wrappingFoilAnimation.lastTime = foilTime |
1125 | end |
1126 | end |
1127 | end |
1128 | |
1129 | local nodesTime = 0 |
1130 | if wrapper.wrappingAnimationNodes.referenceNode ~= nil then |
1131 | wrapper.wrappingAnimationNodes.referenceNodeRotation[1], wrapper.wrappingAnimationNodes.referenceNodeRotation[2], wrapper.wrappingAnimationNodes.referenceNodeRotation[3] = getRotation(wrapper.wrappingAnimationNodes.referenceNode) |
1132 | local rotation = wrapper.wrappingAnimationNodes.referenceNodeRotation[wrapper.wrappingAnimationNodes.referenceAxis] |
1133 | nodesTime = MathUtil.clamp((rotation - wrapper.wrappingAnimationNodes.referenceMinRot) / (wrapper.wrappingAnimationNodes.referenceMaxRot - wrapper.wrappingAnimationNodes.referenceMinRot), 0, 1) |
1134 | nodesTime = MathUtil.round(nodesTime, 5) |
1135 | end |
1136 | |
1137 | if nodesTime > wrapper.wrappingAnimationNodes.lastTime then |
1138 | local nodes = wrapper.wrappingAnimationNodes.nodes |
1139 | for i = wrapper.wrappingAnimationNodes.currentIndex + 1, #nodes do |
1140 | local wrappingAnimationNode = nodes[i] |
1141 | if wrappingAnimationNode.time <= nodesTime then |
1142 | if wrappingAnimationNode.linkNode ~= nil then |
1143 | local x, y, z = localToWorld(wrappingAnimationNode.parent, unpack(wrappingAnimationNode.translation)) |
1144 | if getParent(wrappingAnimationNode.nodeId) ~= wrappingAnimationNode.linkNode then |
1145 | link(wrappingAnimationNode.linkNode, wrappingAnimationNode.nodeId) |
1146 | end |
1147 | setWorldTranslation(wrappingAnimationNode.nodeId, x, y, z) |
1148 | else |
1149 | if getParent(wrappingAnimationNode.nodeId) ~= wrappingAnimationNode.parent then |
1150 | link(wrappingAnimationNode.parent, wrappingAnimationNode.nodeId) |
1151 | end |
1152 | setTranslation(wrappingAnimationNode.nodeId, unpack(wrappingAnimationNode.translation)) |
1153 | end |
1154 | |
1155 | wrapper.wrappingAnimationNodes.currentIndex = i |
1156 | else |
1157 | break |
1158 | end |
1159 | end |
1160 | elseif nodesTime < wrapper.wrappingAnimationNodes.lastTime then |
1161 | wrapper.wrappingAnimationNodes.currentIndex = 0 |
1162 | end |
1163 | wrapper.wrappingAnimationNodes.lastTime = nodesTime |
1164 | |
1165 | for animationNode, rootNode in pairs(wrapper.wrappingAnimationNodes.nodeToRootNode) do |
1166 | local rx, ry, rz = localRotationToLocal(rootNode, getParent(animationNode), 0, 0, 0) |
1167 | setRotation(animationNode, rx, ry, rz) |
1168 | end |
1169 | |
1170 | local wrappingState = math.min(wrappingTime, 1) |
1171 | local wrapperRot = 0 |
1172 | if wrapper.animCurve ~= nil then |
1173 | local v = wrapper.animCurve:get(wrappingTime) |
1174 | if v ~= nil then |
1175 | setRotation(wrapper.baleNode, v[1]%(math.pi*2), v[2]%(math.pi*2), v[3]%(math.pi*2)) |
1176 | setRotation(wrapper.wrapperNode, v[4]%(math.pi*2), v[5]%(math.pi*2), v[6]%(math.pi*2)) |
1177 | wrapperRot = v[3 + wrapper.wrapperRotAxis] |
1178 | elseif wrapper.animations["wrapBale"].animName ~= nil then |
1179 | wrappingTime = self:getAnimationTime(wrapper.animations["wrapBale"].animName) |
1180 | end |
1181 | |
1182 | if wrapper.wrappingAnimationNodes.referenceNode ~= nil then |
1183 | wrappingState = nodesTime |
1184 | end |
1185 | |
1186 | if wrapper.wrappingFoilAnimation ~= nil then |
1187 | wrappingState = foilTime |
1188 | end |
1189 | |
1190 | if wrapper.currentBale ~= nil then |
1191 | local bale = NetworkUtil.getObject(wrapper.currentBale) |
1192 | if bale ~= nil then |
1193 | local baleType = spec.currentWrapper.allowedBaleTypes[spec.currentBaleTypeIndex] |
1194 | if bale:getSupportsWrapping() and not baleType.skipWrapping and bale.wrappingState < 1 then |
1195 | local wrappingStateCurve = baleType.wrappingStateCurve or wrapper.wrappingStateCurve |
1196 | if wrappingStateCurve ~= nil then |
1197 | wrappingState = wrappingStateCurve:get(wrappingState) |
1198 | end |
1199 | |
1200 | bale:setWrappingState(wrappingState, true) |
1201 | |
1202 | if bale.setColor ~= nil then |
1203 | local color = ConfigurationUtil.getColorByConfigId(self, "wrappingColor", self.configurations["wrappingColor"]) |
1204 | if color ~= nil then |
1205 | local r, g, b, a = unpack(color) |
1206 | bale:setColor(r, g, b, a) |
1207 | end |
1208 | end |
1209 | end |
1210 | end |
1211 | end |
1212 | end |
1213 | |
1214 | self:updateWrapNodes(wrappingTime > 0, false, wrappingTime, wrapperRot) |
1215 | if wrappingTime > 0.99999 then |
1216 | if self.isServer and spec.baleWrapperState == BaleWrapper.STATE_WRAPPER_WRAPPING_BALE and not noEventSend then |
1217 | g_server:broadcastEvent(BaleWrapperStateEvent.new(self, BaleWrapper.CHANGE_WRAPPING_BALE_FINSIHED), true, nil, self) |
1218 | end |
1219 | end |
1220 | end |