Script v1_7_1_0
- AI
- Animals
- Collections
- Contracts
- Debug
- Economy
- Elements
- EnvironmentalScore
- Errors
- Events
- GUI
- Handtools
- Hud
- I3d
- Input
- Jobs
- Maps
- Materials
- Misc
- Objects
- Parameters
- Placeables
- Placement
- Player
- Shop
- Sounds
- Specialization
- Specializations
- AIConveyorBelt
- AIDrivable
- AIFieldWorker
- AIImplement
- AIJobVehicle
- AIVehicle
- AIVehicleObstacle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- AutoLoader
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BigBag
- BunkerSiloCompacter
- BunkerSiloInteractor
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- CropSensor
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- ExtendedAIVehicle
- ExtendedCombine
- ExtendedMotorized
- ExtendedMower
- ExtendedSowingMachine
- ExtendedSprayer
- ExtendedWearable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- HeadlandAnimation
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- InlineWrapper
- JigglingParts
- Leveler
- LicensePlates
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- ManureSensor
- MixerWagon
- Motorized
- Mountable
- Mower
- Mulcher
- MultipleItemPurchase
- Pallet
- Pickup
- Pipe
- PlaceableAI
- PlaceableAnimatedObjects
- PlaceableBeehive
- PlaceableBeehivePalletSpa...
- PlaceableBunkerSilo
- PlaceableBuyingStation
- PlaceableCartridgePlayer
- PlaceableChargingStation
- PlaceableClearAreas
- PlaceableColorable
- PlaceableDeletedNodes
- PlaceableDoghouse
- PlaceableDynamicallyLoade...
- PlaceableFarmhouse
- PlaceableFence
- PlaceableFoliageAreas
- PlaceableGreenhouse
- PlaceableHighPressureWash...
- PlaceableHotspots
- PlaceableHusbandry
- PlaceableHusbandryAnimals
- PlaceableHusbandryFeeding...
- PlaceableHusbandryFence
- PlaceableHusbandryFood
- PlaceableHusbandryLiquidM...
- PlaceableHusbandryMilk
- PlaceableHusbandryPallets
- PlaceableHusbandryStraw
- PlaceableHusbandryWater
- PlaceableIncomePerHour
- PlaceableIndoorAreas
- PlaceableInfoTrigger
- PlaceableLeveling
- PlaceableLights
- PlaceableManureHeap
- PlaceablePlacement
- PlaceableProductionPoint
- PlaceableSellingStation
- PlaceableSilo
- PlaceableSiloExtension
- PlaceableSolarPanels
- PlaceableTipOcclusionArea...
- PlaceableTrainSystem
- PlaceableTriggerMarkers
- PlaceableVine
- PlaceableWardrobe
- PlaceableWeatherStation
- PlaceableWeighingStation
- PlaceableWindTurbine
- PlaceableWorkshop
- Plow
- PlowPacker
- PowerConsumer
- PowerTakeOffs
- PrecisionFarmingStatistic
- PushHandTool
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- RTKStation
- SaltSpreader
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SoilSampler
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StonePicker
- StrawBlower
- StumpCutter
- SupportVehicle
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TestAreas
- TipOccluder
- Trailer
- TreePlanter
- TreeSaplingPallet
- TreeSaw
- TurnOnVehicle
- VariableWorkWidth
- VehicleSettings
- VineCutter
- VineDetector
- VinePrepruner
- Washable
- WaterTrailer
- Wearable
- Weeder
- WeedSpotSpray
- Wheels
- WindBending
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- StateMachine
- Statistics
- Tasks
- Triggers
- Utils
- Vehicles
Engine v1_7_1_0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- general
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- NoteNode
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- VoiceChat
- XML
Foundation Reference
TensionBelts
DescriptionClass for vehicle which can dynamically mount objects (e.g. bales and pallets)Functions
- actionEventToggleTensionBelts
- consoleCommandToggleTensionBeltDebugRendering
- createTensionBelt
- freeTensionBeltObject
- getAdditionalComponentMass
- getCanBeSelected
- getFillLevelInformation
- getIsDynamicallyMountedNode
- getIsFoldAllowed
- getIsPlayerInTensionBeltsRange
- getIsReadyForAutomatedTrainTravel
- getObjectsToUnmount
- getObjectToMount
- initSpecialization
- lockTensionBeltObject
- objectOverlapCallback
- onDelete
- onDraw
- onLoad
- onPostLoad
- onPreDelete
- onReadStream
- onRegisterActionEvents
- onTensionBeltTreeShapeCut
- onUpdate
- onUpdateTick
- onWriteStream
- prerequisitesPresent
- refreshTensionBelts
- registerEventListeners
- registerFunctions
- registerOverwrittenFunctions
- removeTensionBelt
- saveToXMLFile
- setAllTensionBeltsActive
- setTensionBeltsActive
- tensionBeltActivationTriggerCallback
- updateFastenState
actionEventToggleTensionBelts
DescriptionDefinitionactionEventToggleTensionBelts()Code
1431 | function TensionBelts.actionEventToggleTensionBelts(self, actionName, inputValue, callbackState, isAnalog) |
1432 | local spec = self.spec_tensionBelts |
1433 | |
1434 | spec.fastedAllBeltsIndex = 1 |
1435 | spec.fastedAllBeltsState = not spec.areBeltsFasten |
1436 | end |
consoleCommandToggleTensionBeltDebugRendering
DescriptionDefinitionconsoleCommandToggleTensionBeltDebugRendering()Code
1440 | function TensionBelts.consoleCommandToggleTensionBeltDebugRendering(unusedSelf) |
1441 | TensionBelts.debugRendering = not TensionBelts.debugRendering |
1442 | return "TensionBeltsDebugRendering = "..tostring(TensionBelts.debugRendering) |
1443 | end |
createTensionBelt
DescriptionCreate tension beltDefinition
createTensionBelt(table belt, boolean isDummy, table object, boolean playSound)Arguments
table | belt | belt to use |
boolean | isDummy | create dummy belt |
table | object | objects to fasten |
boolean | playSound | play sound (nil = true) |
891 | function TensionBelts:createTensionBelt(belt, isDummy, objects, playSound) |
892 | local spec = self.spec_tensionBelts |
893 | |
894 | local tensionBelt = TensionBeltGeometryConstructor.new() |
895 | |
896 | local beltData = spec.beltData |
897 | local width = spec.width or beltData.width |
898 | |
899 | tensionBelt:setWidth(beltData.width) |
900 | tensionBelt:setMaxEdgeLength(spec.maxEdgeLength) |
901 | if isDummy then |
902 | tensionBelt:setMaterial(beltData.dummyMaterial.materialId) |
903 | tensionBelt:setUVscale(beltData.dummyMaterial.uvScale) |
904 | else |
905 | tensionBelt:setMaterial(beltData.material.materialId) |
906 | tensionBelt:setUVscale(beltData.material.uvScale) |
907 | end |
908 | |
909 | if spec.ratchetPosition ~= nil and beltData.ratchet ~= nil then |
910 | tensionBelt:addAttachment(0, spec.ratchetPosition, beltData.ratchet.sizeRatio*width) |
911 | end |
912 | |
913 | if spec.useHooks and beltData.hook ~= nil then |
914 | tensionBelt:addAttachment(0, 0, beltData.hook.sizeRatio*width) |
915 | tensionBelt:addAttachment(1, 0, (beltData.hook2 or beltData.hook).sizeRatio*width) |
916 | end |
917 | |
918 | tensionBelt:setFixedPoints(belt.startNode, belt.endNode) |
919 | tensionBelt:setGeometryBias(spec.geometryBias) |
920 | tensionBelt:setLinkNode(spec.linkNode) |
921 | |
922 | for _, pointNode in pairs(belt.intersectionNodes) do |
923 | local x,y,z = getWorldTranslation(pointNode) |
924 | local dirX, dirY, dirZ = localDirectionToWorld(pointNode, 1, 0, 0) |
925 | tensionBelt:addIntersectionPoint(x,y,z, dirX, dirY, dirZ) |
926 | end |
927 | |
928 | for _, object in pairs(objects) do |
929 | for _, node in pairs(object.visuals) do |
930 | if getSplitType(node) ~= 0 then |
931 | -- Allow a larger range of uvs for trees |
932 | tensionBelt:addShape(node, -100, 100, -100, 100) |
933 | else |
934 | tensionBelt:addShape(node, 0, 1, 0, 1) |
935 | end |
936 | end |
937 | end |
938 | |
939 | local beltShape, _, beltLength = tensionBelt:finalize() |
940 | if beltShape ~= 0 then |
941 | if isDummy then |
942 | belt.dummy = beltShape |
943 | else |
944 | local currentIndex = 0 |
945 | if spec.ratchetPosition ~= nil and beltData.ratchet ~= nil then |
946 | if getNumOfChildren(beltShape) > currentIndex then |
947 | local scale = width |
948 | local ratched = clone(beltData.ratchet.node, false, false, false) |
949 | link(getChildAt(beltShape, 0), ratched) |
950 | setScale(ratched, scale, scale, scale) |
951 | currentIndex = currentIndex + 1 |
952 | end |
953 | end |
954 | if spec.useHooks then |
955 | if beltData.hook ~= nil and getNumOfChildren(beltShape) > currentIndex+1 then |
956 | local scale = width |
957 | local hookStart = clone(beltData.hook.node, false, false, false) |
958 | link(getChildAt(beltShape, currentIndex), hookStart) |
959 | setScale(hookStart, scale, scale, scale) |
960 | |
961 | local hook2 = beltData.hook2 or beltData.hook |
962 | local hookEnd = clone(hook2.node, false, false, false) |
963 | link(getChildAt(beltShape, currentIndex+1), hookEnd) |
964 | setRotation(hookEnd, 0, math.pi, 0) |
965 | setTranslation(hookEnd, 0, 0, hook2.sizeRatio*width) |
966 | setScale(hookEnd, scale, scale, scale) |
967 | |
968 | setShaderParameter(beltShape, "beltClipOffsets", 0, beltData.hook.sizeRatio*width, beltLength-hook2.sizeRatio*width, beltLength, false) |
969 | end |
970 | end |
971 | |
972 | belt.mesh = beltShape |
973 | spec.belts[beltShape] = beltShape |
974 | if belt.dummy ~= nil then |
975 | delete(belt.dummy) |
976 | belt.dummy = nil |
977 | end |
978 | |
979 | if playSound ~= false and self.isClient then |
980 | g_soundManager:playSample(spec.samples.toggleBelt) |
981 | g_soundManager:playSample(spec.samples.addBelt) |
982 | end |
983 | end |
984 | |
985 | return beltShape |
986 | end |
987 | |
988 | return nil |
989 | end |
freeTensionBeltObject
DescriptionDefinitionfreeTensionBeltObject()Code
647 | function TensionBelts:freeTensionBeltObject(objectId, objectsToJointTable, isDynamic, object) |
648 | if entityExists(objectId) then |
649 | local jointData = objectsToJointTable[objectId] |
650 | if jointData.jointIndex ~= nil then |
651 | if self.isServer then |
652 | if jointData ~= nil then |
653 | removeJoint(jointData.jointIndex) |
654 | delete(jointData.jointTransform) |
655 | |
656 | if object ~= nil then |
657 | if object.setReducedComponentMass ~= nil then |
658 | object:setReducedComponentMass(false) |
659 | self:setMassDirty() |
660 | end |
661 | if object.setCanBeSold ~= nil then |
662 | object:setCanBeSold(true) |
663 | end |
664 | end |
665 | end |
666 | end |
667 | else |
668 | local parentNode |
669 | if jointData ~= nil then |
670 | parentNode = jointData.parent |
671 | end |
672 | if parentNode ~= nil and not entityExists(parentNode) then |
673 | -- For some reason the original parent node was deleted. Delete the attached node too |
674 | delete(objectId) |
675 | else |
676 | if parentNode == nil then |
677 | parentNode = getRootNode() |
678 | end |
679 | local x, y, z = getWorldTranslation(objectId) |
680 | local rx, ry, rz = getWorldRotation(objectId) |
681 | |
682 | if object ~= nil and object.unmountKinematic ~= nil then |
683 | object:unmountKinematic() |
684 | else |
685 | -- only for split shapes on server side |
686 | if self.isServer then |
687 | link(parentNode, objectId) |
688 | setWorldTranslation(objectId, x, y, z) |
689 | setWorldRotation(objectId, rx, ry, rz) |
690 | setRigidBodyType(objectId, RigidBodyType.DYNAMIC) |
691 | end |
692 | end |
693 | end |
694 | end |
695 | end |
696 | |
697 | -- remove objectId from object list |
698 | objectsToJointTable[objectId] = nil |
699 | end |
getAdditionalComponentMass
DescriptionDefinitiongetAdditionalComponentMass()Code
1304 | function TensionBelts:getAdditionalComponentMass(superFunc, component) |
1305 | local additionalMass = superFunc(self, component) |
1306 | |
1307 | local spec = self.spec_tensionBelts |
1308 | if spec.hasTensionBelts then |
1309 | if spec.jointComponent == component.node then |
1310 | for _, objectData in pairs(spec.objectsToJoint) do |
1311 | local object = objectData.object |
1312 | if object ~= nil then |
1313 | if object.getAllowComponentMassReduction ~= nil and object:getAllowComponentMassReduction() then |
1314 | additionalMass = additionalMass + math.max((object:getDefaultMass() - 0.1), 0) |
1315 | end |
1316 | end |
1317 | end |
1318 | end |
1319 | end |
1320 | |
1321 | return additionalMass |
1322 | end |
getCanBeSelected
DescriptionDefinitiongetCanBeSelected()Code
1256 | function TensionBelts:getCanBeSelected(superFunc) |
1257 | return true |
1258 | end |
getFillLevelInformation
DescriptionDefinitiongetFillLevelInformation()Code
1275 | function TensionBelts:getFillLevelInformation(superFunc, display) |
1276 | superFunc(self, display) |
1277 | |
1278 | local spec = self.spec_tensionBelts |
1279 | if spec.hasTensionBelts then |
1280 | for _, objectData in pairs(spec.objectsToJoint) do |
1281 | local object = objectData.object |
1282 | if object ~= nil then |
1283 | if object.getFillLevelInformation ~= nil then |
1284 | object:getFillLevelInformation(display) |
1285 | else |
1286 | if object.getFillLevel ~= nil and object.getFillType ~= nil then |
1287 | local fillType = object:getFillType() |
1288 | local fillLevel = object:getFillLevel() |
1289 | local capacity = fillLevel |
1290 | if object.getCapacity ~= nil then |
1291 | capacity = object:getCapacity() |
1292 | end |
1293 | |
1294 | display:addFillLevel(fillType, fillLevel, capacity) |
1295 | end |
1296 | end |
1297 | end |
1298 | end |
1299 | end |
1300 | end |
getIsDynamicallyMountedNode
DescriptionDefinitiongetIsDynamicallyMountedNode()Code
1229 | function TensionBelts:getIsDynamicallyMountedNode(node) |
1230 | local spec = self.spec_tensionBelts |
1231 | |
1232 | if spec.objectsToJoint ~= nil then |
1233 | for object,_ in pairs(spec.objectsToJoint) do |
1234 | if object == node then |
1235 | return true |
1236 | end |
1237 | end |
1238 | end |
1239 | |
1240 | return false |
1241 | end |
getIsFoldAllowed
DescriptionDefinitiongetIsFoldAllowed()Code
1262 | function TensionBelts:getIsFoldAllowed(superFunc, direction, onAiTurnOn) |
1263 | local spec = self.spec_tensionBelts |
1264 | if not spec.allowFoldingWhileFasten then |
1265 | if not (direction < 0 or not spec.areBeltsFasten) then |
1266 | return false, spec.texts.warningFoldingTensionBelts |
1267 | end |
1268 | end |
1269 | |
1270 | return superFunc(self, direction, onAiTurnOn) |
1271 | end |
getIsPlayerInTensionBeltsRange
DescriptionReturns if player is in tension belt rangeDefinition
getIsPlayerInTensionBeltsRange()Return Values
boolean | inRange | player is in range |
table | belt | nearest belt |
1186 | function TensionBelts:getIsPlayerInTensionBeltsRange() |
1187 | |
1188 | if g_currentMission.player == nil then |
1189 | return false, nil |
1190 | end |
1191 | |
1192 | if not g_currentMission.accessHandler:canPlayerAccess(self) then |
1193 | return false, nil |
1194 | end |
1195 | |
1196 | local spec = self.spec_tensionBelts |
1197 | |
1198 | if spec.beltData ~= nil then |
1199 | local px, py, pz = getWorldTranslation(g_currentMission.player.rootNode) |
1200 | local vx, vy, vz = localToWorld(spec.interactionBaseNode, spec.interactionBasePointX, 0, spec.interactionBasePointZ) |
1201 | local currentBelt = nil |
1202 | local distance = math.huge |
1203 | |
1204 | if MathUtil.vector3Length(px-vx, py-vy, pz-vz) < spec.totalInteractionRadius then |
1205 | if spec.tensionBelts ~= nil then |
1206 | for _, belt in pairs(spec.singleBelts) do |
1207 | local sx, _, sz = getWorldTranslation(belt.startNode) |
1208 | local ex, _, ez = getWorldTranslation(belt.endNode) |
1209 | local sDistance = MathUtil.vector2Length(px-sx, pz-sz) |
1210 | local eDistance = MathUtil.vector2Length(px-ex, pz-ez) |
1211 | if (sDistance < distance and sDistance < spec.interactionRadius) or (eDistance < distance and eDistance < spec.interactionRadius) then |
1212 | currentBelt = belt |
1213 | distance = math.min(sDistance, eDistance) |
1214 | end |
1215 | end |
1216 | end |
1217 | |
1218 | if distance < spec.interactionRadius then |
1219 | return true, currentBelt |
1220 | end |
1221 | end |
1222 | end |
1223 | |
1224 | return false, nil |
1225 | end |
getIsReadyForAutomatedTrainTravel
DescriptionDefinitiongetIsReadyForAutomatedTrainTravel()Code
1245 | function TensionBelts:getIsReadyForAutomatedTrainTravel(superFunc) |
1246 | local spec = self.spec_tensionBelts |
1247 | if spec.hasTensionBelts and spec.numObjectsIntensionBeltRange > 0 then |
1248 | return false |
1249 | end |
1250 | |
1251 | return superFunc(self) |
1252 | end |
getObjectsToUnmount
DescriptionReturns objects to unmount if given belt will be removedDefinition
getObjectsToUnmount(table belt)Arguments
table | belt | belt to check |
table | objectIdsToUnmount | table with object ids to unmount |
integer | numObjects | number of objects to unmount |
1121 | function TensionBelts:getObjectsToUnmount(belt) |
1122 | local spec = self.spec_tensionBelts |
1123 | |
1124 | local objectIdsToUnmount = {} |
1125 | local numObjects = 0 |
1126 | -- copy mounted objects table |
1127 | for objectId, data in pairs(spec.objectsToJoint) do |
1128 | objectIdsToUnmount[objectId] = {objectId=objectId, object=data.object} |
1129 | numObjects = numObjects + 1 |
1130 | end |
1131 | |
1132 | -- remove objects mounted by other active belts |
1133 | for _, otherBelt in pairs(spec.singleBelts) do |
1134 | if otherBelt.mesh ~= nil and otherBelt ~= belt then |
1135 | local objectToMount,_ = self:getObjectToMount(otherBelt) |
1136 | for _, object in pairs(objectToMount) do |
1137 | -- remove objects mounted by other belts |
1138 | if objectIdsToUnmount[object.physics] ~= nil then |
1139 | objectIdsToUnmount[object.physics] = nil |
1140 | numObjects = numObjects - 1 |
1141 | end |
1142 | end |
1143 | end |
1144 | end |
1145 | |
1146 | return objectIdsToUnmount, numObjects |
1147 | end |
getObjectToMount
DescriptionReturns objects in belt rangeDefinition
getObjectToMount(table belt)Arguments
table | belt | belt to check |
table | objectsInTensionBeltRange | object in belt range |
integer | numObjectsIntensionBeltRange | number of objects in belt range |
1020 | function TensionBelts:getObjectToMount(belt) |
1021 | local spec = self.spec_tensionBelts |
1022 | |
1023 | local markerStart = spec.startNode |
1024 | local markerEnd = spec.endNode |
1025 | local offsetLeft = nil |
1026 | local offsetRight = nil |
1027 | local offset = nil |
1028 | local height = nil |
1029 | if belt ~= nil then |
1030 | markerStart = belt.startNode |
1031 | markerEnd = belt.endNode |
1032 | |
1033 | offsetLeft = belt.offsetLeft |
1034 | offsetRight = belt.offsetRight |
1035 | offset = belt.offset |
1036 | height = belt.height |
1037 | if offsetLeft == nil then |
1038 | if spec.sortedBelts[belt.id-1] ~= nil and spec.sortedBelts[belt.id-1].mesh ~= nil then |
1039 | local x,_,_ = localToLocal(markerStart, spec.sortedBelts[belt.id-1].startNode, 0, 0, 0) |
1040 | offsetLeft = math.abs(x) |
1041 | end |
1042 | end |
1043 | if offsetRight == nil then |
1044 | if spec.sortedBelts[belt.id+1] ~= nil and spec.sortedBelts[belt.id+1].mesh ~= nil then |
1045 | local x,_,_ = localToLocal(markerStart, spec.sortedBelts[belt.id+1].startNode, 0, 0, 0) |
1046 | offsetRight = math.abs(x) |
1047 | end |
1048 | end |
1049 | |
1050 | end |
1051 | |
1052 | if offsetLeft == nil then |
1053 | offsetLeft = spec.defaultOffsetSide |
1054 | end |
1055 | if offsetRight == nil then |
1056 | offsetRight = spec.defaultOffsetSide |
1057 | end |
1058 | if offset == nil then |
1059 | offset = spec.defaultOffset |
1060 | end |
1061 | if height == nil then |
1062 | height = spec.defaultHeight |
1063 | end |
1064 | |
1065 | local sizeX = (offsetLeft+offsetRight) * 0.5 |
1066 | local sizeY = height * 0.5 |
1067 | local _, _, width = localToLocal(markerEnd, markerStart, 0, 0, 0) |
1068 | local sizeZ = width*0.5 - 2*offset |
1069 | |
1070 | local centerX = (offsetLeft-offsetRight)*0.5 |
1071 | local centerY = height*0.5 |
1072 | local centerZ = width*0.5 |
1073 | local x,y,z = localToWorld(markerStart, centerX, centerY, centerZ) |
1074 | |
1075 | if TensionBelts.debugRendering then |
1076 | local box = {} |
1077 | box.points = {} |
1078 | local colorR = math.random(0, 1) |
1079 | local colorG = math.random(0, 1) |
1080 | local colorB = math.random(0, 1) |
1081 | box.color = {colorR,colorG,colorB} |
1082 | |
1083 | local blx, bly, blz = localToWorld(markerStart, centerX-sizeX, centerY-sizeY, centerZ-sizeZ) |
1084 | local brx, bry, brz = localToWorld(markerStart, centerX+sizeX, centerY-sizeY, centerZ-sizeZ) |
1085 | local flx, fly, flz = localToWorld(markerStart, centerX-sizeX, centerY-sizeY, centerZ+sizeZ) |
1086 | local frx, fry, frz = localToWorld(markerStart, centerX+sizeX, centerY-sizeY, centerZ+sizeZ) |
1087 | |
1088 | local tblx, tbly, tblz = localToWorld(markerStart, centerX-sizeX, centerY+sizeY, centerZ-sizeZ) |
1089 | local tbrx, tbry, tbrz = localToWorld(markerStart, centerX+sizeX, centerY+sizeY, centerZ-sizeZ) |
1090 | local tflx, tfly, tflz = localToWorld(markerStart, centerX-sizeX, centerY+sizeY, centerZ+sizeZ) |
1091 | local tfrx, tfry, tfrz = localToWorld(markerStart, centerX+sizeX, centerY+sizeY, centerZ+sizeZ) |
1092 | |
1093 | table.insert(box.points, { blx, bly, blz } ) -- lower: lb |
1094 | table.insert(box.points, { brx, bry, brz } ) -- rb |
1095 | table.insert(box.points, { frx, fry, frz } ) -- rf |
1096 | table.insert(box.points, { flx, fly, flz } ) -- lf |
1097 | |
1098 | table.insert(box.points, { tblx, tbly, tblz } ) -- upper: lb |
1099 | table.insert(box.points, { tbrx, tbry, tbrz } ) -- rb |
1100 | table.insert(box.points, { tfrx, tfry, tfrz } ) -- rf |
1101 | table.insert(box.points, { tflx, tfly, tflz } ) -- lf |
1102 | table.insert(box.points, { x, y, z } ) -- center |
1103 | |
1104 | spec.checkBoxes[markerStart] = box |
1105 | end |
1106 | |
1107 | local rx,ry,rz = getWorldRotation(markerStart) |
1108 | spec.objectsInTensionBeltRange = {} |
1109 | spec.numObjectsIntensionBeltRange = 0 |
1110 | |
1111 | overlapBox(x, y, z, rx, ry, rz, sizeX, sizeY, sizeZ, "objectOverlapCallback", self, CollisionMask.TRIGGER_DYNAMIC_MOUNT, true, false, true) |
1112 | |
1113 | return spec.objectsInTensionBeltRange, spec.numObjectsIntensionBeltRange |
1114 | end |
initSpecialization
DescriptionDefinitioninitSpecialization()Code
27 | function TensionBelts.initSpecialization() |
28 | g_configurationManager:addConfigurationType("tensionBelts", g_i18n:getText("configuration_tensionBelts"), "tensionBelts", nil, nil, nil, ConfigurationUtil.SELECTOR_MULTIOPTION) |
29 | |
30 | local schema = Vehicle.xmlSchema |
31 | schema:setXMLSpecializationType("TensionBelts") |
32 | |
33 | local key = "vehicle.tensionBelts.tensionBeltsConfigurations.tensionBeltsConfiguration(?).tensionBelts" |
34 | ObjectChangeUtil.registerObjectChangeXMLPaths(schema, "vehicle.tensionBelts.tensionBeltsConfigurations.tensionBeltsConfiguration(?)") |
35 | |
36 | schema:register(XMLValueType.FLOAT, key .. "#totalInteractionRadius", "Total interaction radius", 6) |
37 | schema:register(XMLValueType.FLOAT, key .. "#interactionRadius", "Interaction radius", 1) |
38 | schema:register(XMLValueType.NODE_INDEX, key .. "#interactionBaseNode", "Interaction base node", "Vehicle root node") |
39 | schema:register(XMLValueType.NODE_INDEX, key .. "#activationTrigger", "Activation trigger") |
40 | schema:register(XMLValueType.STRING, key .. "#tensionBeltType", "Supports tension belts", "basic") |
41 | |
42 | schema:register(XMLValueType.FLOAT, key .. "#width", "Belt width", "Used from belt definitions") |
43 | schema:register(XMLValueType.FLOAT, key .. "#ratchetPosition", "Ratchet position") |
44 | schema:register(XMLValueType.BOOL, key .. "#useHooks", "Use hooks", true) |
45 | schema:register(XMLValueType.FLOAT, key .. "#maxEdgeLength", "Max. edge length", 0.1) |
46 | schema:register(XMLValueType.FLOAT, key .. "#geometryBias", "Geometry bias", 0.01) |
47 | schema:register(XMLValueType.FLOAT, key .. "#defaultOffsetSide", "Default offset side", 0.1) |
48 | schema:register(XMLValueType.FLOAT, key .. "#defaultOffset", "Default offset", 0) |
49 | schema:register(XMLValueType.FLOAT, key .. "#defaultHeight", "Default height", 5) |
50 | |
51 | schema:register(XMLValueType.BOOL, key .. "#allowFoldingWhileFasten", "Folding is allowed while tension belts are fasten", true) |
52 | |
53 | schema:register(XMLValueType.NODE_INDEX, key .. "#linkNode", "Link node") |
54 | schema:register(XMLValueType.NODE_INDEX, key .. "#rootNode", "Root node", "Root component") |
55 | schema:register(XMLValueType.NODE_INDEX, key .. "#jointNode", "Joint node", "rootNode") |
56 | |
57 | schema:register(XMLValueType.NODE_INDEX, key .. ".tensionBelt(?)#startNode", "Start node") |
58 | schema:register(XMLValueType.NODE_INDEX, key .. ".tensionBelt(?)#endNode", "End node") |
59 | schema:register(XMLValueType.FLOAT, key .. ".tensionBelt(?)#offsetLeft", "Offset left") |
60 | schema:register(XMLValueType.FLOAT, key .. ".tensionBelt(?)#offsetRight", "Offset right") |
61 | schema:register(XMLValueType.FLOAT, key .. ".tensionBelt(?)#offset", "Offset") |
62 | schema:register(XMLValueType.FLOAT, key .. ".tensionBelt(?)#height", "Height") |
63 | schema:register(XMLValueType.NODE_INDEX, key .. ".tensionBelt(?).intersectionNode(?)#node", "Intersection node") |
64 | |
65 | SoundManager.registerSampleXMLPaths(schema, key .. ".sounds", "toggleBelt") |
66 | SoundManager.registerSampleXMLPaths(schema, key .. ".sounds", "addBelt") |
67 | SoundManager.registerSampleXMLPaths(schema, key .. ".sounds", "removeBelt") |
68 | |
69 | schema:setXMLSpecializationType() |
70 | |
71 | local schemaSavegame = Vehicle.xmlSchemaSavegame |
72 | schemaSavegame:register(XMLValueType.BOOL, "vehicles.vehicle(?).tensionBelts.belt(?)#isActive", "Belt is active", false) |
73 | end |
lockTensionBeltObject
DescriptionDefinitionlockTensionBeltObject()Code
703 | function TensionBelts:lockTensionBeltObject(objectId, objectsToJointTable, isDynamic, jointNode, object) |
704 | if objectsToJointTable[objectId] == nil then |
705 | local useDynamicMount = false |
706 | local useKinematicMount = false |
707 | local useSplitShapeMount = false |
708 | |
709 | if isDynamic then |
710 | if self.isServer then |
711 | useDynamicMount = true |
712 | end |
713 | else |
714 | if object ~= nil and object.mountKinematic ~= nil then |
715 | local allowKinematicMounting = true |
716 | if object.getSupportsMountKinematic ~= nil and not object:getSupportsMountKinematic() then |
717 | allowKinematicMounting = false |
718 | end |
719 | |
720 | if object.rootVehicle ~= nil then |
721 | local vehicles = object.rootVehicle.childVehicles |
722 | if #vehicles > 1 then |
723 | allowKinematicMounting = false |
724 | end |
725 | end |
726 | |
727 | if allowKinematicMounting then |
728 | useKinematicMount = true |
729 | else |
730 | useDynamicMount = true |
731 | end |
732 | else |
733 | -- only for split shapes on server side |
734 | if self.isServer then |
735 | useSplitShapeMount = true |
736 | end |
737 | end |
738 | end |
739 | |
740 | if useDynamicMount then |
741 | local constr = JointConstructor.new() |
742 | constr:setActors(jointNode, objectId) |
743 | |
744 | -- create joint at center of mass to avoid jittering (e.g. tree trunks pivots are not at center of mass position) |
745 | -- create a transformGroup at the joint position to move the joint afterwards based on this transformGroup |
746 | local jointTransform = createTransformGroup("tensionBeltJoint") |
747 | link(self.spec_tensionBelts.linkNode, jointTransform) |
748 | local x,y,z = localToWorld(objectId, getCenterOfMass(objectId)) |
749 | setWorldTranslation(jointTransform, x,y,z) |
750 | |
751 | constr:setJointTransforms(jointTransform, jointTransform) |
752 | |
753 | constr:setRotationLimit(0, 0, 0) |
754 | constr:setRotationLimit(1, 0, 0) |
755 | constr:setRotationLimit(2, 0, 0) |
756 | |
757 | local springForce = 1000 |
758 | local springDamping = 10 |
759 | constr:setRotationLimitSpring(springForce, springDamping, springForce, springDamping, springForce, springDamping) |
760 | constr:setTranslationLimitSpring(springForce, springDamping, springForce, springDamping, springForce, springDamping) |
761 | local jointIndex = constr:finalize() |
762 | |
763 | if object ~= nil then |
764 | if object.setReducedComponentMass ~= nil then |
765 | object:setReducedComponentMass(true) |
766 | self:setMassDirty() |
767 | end |
768 | if object.setCanBeSold ~= nil then |
769 | object:setCanBeSold(false) |
770 | end |
771 | end |
772 | |
773 | objectsToJointTable[objectId] = {jointIndex=jointIndex, jointTransform=jointTransform, object=object} |
774 | elseif useKinematicMount then |
775 | local parentNode = getParent(objectId) |
776 | local x, y, z = localToLocal(objectId, jointNode, 0, 0, 0) |
777 | local rx, ry, rz = localRotationToLocal(objectId, jointNode, 0, 0, 0) |
778 | |
779 | object:mountKinematic(self, jointNode, x, y, z, rx, ry, rz) |
780 | |
781 | objectsToJointTable[objectId] = {parent=parentNode, object=object} |
782 | elseif useSplitShapeMount then |
783 | local parentNode = getParent(objectId) |
784 | local x, y, z = localToLocal(objectId, jointNode, 0, 0, 0) |
785 | local rx, ry, rz = localRotationToLocal(objectId, jointNode, 0, 0, 0) |
786 | |
787 | setRigidBodyType(objectId, RigidBodyType.KINEMATIC) |
788 | link(jointNode, objectId) |
789 | setTranslation(objectId, x, y, z) |
790 | setRotation(objectId, rx, ry, rz) |
791 | objectsToJointTable[objectId] = {parent=parentNode, object=object} |
792 | end |
793 | end |
794 | end |
objectOverlapCallback
DescriptionOverlap callbackDefinition
objectOverlapCallback(integer transformId)Arguments
integer | transformId | id of found transform |
1152 | function TensionBelts:objectOverlapCallback(transformId) |
1153 | if transformId ~= 0 and getHasClassId(transformId, ClassIds.SHAPE) then |
1154 | local spec = self.spec_tensionBelts |
1155 | |
1156 | local object = g_currentMission:getNodeObject(transformId) |
1157 | if object ~= nil and object ~= self and (object.rootVehicle ~= self.rootVehicle) then |
1158 | if object.getSupportsTensionBelts ~= nil and object:getSupportsTensionBelts() then |
1159 | if object.getMeshNodes ~= nil and object.dynamicMountObject == nil then |
1160 | local nodeId = object:getTensionBeltNodeId() |
1161 | if spec.objectsInTensionBeltRange[nodeId] == nil then |
1162 | local nodes = object:getMeshNodes() |
1163 | if nodes ~= nil then |
1164 | spec.objectsInTensionBeltRange[nodeId] = {physics=nodeId, visuals=nodes, object=object} |
1165 | spec.numObjectsIntensionBeltRange = spec.numObjectsIntensionBeltRange + 1 |
1166 | end |
1167 | end |
1168 | end |
1169 | end |
1170 | elseif getSplitType(transformId) ~= 0 then |
1171 | local rigidBodyType = getRigidBodyType(transformId) |
1172 | if (rigidBodyType == RigidBodyType.DYNAMIC or rigidBodyType == RigidBodyType.KINEMATIC) and spec.objectsInTensionBeltRange[transformId] == nil then |
1173 | spec.objectsInTensionBeltRange[transformId] = {physics=transformId, visuals={transformId}} |
1174 | spec.numObjectsIntensionBeltRange = spec.numObjectsIntensionBeltRange + 1 |
1175 | end |
1176 | end |
1177 | end |
1178 | |
1179 | return true |
1180 | end |
onDelete
DescriptionCalled on deletingDefinition
onDelete()Code
384 | function TensionBelts:onDelete() |
385 | local spec = self.spec_tensionBelts |
386 | |
387 | spec.isPlayerInRange = false |
388 | g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable) |
389 | self:setTensionBeltsActive(false, nil, true, false) |
390 | |
391 | if spec.activationTrigger ~= nil then |
392 | removeTrigger(spec.activationTrigger) |
393 | spec.activationTrigger = nil |
394 | end |
395 | |
396 | g_soundManager:deleteSamples(spec.samples) |
397 | 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 |
607 | function TensionBelts:onDraw(isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
608 | local spec = self.spec_tensionBelts |
609 | |
610 | if not spec.hasTensionBelts then |
611 | return |
612 | end |
613 | |
614 | if isActiveForInputIgnoreSelection and isSelected then |
615 | if spec.areBeltsFasten then |
616 | g_currentMission:addHelpButtonText(g_i18n:getText("action_unfastenTensionBelts"), InputBinding.TOGGLE_TENSION_BELTS, nil, GS_PRIO_NORMAL) |
617 | else |
618 | g_currentMission:addHelpButtonText(g_i18n:getText("action_fastenTensionBelts"), InputBinding.TOGGLE_TENSION_BELTS, nil, GS_PRIO_NORMAL) |
619 | end |
620 | end |
621 | |
622 | -- for _, d in pairs(spec.objectsToJoint) do |
623 | -- local node = d.jointTransform |
624 | -- DebugUtil.drawDebugNode(node, getName(node)) |
625 | -- end |
626 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
123 | function TensionBelts:onLoad(savegame) |
124 | local spec = self.spec_tensionBelts |
125 | |
126 | local tensionBeltConfigurationId = Utils.getNoNil(self.configurations["tensionBelts"], 1) |
127 | local configKey = string.format("vehicle.tensionBelts.tensionBeltsConfigurations.tensionBeltsConfiguration(%d).tensionBelts", tensionBeltConfigurationId -1) |
128 | ObjectChangeUtil.updateObjectChanges(self.xmlFile, "vehicle.tensionBelts.tensionBeltsConfigurations.tensionBeltsConfiguration", tensionBeltConfigurationId , self.components, self) |
129 | |
130 | |
131 | spec.hasTensionBelts = true |
132 | if not self.xmlFile:hasProperty(configKey) then |
133 | spec.hasTensionBelts = false |
134 | |
135 | SpecializationUtil.removeEventListener(self, "onPostLoad", TensionBelts) |
136 | SpecializationUtil.removeEventListener(self, "onDelete", TensionBelts) |
137 | SpecializationUtil.removeEventListener(self, "onPreDelete", TensionBelts) |
138 | SpecializationUtil.removeEventListener(self, "onReadStream", TensionBelts) |
139 | SpecializationUtil.removeEventListener(self, "onWriteStream", TensionBelts) |
140 | SpecializationUtil.removeEventListener(self, "onUpdate", TensionBelts) |
141 | SpecializationUtil.removeEventListener(self, "onUpdateTick", TensionBelts) |
142 | SpecializationUtil.removeEventListener(self, "onDraw", TensionBelts) |
143 | SpecializationUtil.removeEventListener(self, "onRegisterActionEvents", TensionBelts) |
144 | |
145 | return |
146 | end |
147 | |
148 | spec.belts = {} |
149 | spec.tensionBelts = {} |
150 | spec.singleBelts = {} |
151 | spec.sortedBelts = {} |
152 | |
153 | spec.activatable = TensionBeltsActivatable.new(self) |
154 | |
155 | spec.totalInteractionRadius = self.xmlFile:getValue(configKey.."#totalInteractionRadius", 6) |
156 | spec.interactionRadius = self.xmlFile:getValue(configKey.."#interactionRadius", 1) |
157 | spec.interactionBaseNode = self.xmlFile:getValue(configKey.."#interactionBaseNode", self.rootNode, self.components, self.i3dMappings) |
158 | spec.activationTrigger = self.xmlFile:getValue(configKey.."#activationTrigger", nil, self.components, self.i3dMappings) |
159 | if spec.activationTrigger ~= nil then |
160 | if not CollisionFlag.getHasFlagSet(spec.activationTrigger, CollisionFlag.TRIGGER_PLAYER) then |
161 | Logging.xmlError(self.xmlFile, "Missing player collision mask bit '%d' for tension belt trigger.", CollisionFlag.getBit(CollisionFlag.TRIGGER_PLAYER)) |
162 | else |
163 | addTrigger(spec.activationTrigger, "tensionBeltActivationTriggerCallback", self) |
164 | end |
165 | end |
166 | |
167 | spec.allowFoldingWhileFasten = self.xmlFile:getValue(configKey.."#allowFoldingWhileFasten", true) |
168 | |
169 | spec.isPlayerInTrigger = false |
170 | spec.checkSizeOffsets = {0*0.5, 5*0.5, 3*0.5} |
171 | spec.numObjectsIntensionBeltRange = 0 |
172 | |
173 | local tensionBeltType = self.xmlFile:getValue(configKey.."#tensionBeltType", "basic") |
174 | local beltData = g_tensionBeltManager:getBeltData(tensionBeltType) |
175 | |
176 | if beltData ~= nil then |
177 | spec.width = self.xmlFile:getValue(configKey.."#width") |
178 | spec.ratchetPosition = self.xmlFile:getValue(configKey.."#ratchetPosition") |
179 | spec.useHooks = self.xmlFile:getValue(configKey.."#useHooks", true) |
180 | spec.maxEdgeLength = self.xmlFile:getValue(configKey.."#maxEdgeLength", 0.1) |
181 | spec.geometryBias = self.xmlFile:getValue(configKey.."#geometryBias", 0.01) |
182 | spec.defaultOffsetSide = self.xmlFile:getValue(configKey.."#defaultOffsetSide", 0.1) |
183 | spec.defaultOffset = self.xmlFile:getValue(configKey.."#defaultOffset", 0) |
184 | spec.defaultHeight = self.xmlFile:getValue(configKey.."#defaultHeight", 5) |
185 | spec.beltData = beltData |
186 | spec.linkNode = self.xmlFile:getValue(configKey.."#linkNode", nil, self.components, self.i3dMappings) |
187 | spec.rootNode = self.xmlFile:getValue(configKey.."#rootNode", self.components[1].node, self.components, self.i3dMappings) |
188 | spec.jointNode = self.xmlFile:getValue(configKey.."#jointNode", spec.rootNode, self.components, self.i3dMappings) |
189 | spec.checkTimerDuration = 500 |
190 | spec.checkTimer = spec.checkTimerDuration |
191 | |
192 | if spec.linkNode == nil then |
193 | Logging.xmlError(self.xmlFile, "No tension belts link node given at %s%s", configKey, "#linkNode") |
194 | self:setLoadingState(VehicleLoadingUtil.VEHICLE_LOAD_ERROR) |
195 | return |
196 | end |
197 | |
198 | if getRigidBodyType(spec.jointNode) ~= RigidBodyType.DYNAMIC and getRigidBodyType(spec.jointNode) ~= RigidBodyType.KINEMATIC then |
199 | Logging.xmlError(self.xmlFile, "Given jointNode '"..getName(spec.jointNode).."' has invalid rigidBodyType. Have to be 'Dynamic' or 'Kinematic'! Using '"..getName(self.components[1].node).."' instead!") |
200 | spec.jointNode = self.components[1].node |
201 | end |
202 | |
203 | local rigidBodyType = getRigidBodyType(spec.jointNode) |
204 | spec.isDynamic = rigidBodyType == RigidBodyType.DYNAMIC |
205 | |
206 | local x,y,z = localToLocal(spec.linkNode, spec.jointNode, 0,0,0) |
207 | local rx,ry,rz = localRotationToLocal(spec.linkNode, spec.jointNode, 0,0,0) |
208 | spec.linkNodePosition = {x, y, z} |
209 | spec.linkNodeRotation = {rx, ry, rz} |
210 | |
211 | spec.jointComponent = self:getParentComponent(spec.jointNode) |
212 | |
213 | local i = 0 |
214 | while true do |
215 | local key = string.format(configKey..".tensionBelt(%d)", i) |
216 | if not self.xmlFile:hasProperty(key) then |
217 | break |
218 | end |
219 | |
220 | if #spec.sortedBelts == 2^TensionBelts.NUM_SEND_BITS then |
221 | Logging.xmlWarning(self.xmlFile, "Max number of tension belts is ".. 2^TensionBelts.NUM_SEND_BITS.."!") |
222 | break |
223 | end |
224 | |
225 | local startNode = self.xmlFile:getValue(key.."#startNode", nil, self.components, self.i3dMappings) |
226 | local endNode = self.xmlFile:getValue(key.."#endNode", nil, self.components, self.i3dMappings) |
227 | if startNode ~= nil and endNode ~= nil then |
228 | local endX,endY,_ = getTranslation(endNode) |
229 | if math.abs(endX) < 0.0001 and math.abs(endY) < 0.0001 then |
230 | if spec.linkNode == nil then |
231 | spec.linkNode = getParent(startNode) |
232 | end |
233 | if spec.startNode == nil then |
234 | spec.startNode = startNode |
235 | end |
236 | spec.endNode = endNode |
237 | |
238 | local offsetLeft = self.xmlFile:getValue(key.."#offsetLeft") |
239 | local offsetRight = self.xmlFile:getValue(key.."#offsetRight") |
240 | local offset = self.xmlFile:getValue(key.."#offset") |
241 | local height = self.xmlFile:getValue(key.."#height") |
242 | |
243 | local intersectionNodes = {} |
244 | local j = 0 |
245 | while true do |
246 | local intersectionKey = string.format(key..".intersectionNode(%d)", j) |
247 | if not self.xmlFile:hasProperty(intersectionKey) then |
248 | break |
249 | end |
250 | local node = self.xmlFile:getValue(intersectionKey.."#node", nil, self.components, self.i3dMappings) |
251 | if node ~= nil then |
252 | table.insert(intersectionNodes, node) |
253 | end |
254 | j = j + 1 |
255 | end |
256 | |
257 | local belt = {id=i+1, startNode=startNode, endNode=endNode, offsetLeft=offsetLeft, offsetRight=offsetRight, offset=offset, height=height, mesh=nil, intersectionNodes=intersectionNodes, dummy=nil, objectsToMount=nil} |
258 | spec.singleBelts[belt] = belt |
259 | table.insert(spec.sortedBelts, belt) |
260 | else |
261 | Logging.xmlWarning(self.xmlFile, "x and y position of endNode need to be 0 for tension belt '"..key.."'") |
262 | end |
263 | end |
264 | |
265 | i = i + 1 |
266 | end |
267 | |
268 | local minX, minZ = math.huge, math.huge |
269 | local maxX, maxZ = -math.huge, -math.huge |
270 | for _, belt in pairs(spec.singleBelts) do |
271 | local sx,_,sz = localToLocal(belt.startNode, spec.interactionBaseNode, 0, 0, 0) |
272 | local ex,_,ez = localToLocal(belt.endNode, spec.interactionBaseNode, 0, 0, 0) |
273 | minX = math.min(minX, sx, ex) |
274 | minZ = math.min(minZ, sz, ez) |
275 | maxX = math.max(maxX, sx, ex) |
276 | maxZ = math.max(maxZ, sz, ez) |
277 | end |
278 | |
279 | spec.interactionBasePointX = (maxX + minX) / 2 |
280 | spec.interactionBasePointZ = (maxZ + minZ) / 2 |
281 | |
282 | for _, belt in pairs(spec.singleBelts) do |
283 | local sx,_,sz = localToLocal(belt.startNode, spec.interactionBaseNode, 0, 0, 0) |
284 | local sl = MathUtil.vector2Length(spec.interactionBasePointX-sx, spec.interactionBasePointZ-sz)+1 |
285 | local el = MathUtil.vector2Length(spec.interactionBasePointX-sx, spec.interactionBasePointZ-sz)+1 |
286 | spec.totalInteractionRadius = math.max(spec.totalInteractionRadius, sl, el) |
287 | end |
288 | |
289 | else |
290 | Logging.xmlWarning(self.xmlFile, "No belt data found for tension belt type %s", tensionBeltType) |
291 | end |
292 | |
293 | spec.hasTensionBelts = #spec.sortedBelts > 0 |
294 | |
295 | spec.checkBoxes = {} |
296 | spec.objectsToJoint = {} |
297 | spec.isPlayerInRange = false |
298 | spec.currentBelt = nil |
299 | spec.areBeltsFasten = false |
300 | spec.fastedAllBeltsIndex = -1 |
301 | spec.fastedAllBeltsState = true |
302 | |
303 | if self.isClient then |
304 | spec.samples = {} |
305 | spec.samples.toggleBelt = g_soundManager:loadSampleFromXML(self.xmlFile, configKey .. ".sounds", "toggleBelt", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
306 | spec.samples.addBelt = g_soundManager:loadSampleFromXML(self.xmlFile, configKey .. ".sounds", "addBelt", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
307 | spec.samples.removeBelt = g_soundManager:loadSampleFromXML(self.xmlFile, configKey .. ".sounds", "removeBelt", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
308 | end |
309 | |
310 | spec.texts = {} |
311 | spec.texts.warningFoldingTensionBelts = g_i18n:getText("warning_foldingNotWhileTensionBeltsFasten") |
312 | |
313 | if not spec.hasTensionBelts then |
314 | SpecializationUtil.removeEventListener(self, "onPostLoad", TensionBelts) |
315 | SpecializationUtil.removeEventListener(self, "onDelete", TensionBelts) |
316 | SpecializationUtil.removeEventListener(self, "onPreDelete", TensionBelts) |
317 | SpecializationUtil.removeEventListener(self, "onReadStream", TensionBelts) |
318 | SpecializationUtil.removeEventListener(self, "onWriteStream", TensionBelts) |
319 | SpecializationUtil.removeEventListener(self, "onUpdate", TensionBelts) |
320 | SpecializationUtil.removeEventListener(self, "onUpdateTick", TensionBelts) |
321 | SpecializationUtil.removeEventListener(self, "onDraw", TensionBelts) |
322 | SpecializationUtil.removeEventListener(self, "onRegisterActionEvents", TensionBelts) |
323 | |
324 | -- delete activation trigger as onDelete event is removed |
325 | if spec.activationTrigger ~= nil then |
326 | removeTrigger(spec.activationTrigger) |
327 | spec.activationTrigger = nil |
328 | end |
329 | else |
330 | g_messageCenter:subscribe(MessageType.TREE_SHAPE_CUT, self.onTensionBeltTreeShapeCut, self) |
331 | end |
332 | end |
onPostLoad
DescriptionCalled after loadingDefinition
onPostLoad(table savegame)Arguments
table | savegame | savegame |
337 | function TensionBelts:onPostLoad(savegame) |
338 | if savegame ~= nil then |
339 | local spec = self.spec_tensionBelts |
340 | |
341 | spec.beltsToLoad = {} |
342 | local i = 0 |
343 | while true do |
344 | local key = string.format("%s.tensionBelts.belt(%d)", savegame.key, i) |
345 | if not savegame.xmlFile:hasProperty(key) then |
346 | break |
347 | end |
348 | if savegame.xmlFile:getValue(key.."#isActive") then |
349 | table.insert(spec.beltsToLoad, i+1) |
350 | end |
351 | i = i + 1 |
352 | end |
353 | end |
354 | end |
onPreDelete
DescriptionDefinitiononPreDelete()Code
371 | function TensionBelts:onPreDelete() |
372 | if self.spec_tensionBelts.sortedBelts ~= nil then |
373 | for _, belt in pairs(self.spec_tensionBelts.sortedBelts) do |
374 | local objects, _ = self:getObjectToMount(belt) |
375 | for id, _ in pairs(objects) do |
376 | I3DUtil.wakeUpObject(id) |
377 | end |
378 | end |
379 | end |
380 | end |
onReadStream
DescriptionCalled on client side on joinDefinition
onReadStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
403 | function TensionBelts:onReadStream(streamId, connection) |
404 | local spec = self.spec_tensionBelts |
405 | |
406 | if spec.tensionBelts ~= nil then |
407 | spec.beltsToLoad = {} |
408 | for k, _ in ipairs(spec.sortedBelts) do |
409 | local beltActive = streamReadBool(streamId) |
410 | if beltActive then |
411 | table.insert(spec.beltsToLoad, k) |
412 | end |
413 | end |
414 | end |
415 | end |
onRegisterActionEvents
DescriptionDefinitiononRegisterActionEvents()Code
1327 | function TensionBelts:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
1328 | local spec = self.spec_tensionBelts |
1329 | if self.isClient and spec.hasTensionBelts then |
1330 | self:clearActionEventsTable(spec.actionEvents) |
1331 | |
1332 | if isActiveForInputIgnoreSelection then |
1333 | local _, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_TENSION_BELTS, self, TensionBelts.actionEventToggleTensionBelts, false, true, false, true, nil) |
1334 | g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL) |
1335 | end |
1336 | end |
1337 | end |
onTensionBeltTreeShapeCut
DescriptionDefinitiononTensionBeltTreeShapeCut()Code
1359 | function TensionBelts:onTensionBeltTreeShapeCut(oldShape, shape) |
1360 | if self.isServer then |
1361 | local spec = self.spec_tensionBelts |
1362 | for objectId, data in pairs(spec.objectsToJoint) do |
1363 | if objectId == oldShape then |
1364 | self:setAllTensionBeltsActive(false) |
1365 | end |
1366 | end |
1367 | end |
1368 | 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 |
436 | function TensionBelts:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
437 | local spec = self.spec_tensionBelts |
438 | |
439 | if spec.beltsToLoad ~= nil then |
440 | if #spec.beltsToLoad > 0 then |
441 | local beltIndex = spec.beltsToLoad[#spec.beltsToLoad] |
442 | |
443 | local noEventSend = false |
444 | if not self.isServer then |
445 | -- do not resend event to server after sync. Only send event after loading to make sure client have visible tension belts |
446 | noEventSend = true |
447 | end |
448 | self:setTensionBeltsActive(true, spec.sortedBelts[beltIndex].id, noEventSend, false) |
449 | |
450 | table.remove(spec.beltsToLoad, #spec.beltsToLoad) |
451 | else |
452 | spec.beltsToLoad = nil |
453 | end |
454 | end |
455 | |
456 | if self.isServer and spec.isDynamic then |
457 | local x,y,z = localToLocal(spec.linkNode, spec.jointNode, 0,0,0) |
458 | local rx,ry,rz = localRotationToLocal(spec.linkNode, spec.jointNode, 0,0,0) |
459 | |
460 | local isDirty = false |
461 | if math.abs(x - spec.linkNodePosition[1]) > 0.001 or math.abs(y - spec.linkNodePosition[2]) > 0.001 or math.abs(z - spec.linkNodePosition[3]) > 0.001 or |
462 | math.abs(rx - spec.linkNodeRotation[1]) > 0.001 or math.abs(ry - spec.linkNodeRotation[2]) > 0.001 or math.abs(rz - spec.linkNodeRotation[3]) > 0.001 then |
463 | isDirty = true |
464 | end |
465 | if isDirty then |
466 | spec.linkNodePosition[1], spec.linkNodePosition[2], spec.linkNodePosition[3] = x, y, z |
467 | spec.linkNodeRotation[1], spec.linkNodeRotation[2], spec.linkNodeRotation[3] = rx, ry, rz |
468 | for _, joint in pairs(spec.objectsToJoint) do |
469 | setJointFrame(joint.jointIndex, 0, joint.jointTransform) |
470 | end |
471 | end |
472 | end |
473 | |
474 | if self.isClient then |
475 | if spec.fastedAllBeltsIndex > 0 then |
476 | local belt = spec.sortedBelts[spec.fastedAllBeltsIndex] |
477 | if belt ~= nil then |
478 | self:setTensionBeltsActive(spec.fastedAllBeltsState, belt.id, false) |
479 | end |
480 | |
481 | spec.fastedAllBeltsIndex = spec.fastedAllBeltsIndex + 1 |
482 | if spec.fastedAllBeltsIndex > #spec.sortedBelts then |
483 | spec.fastedAllBeltsIndex = -1 |
484 | end |
485 | end |
486 | end |
487 | |
488 | if TensionBelts.debugRendering then |
489 | for belt,_ in pairs(spec.belts) do |
490 | DebugUtil.drawDebugNode(belt) |
491 | for i=0, getNumOfChildren(belt)-1 do |
492 | DebugUtil.drawDebugNode(getChildAt(belt, i)) |
493 | end |
494 | end |
495 | |
496 | if spec.checkBoxes ~= nil then |
497 | for _, box in pairs(spec.checkBoxes) do |
498 | local p = box.points |
499 | local c = box.color |
500 | |
501 | -- bottom |
502 | drawDebugLine(p[1][1],p[1][2],p[1][3], c[1],c[2],c[3], p[2][1],p[2][2],p[2][3], c[1],c[2],c[3]) |
503 | drawDebugLine(p[2][1],p[2][2],p[2][3], c[1],c[2],c[3], p[3][1],p[3][2],p[3][3], c[1],c[2],c[3]) |
504 | drawDebugLine(p[3][1],p[3][2],p[3][3], c[1],c[2],c[3], p[4][1],p[4][2],p[4][3], c[1],c[2],c[3]) |
505 | drawDebugLine(p[4][1],p[4][2],p[4][3], c[1],c[2],c[3], p[1][1],p[1][2],p[1][3], c[1],c[2],c[3]) |
506 | -- top |
507 | drawDebugLine(p[5][1],p[5][2],p[5][3], c[1],c[2],c[3], p[6][1],p[6][2],p[6][3], c[1],c[2],c[3]) |
508 | drawDebugLine(p[6][1],p[6][2],p[6][3], c[1],c[2],c[3], p[7][1],p[7][2],p[7][3], c[1],c[2],c[3]) |
509 | drawDebugLine(p[7][1],p[7][2],p[7][3], c[1],c[2],c[3], p[8][1],p[8][2],p[8][3], c[1],c[2],c[3]) |
510 | drawDebugLine(p[8][1],p[8][2],p[8][3], c[1],c[2],c[3], p[5][1],p[5][2],p[5][3], c[1],c[2],c[3]) |
511 | -- left |
512 | drawDebugLine(p[1][1],p[1][2],p[1][3], c[1],c[2],c[3], p[5][1],p[5][2],p[5][3], c[1],c[2],c[3]) |
513 | drawDebugLine(p[4][1],p[4][2],p[4][3], c[1],c[2],c[3], p[8][1],p[8][2],p[8][3], c[1],c[2],c[3]) |
514 | -- right |
515 | drawDebugLine(p[2][1],p[2][2],p[2][3], c[1],c[2],c[3], p[6][1],p[6][2],p[6][3], c[1],c[2],c[3]) |
516 | drawDebugLine(p[3][1],p[3][2],p[3][3], c[1],c[2],c[3], p[7][1],p[7][2],p[7][3], c[1],c[2],c[3]) |
517 | drawDebugPoint(p[9][1], p[9][2], p[9][3], 1, 1, 1, 1) |
518 | end |
519 | end |
520 | |
521 | local a,b,c = localToWorld(spec.interactionBaseNode, spec.interactionBasePointX, 0, spec.interactionBasePointZ) |
522 | drawDebugPoint(a,b,c, 0,0,1, 1,1,1,1) |
523 | |
524 | for i=0, 360-10, 10 do |
525 | local x,y,z = localToWorld(spec.interactionBaseNode, spec.interactionBasePointX+math.cos(math.rad(i))*spec.totalInteractionRadius,0, spec.interactionBasePointZ+math.sin(math.rad(i))*spec.totalInteractionRadius) |
526 | drawDebugPoint(x, y, z, 1,1,1,1) |
527 | for _, belt in pairs(spec.singleBelts) do |
528 | x,y,z = localToWorld(belt.startNode, math.cos(math.rad(i))*spec.interactionRadius, 0, math.sin(math.rad(i))*spec.interactionRadius) |
529 | drawDebugPoint(x, y, z, 0,1,0,1) |
530 | x,y,z = localToWorld(belt.endNode, math.cos(math.rad(i))*spec.interactionRadius, 0, math.sin(math.rad(i))*spec.interactionRadius) |
531 | drawDebugPoint(x, y, z, 1,0,0,1) |
532 | end |
533 | end |
534 | end |
535 | |
536 | if spec.isPlayerInTrigger or spec.isPlayerInRange then |
537 | self:raiseActive() |
538 | end |
539 | |
540 | -- create tension belt preview and control activation |
541 | local currentBelt |
542 | local wasInRange = spec.isPlayerInRange |
543 | spec.isPlayerInRange, currentBelt = self:getIsPlayerInTensionBeltsRange() |
544 | if spec.isPlayerInRange then |
545 | if currentBelt ~= spec.currentBelt then |
546 | if spec.currentBelt ~= nil and spec.currentBelt.dummy ~= nil then |
547 | delete(spec.currentBelt.dummy) |
548 | spec.currentBelt.dummy = nil |
549 | end |
550 | spec.currentBelt = currentBelt |
551 | |
552 | if spec.currentBelt ~= nil and spec.currentBelt.mesh == nil then |
553 | local objects, _ = self:getObjectToMount(spec.currentBelt) |
554 | self:createTensionBelt(spec.currentBelt, true, objects) |
555 | end |
556 | end |
557 | g_currentMission.activatableObjectsSystem:addActivatable(spec.activatable) |
558 | else |
559 | if wasInRange then |
560 | g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable) |
561 | if spec.currentBelt ~= nil and spec.currentBelt.dummy ~= nil then |
562 | delete(spec.currentBelt.dummy) |
563 | spec.currentBelt.dummy = nil |
564 | spec.currentBelt = nil |
565 | end |
566 | end |
567 | end |
568 | 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 |
575 | function TensionBelts:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
576 | local spec = self.spec_tensionBelts |
577 | |
578 | if not spec.hasTensionBelts then |
579 | return |
580 | end |
581 | |
582 | if self.isServer and spec.tensionBelts ~= nil then |
583 | spec.checkTimer = spec.checkTimer - dt |
584 | if spec.checkTimer < 0 then |
585 | -- check if entities have been deleted |
586 | local needUpdate = false |
587 | for phyiscObject, _ in pairs(spec.objectsToJoint) do |
588 | if not entityExists(phyiscObject) then |
589 | spec.objectsToJoint[phyiscObject] = nil |
590 | needUpdate = true |
591 | break |
592 | end |
593 | end |
594 | if needUpdate then |
595 | self:refreshTensionBelts() |
596 | end |
597 | |
598 | spec.checkTimer = spec.checkTimerDuration |
599 | end |
600 | end |
601 | end |
onWriteStream
DescriptionCalled on server side on joinDefinition
onWriteStream(integer streamId, integer connection)Arguments
integer | streamId | streamId |
integer | connection | connection |
421 | function TensionBelts:onWriteStream(streamId, connection) |
422 | local spec = self.spec_tensionBelts |
423 | |
424 | if spec.tensionBelts ~= nil then |
425 | for _, belt in ipairs(spec.sortedBelts) do |
426 | streamWriteBool(streamId, belt.mesh ~= nil) |
427 | end |
428 | end |
429 | end |
prerequisitesPresent
DescriptionDefinitionprerequisitesPresent()Code
21 | function TensionBelts.prerequisitesPresent(specializations) |
22 | return true |
23 | end |
refreshTensionBelts
DescriptionDefinitionrefreshTensionBelts()Code
630 | function TensionBelts:refreshTensionBelts() |
631 | if self.isServer then |
632 | if g_server ~= nil then |
633 | g_server:broadcastEvent(TensionBeltsRefreshEvent.new(self), nil, nil, self) |
634 | end |
635 | end |
636 | for _, belt in pairs(self.spec_tensionBelts.sortedBelts) do |
637 | if belt.mesh ~= nil then |
638 | self:removeTensionBelt(belt) |
639 | local objects, _ = self:getObjectToMount(belt) |
640 | self:createTensionBelt(belt, false, objects) |
641 | end |
642 | end |
643 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
107 | function TensionBelts.registerEventListeners(vehicleType) |
108 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", TensionBelts) |
109 | SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", TensionBelts) |
110 | SpecializationUtil.registerEventListener(vehicleType, "onDelete", TensionBelts) |
111 | SpecializationUtil.registerEventListener(vehicleType, "onPreDelete", TensionBelts) |
112 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", TensionBelts) |
113 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", TensionBelts) |
114 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", TensionBelts) |
115 | SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", TensionBelts) |
116 | SpecializationUtil.registerEventListener(vehicleType, "onDraw", TensionBelts) |
117 | SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", TensionBelts) |
118 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
77 | function TensionBelts.registerFunctions(vehicleType) |
78 | SpecializationUtil.registerFunction(vehicleType, "createTensionBelt", TensionBelts.createTensionBelt) |
79 | SpecializationUtil.registerFunction(vehicleType, "removeTensionBelt", TensionBelts.removeTensionBelt) |
80 | SpecializationUtil.registerFunction(vehicleType, "setTensionBeltsActive", TensionBelts.setTensionBeltsActive) |
81 | SpecializationUtil.registerFunction(vehicleType, "setAllTensionBeltsActive", TensionBelts.setAllTensionBeltsActive) |
82 | SpecializationUtil.registerFunction(vehicleType, "objectOverlapCallback", TensionBelts.objectOverlapCallback) |
83 | SpecializationUtil.registerFunction(vehicleType, "getObjectToMount", TensionBelts.getObjectToMount) |
84 | SpecializationUtil.registerFunction(vehicleType, "getObjectsToUnmount", TensionBelts.getObjectsToUnmount) |
85 | SpecializationUtil.registerFunction(vehicleType, "updateFastenState", TensionBelts.updateFastenState) |
86 | SpecializationUtil.registerFunction(vehicleType, "refreshTensionBelts", TensionBelts.refreshTensionBelts) |
87 | SpecializationUtil.registerFunction(vehicleType, "freeTensionBeltObject", TensionBelts.freeTensionBeltObject) |
88 | SpecializationUtil.registerFunction(vehicleType, "lockTensionBeltObject", TensionBelts.lockTensionBeltObject) |
89 | SpecializationUtil.registerFunction(vehicleType, "getIsPlayerInTensionBeltsRange", TensionBelts.getIsPlayerInTensionBeltsRange) |
90 | SpecializationUtil.registerFunction(vehicleType, "getIsDynamicallyMountedNode", TensionBelts.getIsDynamicallyMountedNode) |
91 | SpecializationUtil.registerFunction(vehicleType, "tensionBeltActivationTriggerCallback", TensionBelts.tensionBeltActivationTriggerCallback) |
92 | SpecializationUtil.registerFunction(vehicleType, "onTensionBeltTreeShapeCut", TensionBelts.onTensionBeltTreeShapeCut) |
93 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
97 | function TensionBelts.registerOverwrittenFunctions(vehicleType) |
98 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsReadyForAutomatedTrainTravel", TensionBelts.getIsReadyForAutomatedTrainTravel) |
99 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeSelected", TensionBelts.getCanBeSelected) |
100 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsFoldAllowed", TensionBelts.getIsFoldAllowed) |
101 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getFillLevelInformation", TensionBelts.getFillLevelInformation) |
102 | SpecializationUtil.registerOverwrittenFunction(vehicleType, "getAdditionalComponentMass", TensionBelts.getAdditionalComponentMass) |
103 | end |
removeTensionBelt
DescriptionRemove tension beltDefinition
removeTensionBelt(table belt, boolean playSound)Arguments
table | belt | belt to remove |
boolean | playSound | play sound (nil = true) |
995 | function TensionBelts:removeTensionBelt(belt, playSound) |
996 | if belt.mesh ~= nil then |
997 | local spec = self.spec_tensionBelts |
998 | |
999 | spec.belts[belt.mesh] = nil |
1000 | delete(belt.mesh) |
1001 | belt.mesh = nil |
1002 | if spec.currentBelt == belt then |
1003 | spec.currentBelt = nil |
1004 | end |
1005 | |
1006 | if belt.dummy == nil and playSound ~= false then |
1007 | if self.isClient then |
1008 | g_soundManager:playSample(spec.samples.toggleBelt) |
1009 | g_soundManager:playSample(spec.samples.removeBelt) |
1010 | end |
1011 | end |
1012 | end |
1013 | end |
saveToXMLFile
DescriptionDefinitionsaveToXMLFile()Code
358 | function TensionBelts:saveToXMLFile(xmlFile, key, usedModNames) |
359 | local spec = self.spec_tensionBelts |
360 | |
361 | if spec.hasTensionBelts then |
362 | for i, belt in ipairs(spec.sortedBelts) do |
363 | local beltKey = string.format("%s.belt(%d)", key, i-1) |
364 | xmlFile:setValue(beltKey.."#isActive", belt.mesh ~= nil) |
365 | end |
366 | end |
367 | end |
setAllTensionBeltsActive
DescriptionSet tensionbelts active stateDefinition
setAllTensionBeltsActive()Code
858 | function TensionBelts:setAllTensionBeltsActive(isActive, noEventSend) |
859 | local spec = self.spec_tensionBelts |
860 | |
861 | if spec.hasTensionBelts then |
862 | isActive = Utils.getNoNil(isActive, not spec.areBeltsFasten) |
863 | for _, belt in pairs(spec.sortedBelts) do |
864 | self:setTensionBeltsActive(isActive, belt.id, noEventSend) |
865 | end |
866 | end |
867 | end |
setTensionBeltsActive
DescriptionSet tensionbelts active stateDefinition
setTensionBeltsActive(boolean isActive, integer beltId, boolean playSound)Arguments
boolean | isActive | new active state |
integer | beltId | id of belt to set state (if id is nil it uses every belt) |
boolean | playSound | play sound (nil = true) |
801 | function TensionBelts:setTensionBeltsActive(isActive, beltId, noEventSend, playSound) |
802 | local spec = self.spec_tensionBelts |
803 | |
804 | if spec.tensionBelts ~= nil then |
805 | TensionBeltsEvent.sendEvent(self, isActive, beltId, noEventSend) |
806 | |
807 | local belt = nil |
808 | if beltId ~= nil then |
809 | belt = spec.sortedBelts[beltId] |
810 | end |
811 | |
812 | if isActive then |
813 | local objects, _ = self:getObjectToMount(belt) |
814 | if belt == nil then |
815 | for _, singleBelt in pairs(spec.singleBelts) do |
816 | if singleBelt.mesh == nil then |
817 | self:createTensionBelt(singleBelt, false, objects, playSound) |
818 | end |
819 | end |
820 | else |
821 | if belt.mesh == nil then |
822 | self:createTensionBelt(belt, false, objects, playSound) |
823 | end |
824 | end |
825 | |
826 | for _, data in pairs(objects) do |
827 | self:lockTensionBeltObject(data.physics, spec.objectsToJoint, spec.isDynamic, spec.jointNode, data.object) |
828 | if data.object ~= nil then |
829 | data.object.tensionMountObject = self |
830 | end |
831 | end |
832 | else |
833 | if belt == nil then |
834 | for _, singleBelt in pairs(spec.singleBelts) do |
835 | self:removeTensionBelt(singleBelt, playSound) |
836 | end |
837 | else |
838 | self:removeTensionBelt(belt, playSound) |
839 | end |
840 | |
841 | -- remove joints |
842 | local objectIds, _ = self:getObjectsToUnmount(belt) |
843 | for objectId, objectData in pairs(objectIds) do |
844 | self:freeTensionBeltObject(objectId, spec.objectsToJoint, spec.isDynamic, objectData.object) |
845 | |
846 | if objectData.object ~= nil then |
847 | objectData.object.tensionMountObject = nil |
848 | end |
849 | end |
850 | end |
851 | |
852 | self:updateFastenState() |
853 | end |
854 | end |
tensionBeltActivationTriggerCallback
DescriptionDefinitiontensionBeltActivationTriggerCallback()Code
1341 | function TensionBelts:tensionBeltActivationTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId) |
1342 | local spec = self.spec_tensionBelts |
1343 | if self.isClient and spec.hasTensionBelts then |
1344 | if onEnter or onLeave then |
1345 | if g_currentMission.player ~= nil and otherActorId == g_currentMission.player.rootNode then |
1346 | if onEnter then |
1347 | self:raiseActive() |
1348 | spec.isPlayerInTrigger = true |
1349 | else |
1350 | spec.isPlayerInTrigger = false |
1351 | end |
1352 | end |
1353 | end |
1354 | end |
1355 | end |
updateFastenState
DescriptionUpdate 'self.areBeltsFasten'Definition
updateFastenState()Code
871 | function TensionBelts:updateFastenState() |
872 | local spec = self.spec_tensionBelts |
873 | |
874 | local unfastenBelts = false |
875 | for _, belt in pairs(spec.singleBelts) do |
876 | if belt.mesh == nil then |
877 | unfastenBelts = true |
878 | break |
879 | end |
880 | end |
881 | |
882 | spec.areBeltsFasten = not unfastenBelts |
883 | end |