LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Attachable

Description
Specialization for vehicles that may be attached to another vehicle
Functions

actionControllerLowerImplementEvent

Description
Definition
actionControllerLowerImplementEvent()
Code
2154function Attachable:actionControllerLowerImplementEvent(direction)
2155 local spec = self.spec_attachable
2156
2157 if self:getAllowsLowering() then
2158 local moveDown = true
2159 if direction < 0 then
2160 moveDown = false
2161 end
2162
2163 local jointDescIndex = spec.attacherVehicle:getAttacherJointIndexFromObject(self)
2164 if spec.attacherVehicle:getJointMoveDown(jointDescIndex) ~= moveDown then
2165 spec.attacherVehicle:setJointMoveDown(jointDescIndex, moveDown, false)
2166 end
2167
2168 return true
2169 end
2170
2171 return false
2172end

attachableAddToolCameras

Description
Add tool cameras to root attacher vehicle
Definition
attachableAddToolCameras()
Code
1374function Attachable:attachableAddToolCameras()
1375 local spec = self.spec_attachable
1376
1377 if #spec.toolCameras > 0 then
1378 local rootAttacherVehicle = self.rootVehicle
1379 if rootAttacherVehicle ~= nil then
1380 if rootAttacherVehicle.addToolCameras ~= nil then
1381 rootAttacherVehicle:addToolCameras(spec.toolCameras)
1382 end
1383 end
1384 end
1385end

attachableRemoveToolCameras

Description
Remove tool cameras from root attacher vehicle
Definition
attachableRemoveToolCameras()
Code
1389function Attachable:attachableRemoveToolCameras()
1390 local spec = self.spec_attachable
1391
1392 if #spec.toolCameras > 0 then
1393 local rootAttacherVehicle = self.rootVehicle
1394 if rootAttacherVehicle ~= nil then
1395 if rootAttacherVehicle.removeToolCameras ~= nil then
1396 rootAttacherVehicle:removeToolCameras(spec.toolCameras)
1397 end
1398 end
1399 end
1400end

findRootVehicle

Description
Definition
findRootVehicle()
Code
1752function Attachable:findRootVehicle(superFunc)
1753 local spec = self.spec_attachable
1754 if spec.attacherVehicle ~= nil then
1755 return spec.attacherVehicle:findRootVehicle()
1756 end
1757
1758 return superFunc(self)
1759end

getActiveFarm

Description
Definition
getActiveFarm()
Code
1913function Attachable:getActiveFarm(superFunc)
1914 local spec = self.spec_attachable
1915
1916 -- Some vehicles can both be attached and entered. Entering takes precedence.
1917 if self.spec_enterable ~= nil and self.spec_enterable.controllerFarmId ~= 0 then
1918 return superFunc(self)
1919 end
1920
1921 if spec.attacherVehicle ~= nil then
1922 return spec.attacherVehicle:getActiveFarm()
1923 else
1924 return superFunc(self)
1925 end
1926end

getActiveInputAttacherJoint

Description
Definition
getActiveInputAttacherJoint()
Code
1116function Attachable:getActiveInputAttacherJoint()
1117 return self.spec_attachable.attacherJoint
1118end

getActiveInputAttacherJointDescIndex

Description
Definition
getActiveInputAttacherJointDescIndex()
Code
1110function Attachable:getActiveInputAttacherJointDescIndex()
1111 return self.spec_attachable.inputAttacherJointDescIndex
1112end

getAllowMultipleAttachments

Description
Function to allow showing the attachment dialog even if the attachable is already attached
Definition
getAllowMultipleAttachments()
Code
1705function Attachable:getAllowMultipleAttachments()
1706 return false
1707end

getAllowsLowering

Description
Returns true if tool can be lowered
Definition
getAllowsLowering()
Return Values
booleandetachAlloweddetach is allowed
stringwarning[optional] warning text to display
Code
1124function Attachable:getAllowsLowering()
1125 local spec = self.spec_attachable
1126 if spec.isAdditionalAttachment then
1127 if not spec.additionalAttachmentNeedsLowering then
1128 return false, nil
1129 end
1130 end
1131
1132 local inputAttacherJoint = self:getActiveInputAttacherJoint()
1133 if inputAttacherJoint ~= nil then
1134 if not inputAttacherJoint.allowsLowering then
1135 return false, nil
1136 end
1137 end
1138
1139 return true, nil
1140end

getAttachbleAirConsumerUsage

Description
Returns air consumer usage
Definition
getAttachbleAirConsumerUsage()
Return Values
floatusageusage
Code
1222function Attachable:getAttachbleAirConsumerUsage()
1223 return self.spec_attachable.airConsumerUsage
1224end

getAttacherVehicle

Description
Definition
getAttacherVehicle()
Code
1079function Attachable:getAttacherVehicle()
1080 return self.spec_attachable.attacherVehicle
1081end

getBlockFoliageDestruction

Description
Returns if attachment blocks all foliage destructions of vehicle chain
Definition
getBlockFoliageDestruction()
Code
1716function Attachable:getBlockFoliageDestruction()
1717 return self.spec_attachable.blockFoliageDestruction
1718end

getBrakeForce

Description
Definition
getBrakeForce()
Code
1791function Attachable:getBrakeForce(superFunc)
1792 local superBrakeForce = superFunc(self)
1793
1794 local spec = self.spec_attachable
1795 local brakeForce = spec.brakeForce
1796 if spec.maxBrakeForceMass > 0 then
1797 local mass = self:getTotalMass(true)
1798 local percentage = math.min(math.max((mass - self.defaultMass) / (spec.maxBrakeForceMass - self.defaultMass), 0), 1)
1799 brakeForce = MathUtil.lerp(spec.brakeForce, spec.maxBrakeForce, percentage)
1800 end
1801
1802 if spec.loweredBrakeForce >= 0 then
1803 if self:getIsLowered(false) then
1804 brakeForce = spec.loweredBrakeForce
1805 end
1806 end
1807
1808 return math.max(superBrakeForce, brakeForce)
1809end

getCanAIImplementContinueWork

Description
Returns true if vehicle is ready for ai work
Definition
getCanAIImplementContinueWork()
Return Values
booleanisReadyis ready for ai work
Code
1887function Attachable:getCanAIImplementContinueWork(superFunc)
1888 local canContinue, stopAI, stopReason = superFunc(self)
1889 if not canContinue then
1890 return false, stopAI, stopReason
1891 end
1892
1893 local spec = self.spec_attachable
1894
1895 local isReady = true
1896 if spec.lowerAnimation ~= nil then
1897 local time = self:getAnimationTime(spec.lowerAnimation)
1898 isReady = time == 1 or time == 0
1899 end
1900
1901 local jointDesc = spec.attacherVehicle:getAttacherJointDescFromObject(self)
1902 if jointDesc.allowsLowering and self:getAINeedsLowering() then
1903 if jointDesc.moveDown then
1904 isReady = (jointDesc.moveAlpha == jointDesc.lowerAlpha or jointDesc.moveAlpha == jointDesc.upperAlpha) and isReady
1905 end
1906 end
1907
1908 return isReady
1909end

getCanBeReset

Description
Definition
getCanBeReset()
Code
2000function Attachable:getCanBeReset(superFunc)
2001 if self:getIsAdditionalAttachment() then
2002 return false
2003 end
2004
2005 if self:getIsSupportVehicle() then
2006 return false
2007 end
2008
2009 return superFunc(self)
2010end

getCanBeSelected

Description
Definition
getCanBeSelected()
Code
1930function Attachable:getCanBeSelected(superFunc)
1931 return true
1932end

getCanToggleTurnedOn

Description
Definition
getCanToggleTurnedOn()
Code
1837function Attachable:getCanToggleTurnedOn(superFunc)
1838 local attacherVehicle = self:getAttacherVehicle()
1839 if attacherVehicle ~= nil then
1840 local jointDesc = attacherVehicle:getAttacherJointDescFromObject(self)
1841 if jointDesc ~= nil then
1842 if not jointDesc.canTurnOnImplement then
1843 return false
1844 end
1845 end
1846 end
1847
1848 local spec = self.spec_attachable
1849 if spec.attacherJoint ~= nil and not spec.attacherJoint.allowTurnOn then
1850 return false
1851 end
1852
1853 return superFunc(self)
1854end

getConnectionHoseConfigIndex

Description
Definition
getConnectionHoseConfigIndex()
Code
2059function Attachable:getConnectionHoseConfigIndex(superFunc)
2060 local index = superFunc(self)
2061 index = self.xmlFile:getValue("vehicle.attachable#connectionHoseConfigId", index)
2062
2063 if self.configurations["inputAttacherJoint"] ~= nil then
2064 local configKey = string.format("vehicle.attachable.inputAttacherJointConfigurations.inputAttacherJointConfiguration(%d)", self.configurations["inputAttacherJoint"] - 1)
2065 index = self.xmlFile:getValue(configKey .. "#connectionHoseConfigId", index)
2066 end
2067
2068 return index
2069end

getDeactivateOnLeave

Description
Definition
getDeactivateOnLeave()
Code
1873function Attachable:getDeactivateOnLeave(superFunc)
1874 local attacherVehicle = self:getAttacherVehicle()
1875 if attacherVehicle ~= nil then
1876 if not attacherVehicle:getDeactivateOnLeave() then
1877 return false
1878 end
1879 end
1880
1881 return superFunc(self)
1882end

getInputAttacherJointByJointDescIndex

Description
Definition
getInputAttacherJointByJointDescIndex()
Code
1058function Attachable:getInputAttacherJointByJointDescIndex(index)
1059 return self.spec_attachable.inputAttacherJoints[index]
1060end

getInputAttacherJointIndexByNode

Description
Definition
getInputAttacherJointIndexByNode()
Code
1064function Attachable:getInputAttacherJointIndexByNode(node)
1065 local spec = self.spec_attachable
1066
1067 for i=1, #spec.inputAttacherJoints do
1068 local inputAttacherJoint = spec.inputAttacherJoints[i]
1069 if inputAttacherJoint.node == node then
1070 return i
1071 end
1072 end
1073
1074 return nil
1075end

getInputAttacherJoints

Description
Definition
getInputAttacherJoints()
Code
1085function Attachable:getInputAttacherJoints()
1086 return self.spec_attachable.inputAttacherJoints
1087end

getIsActive

Description
Definition
getIsActive()
Code
1763function Attachable:getIsActive(superFunc)
1764 if superFunc(self) then
1765 return true
1766 end
1767 local spec = self.spec_attachable
1768 if spec.attacherVehicle ~= nil then
1769 return spec.attacherVehicle:getIsActive()
1770 end
1771 return false
1772end

getIsAdditionalAttachment

Description
get is additional attachment
Definition
getIsAdditionalAttachment()
Code
1652function Attachable:getIsAdditionalAttachment()
1653 return self.spec_attachable.isAdditionalAttachment
1654end

getIsAttachedTo

Description
Definition
getIsAttachedTo()
Code
1091function Attachable:getIsAttachedTo(vehicle)
1092 if vehicle == self then
1093 return true
1094 end
1095
1096 local spec = self.spec_attachable
1097 if spec.attacherVehicle ~= nil then
1098 if spec.attacherVehicle == vehicle then
1099 return true
1100 end
1101 if spec.attacherVehicle.getIsAttachedTo ~= nil then
1102 return spec.attacherVehicle:getIsAttachedTo(vehicle)
1103 end
1104 end
1105 return false
1106end

getIsAttacherJointHeightNodeActive

Description
Returns if height node is active
Definition
getIsAttacherJointHeightNodeActive(table heightNode)
Arguments
tableheightNodeheight node target table
Return Values
booleanisActiveheight node is active
Code
1052function Attachable:getIsAttacherJointHeightNodeActive(heightNode)
1053 return true
1054end

getIsDashboardGroupActive

Description
Definition
getIsDashboardGroupActive()
Code
2117function Attachable:getIsDashboardGroupActive(superFunc, group)
2118 if group.isAttached ~= nil then
2119 if group.isAttached ~= (self:getAttacherVehicle() ~= nil) then
2120 return false
2121 end
2122 end
2123
2124 return superFunc(self, group)
2125end

getIsFoldAllowed

Description
Definition
getIsFoldAllowed()
Code
1813function Attachable:getIsFoldAllowed(superFunc, direction, onAiTurnOn)
1814 local spec = self.spec_attachable
1815
1816 if not spec.allowFoldingWhileAttached then
1817 if self:getAttacherVehicle() ~= nil then
1818 return false, spec.texts.warningFoldingAttached
1819 end
1820 end
1821
1822 if not spec.allowFoldingWhileLowered then
1823 if self:getIsLowered() then
1824 return false, spec.texts.warningFoldingLowered
1825 end
1826 end
1827
1828 if spec.attacherJoint ~= nil and not spec.attacherJoint.allowFolding then
1829 return false, spec.texts.warningFoldingAttacherJoint
1830 end
1831
1832 return superFunc(self)
1833end

getIsImplementChainLowered

Description
Returns true if vehicle itself is lowered and all parent vehicles are lowered until the first vehicle is not attachable (e.g. all implements until a tractor is in the chain)
Definition
getIsImplementChainLowered(boolean defaultIsLowered)
Arguments
booleandefaultIsLowereddefault value if lowering is not allowed
Return Values
booleanisLoweredimplement chain is lowered
Code
1193function Attachable:getIsImplementChainLowered(defaultIsLowered)
1194 if not self:getIsLowered(defaultIsLowered) then
1195 return false
1196 end
1197
1198 local attacherVehicle = self:getAttacherVehicle()
1199 if attacherVehicle ~= nil then
1200 if attacherVehicle.getAllowsLowering ~= nil then
1201 if attacherVehicle:getAllowsLowering() then
1202 if not attacherVehicle:getIsImplementChainLowered(defaultIsLowered) then
1203 return false
1204 end
1205 end
1206 end
1207 end
1208
1209 return true
1210end

getIsInputAttacherActive

Description
Returns true if input attacher is active and can be used to attach
Definition
getIsInputAttacherActive(table inputAttacherJoint)
Arguments
tableinputAttacherJointinput attacher joint
Return Values
booleanisActiveinput attacher is active
Code
1281function Attachable:getIsInputAttacherActive(inputAttacherJoint)
1282 return true
1283end

getIsInUse

Description
Definition
getIsInUse()
Code
1978function Attachable:getIsInUse(superFunc, connection)
1979 local attacherVehicle = self:getAttacherVehicle()
1980 if attacherVehicle ~= nil then
1981 return attacherVehicle:getIsInUse(connection)
1982 end
1983
1984 return superFunc(self, connection)
1985end

getIsInWorkPosition

Description
Returns true if it is in work position
Definition
getIsInWorkPosition()
Return Values
booleaninWorkPositionis in work position
Code
1215function Attachable:getIsInWorkPosition()
1216 return true
1217end

getIsLightActive

Description
Definition
getIsLightActive()
Code
2026function Attachable:getIsLightActive(superFunc, light)
2027 if light.inputAttacherJointIndex ~= nil then
2028 if light.inputAttacherJointIndex ~= self:getActiveInputAttacherJointDescIndex() then
2029 return false
2030 end
2031 end
2032
2033 return superFunc(self, light)
2034end

getIsLowered

Description
Definition
getIsLowered()
Code
1936function Attachable:getIsLowered(superFunc, defaultIsLowered)
1937 local attacherVehicle = self:getAttacherVehicle()
1938 if attacherVehicle ~= nil then
1939 local jointDesc = attacherVehicle:getAttacherJointDescFromObject(self)
1940 if jointDesc ~= nil then
1941 if jointDesc.allowsLowering or jointDesc.isDefaultLowered then
1942 return jointDesc.moveDown
1943 else
1944 return defaultIsLowered
1945 end
1946 end
1947 end
1948
1949 return superFunc(self, defaultIsLowered)
1950end

getIsMapHotspotVisible

Description
Definition
getIsMapHotspotVisible()
Code
2073function Attachable:getIsMapHotspotVisible(superFunc)
2074 if not superFunc(self) then
2075 return false
2076 end
2077
2078 if self:getIsAdditionalAttachment() then
2079 return false
2080 end
2081
2082 if self:getIsSupportVehicle() then
2083 return false
2084 end
2085
2086 return self:getAttacherVehicle() == nil
2087end

getIsOperating

Description
Returns if vehicle is operating
Definition
getIsOperating()
Return Values
booleanisOperatingis operating
Code
1777function Attachable:getIsOperating(superFunc)
1778 local spec = self.spec_attachable
1779
1780 local isOperating = superFunc(self)
1781
1782 if not isOperating and spec.attacherVehicle ~= nil then
1783 isOperating = spec.attacherVehicle:getIsOperating()
1784 end
1785
1786 return isOperating
1787end

getIsPowered

Description
Definition
getIsPowered()
Code
2038function Attachable:getIsPowered(superFunc)
2039 local attacherVehicle = self:getAttacherVehicle()
2040 if attacherVehicle ~= nil then
2041 local isPowered, warning = attacherVehicle:getIsPowered()
2042 if not isPowered then
2043 return isPowered, warning
2044 end
2045 else
2046 local spec = self.spec_attachable
2047 if spec.requiresExternalPower then
2048 if not SpecializationUtil.hasSpecialization(Motorized, self.specializations) then
2049 return false, spec.attachToPowerWarning
2050 end
2051 end
2052 end
2053
2054 return superFunc(self)
2055end

getIsSteeringAxleAllowed

Description
Returns if steering axle is allowed to adjust
Definition
getIsSteeringAxleAllowed()
Code
1335function Attachable:getIsSteeringAxleAllowed()
1336 return true
1337end

getIsSupportAnimationAllowed

Description
Returns if support animation is allowed to play
Definition
getIsSupportAnimationAllowed()
Code
1159function Attachable:getIsSupportAnimationAllowed(supportAnimation)
1160 return self.playAnimation ~= nil
1161end

getIsSupportVehicle

Description
get is additional attachment
Definition
getIsSupportVehicle()
Code
1669function Attachable:getIsSupportVehicle()
1670 return self.spec_attachable.isSupportVehicle
1671end

getLoweringActionEventState

Description
Definition
getLoweringActionEventState()
Code
1682function Attachable:getLoweringActionEventState()
1683 local showLower = false
1684
1685 local attacherVehicle = self:getAttacherVehicle()
1686 if attacherVehicle ~= nil then
1687 local jointDesc = attacherVehicle:getAttacherJointDescFromObject(self)
1688 local inputJointDesc = self:getActiveInputAttacherJoint()
1689 showLower = jointDesc.allowsLowering and inputJointDesc.allowsLowering
1690 end
1691
1692 local spec = self.spec_attachable
1693 local text
1694 if self:getIsLowered() then
1695 text = string.format(spec.texts.liftObject, self.typeDesc)
1696 else
1697 text = string.format(spec.texts.lowerObject, self.typeDesc)
1698 end
1699
1700 return showLower, text
1701end

getOwner

Description
Definition
getOwner()
Code
1966function Attachable:getOwner(superFunc)
1967 local spec = self.spec_attachable
1968
1969 if spec.attacherVehicle ~= nil then
1970 return spec.attacherVehicle:getOwner()
1971 end
1972
1973 return superFunc(self)
1974end

getPowerTakeOffConfigIndex

Description
Definition
getPowerTakeOffConfigIndex()
Code
2091function Attachable:getPowerTakeOffConfigIndex(superFunc)
2092 local index = superFunc(self)
2093 index = self.xmlFile:getValue("vehicle.attachable#powerTakeOffConfigId", index)
2094
2095 if self.configurations["inputAttacherJoint"] ~= nil then
2096 local configKey = string.format("vehicle.attachable.inputAttacherJointConfigurations.inputAttacherJointConfiguration(%d)", self.configurations["inputAttacherJoint"] - 1)
2097 index = self.xmlFile:getValue(configKey .. "#powerTakeOffConfigId", index)
2098 end
2099
2100 return index
2101end

getSteeringAxleBaseVehicle

Description
Returns vehicle used to calculate steering axle
Definition
getSteeringAxleBaseVehicle()
Code
1287function Attachable:getSteeringAxleBaseVehicle()
1288 local spec = self.spec_attachable
1289
1290 if spec.steeringAxleUseSuperAttachable then
1291 if spec.attacherVehicle ~= nil then
1292 if spec.attacherVehicle.getAttacherVehicle ~= nil then
1293 return spec.attacherVehicle:getAttacherVehicle()
1294 end
1295 end
1296 end
1297
1298 if spec.attacherVehicle ~= nil then
1299 if spec.steeringAxleForceUsage or spec.attacherVehicle:getCanSteerAttachable(self) then
1300 return spec.attacherVehicle
1301 end
1302 end
1303
1304 return nil
1305end

getUpdatePriority

Description
Definition
getUpdatePriority()
Code
1989function Attachable:getUpdatePriority(superFunc, skipCount, x, y, z, coeff, connection, isGuiVisible)
1990 local attacherVehicle = self:getAttacherVehicle()
1991 if attacherVehicle ~= nil then
1992 return attacherVehicle:getUpdatePriority(skipCount, x, y, z, coeff, connection, isGuiVisible)
1993 end
1994
1995 return superFunc(self, skipCount, x, y, z, coeff, connection)
1996end

initSpecialization

Description
Definition
initSpecialization()
Code
140function Attachable.initSpecialization()
141 g_configurationManager:addConfigurationType("inputAttacherJoint", g_i18n:getText("configuration_inputAttacherJoint"), "attachable", nil, nil, nil, ConfigurationUtil.SELECTOR_MULTIOPTION)
142
143 local schema = Vehicle.xmlSchema
144 schema:setXMLSpecializationType("Attachable")
145
146 Attachable.registerInputAttacherJointXMLPaths(schema, Attachable.INPUT_ATTACHERJOINT_XML_KEY)
147 Attachable.registerInputAttacherJointXMLPaths(schema, Attachable.INPUT_ATTACHERJOINT_CONFIG_XML_KEY)
148
149 ObjectChangeUtil.registerObjectChangeXMLPaths(schema, "vehicle.attachable.inputAttacherJointConfigurations.inputAttacherJointConfiguration(?)")
150 ObjectChangeUtil.registerObjectChangeXMLPaths(schema, Attachable.INPUT_ATTACHERJOINT_XML_KEY)
151 ObjectChangeUtil.registerObjectChangeXMLPaths(schema, Attachable.INPUT_ATTACHERJOINT_CONFIG_XML_KEY)
152
153 schema:register(XMLValueType.INT, "vehicle.attachable#connectionHoseConfigId", "Connection hose configuration index to use")
154 schema:register(XMLValueType.INT, "vehicle.attachable#powerTakeOffConfigId", "Power take off configuration index to use")
155 schema:register(XMLValueType.INT, "vehicle.attachable.inputAttacherJointConfigurations.inputAttacherJointConfiguration(?)#connectionHoseConfigId", "Connection hose configuration index to use")
156 schema:register(XMLValueType.INT, "vehicle.attachable.inputAttacherJointConfigurations.inputAttacherJointConfiguration(?)#powerTakeOffConfigId", "Power take off configuration index to use")
157
158 schema:register(XMLValueType.FLOAT, "vehicle.attachable.brakeForce#force", "Brake force", 0)
159 schema:register(XMLValueType.FLOAT, "vehicle.attachable.brakeForce#maxForce", "Brake force when vehicle reached mass of #maxForceMass", 0)
160 schema:register(XMLValueType.FLOAT, "vehicle.attachable.brakeForce#maxForceMass", "When this mass is reached the vehicle will brake with #maxForce", 0)
161 schema:register(XMLValueType.FLOAT, "vehicle.attachable.brakeForce#loweredForce", "Brake force while the tool is lowered")
162
163 schema:register(XMLValueType.FLOAT, "vehicle.attachable.airConsumer#usage", "Air consumption while fully braking", 0)
164 schema:register(XMLValueType.BOOL, "vehicle.attachable#allowFoldingWhileAttached", "Allow folding while attached", true)
165 schema:register(XMLValueType.BOOL, "vehicle.attachable#allowFoldingWhileLowered", "Allow folding while lowered", true)
166 schema:register(XMLValueType.BOOL, "vehicle.attachable#blockFoliageDestruction", "If active the vehicle will block the complete foliage destruction of the vehicle chain", false)
167
168 schema:register(XMLValueType.BOOL, "vehicle.attachable.power#requiresExternalPower", "Tool requires external power from a vehicle with motor to work", true)
169 schema:register(XMLValueType.L10N_STRING, "vehicle.attachable.power#attachToPowerWarning", "Warning to be displayed if no vehicle with motor is attached", "warning_attachToPower")
170
171 schema:register(XMLValueType.FLOAT, "vehicle.attachable.steeringAxleAngleScale#startSpeed", "Start speed", 10)
172 schema:register(XMLValueType.FLOAT, "vehicle.attachable.steeringAxleAngleScale#endSpeed", "End speed", 30)
173 schema:register(XMLValueType.BOOL, "vehicle.attachable.steeringAxleAngleScale#backwards", "Is active backwards", false)
174 schema:register(XMLValueType.FLOAT, "vehicle.attachable.steeringAxleAngleScale#speed", "Speed", 0.001)
175 schema:register(XMLValueType.BOOL, "vehicle.attachable.steeringAxleAngleScale#useSuperAttachable", "Use super attachable", false)
176 schema:register(XMLValueType.NODE_INDEX, "vehicle.attachable.steeringAxleAngleScale.targetNode#node", "Target node")
177 schema:register(XMLValueType.ANGLE, "vehicle.attachable.steeringAxleAngleScale.targetNode#refAngle", "Reference angle to transfer from angle between vehicles to defined min. and max. rot for target node")
178 schema:register(XMLValueType.ANGLE, "vehicle.attachable.steeringAxleAngleScale#minRot", "Min Rotation", 0)
179 schema:register(XMLValueType.ANGLE, "vehicle.attachable.steeringAxleAngleScale#maxRot", "Max Rotation", 0)
180 schema:register(XMLValueType.FLOAT, "vehicle.attachable.steeringAxleAngleScale#direction", "Direction", 1)
181 schema:register(XMLValueType.BOOL, "vehicle.attachable.steeringAxleAngleScale#forceUsage", "Force usage of steering axle, even if attacher vehicle does not have steering bar nodes", false)
182 schema:register(XMLValueType.BOOL, "vehicle.attachable.steeringAxleAngleScale#speedDependent", "Steering axle angle is scaled based on speed with #startSpeed and #endSpeed", true)
183 schema:register(XMLValueType.FLOAT, "vehicle.attachable.steeringAxleAngleScale#distanceDelay", "The steering angle is updated delayed after vehicle has been moved this distance", 0)
184 schema:register(XMLValueType.INT, "vehicle.attachable.steeringAxleAngleScale#referenceComponentIndex", "If defined the given component is used for steering angle reference. Y between root component and this component will result in steering angle.")
185
186 schema:register(XMLValueType.NODE_INDEX, Attachable.STEERING_ANGLE_NODE_XML_KEY .. "#node", "Steering angle node")
187 schema:register(XMLValueType.ANGLE, Attachable.STEERING_ANGLE_NODE_XML_KEY .. "#speed", "Change speed (degree per second)", 25)
188 schema:register(XMLValueType.FLOAT, Attachable.STEERING_ANGLE_NODE_XML_KEY .. "#scale", "Scale of vehicle to vehicle angle that is applied", 1)
189 schema:register(XMLValueType.ANGLE, Attachable.STEERING_ANGLE_NODE_XML_KEY .. "#offset", "Angle offset", 0)
190 schema:register(XMLValueType.FLOAT, Attachable.STEERING_ANGLE_NODE_XML_KEY .. "#minSpeed", "Min. speed of vehicle to update", 0)
191
192 schema:register(XMLValueType.STRING, "vehicle.attachable.support(?)#animationName", "Animation name")
193 schema:register(XMLValueType.BOOL, "vehicle.attachable.support(?)#delayedOnLoad", "Defines if the animation is played onPostLoad or onLoadFinished -> useful if the animation collides e.g. with the folding animation", false)
194 schema:register(XMLValueType.BOOL, "vehicle.attachable.support(?)#delayedOnAttach", "Defines if the animation is played before or after the attaching process", true)
195 schema:register(XMLValueType.BOOL, "vehicle.attachable.support(?)#detachAfterAnimation", "Defines if the vehicle is detached after the animation has played", true)
196 schema:register(XMLValueType.FLOAT, "vehicle.attachable.support(?)#detachAnimationTime", "Defines when in the support animation the vehicle is detached (detachAfterAnimation needs to be true)", 1)
197
198 schema:register(XMLValueType.STRING, "vehicle.attachable.lowerAnimation#name", "Animation name")
199 schema:register(XMLValueType.FLOAT, "vehicle.attachable.lowerAnimation#speed", "Animation speed", 1)
200 schema:register(XMLValueType.INT, "vehicle.attachable.lowerAnimation#directionOnDetach", "Direction on detach", 0)
201 schema:register(XMLValueType.BOOL, "vehicle.attachable.lowerAnimation#defaultLowered", "Is default lowered", false)
202
203 VehicleCamera.registerCameraXMLPaths(schema, "vehicle.attachable.toolCameras.toolCamera(?)")
204
205 for i=1, #Lights.ADDITIONAL_LIGHT_ATTRIBUTES_KEYS do
206 local key = Lights.ADDITIONAL_LIGHT_ATTRIBUTES_KEYS[i]
207 schema:register(XMLValueType.INT, key .. "#inputAttacherJointIndex", "Index of input attacher joint that needs to be active to activate light")
208 end
209
210 schema:register(XMLValueType.BOOL, Dashboard.GROUP_XML_KEY .. "#isAttached", "Tool is attached")
211
212 schema:addDelayedRegistrationFunc("AnimatedVehicle:part", function(cSchema, cKey)
213 cSchema:register(XMLValueType.INT, cKey .. "#inputAttacherJointIndex", "Input Attacher Joint Index [1..n]")
214
215 cSchema:register(XMLValueType.VECTOR_3, cKey .. "#lowerRotLimitScaleStart", "Lower rotaton limit start")
216 cSchema:register(XMLValueType.VECTOR_3, cKey .. "#lowerRotLimitScaleEnd", "Lower rotaton limit end")
217 cSchema:register(XMLValueType.VECTOR_3, cKey .. "#upperRotLimitScaleStart", "Upper rotaton limit start")
218 cSchema:register(XMLValueType.VECTOR_3, cKey .. "#upperRotLimitScaleEnd", "Upper rotaton limit end")
219
220 cSchema:register(XMLValueType.VECTOR_3, cKey .. "#lowerTransLimitScaleStart", "Lower translation limit start")
221 cSchema:register(XMLValueType.VECTOR_3, cKey .. "#lowerTransLimitScaleEnd", "Lower translation limit end")
222 cSchema:register(XMLValueType.VECTOR_3, cKey .. "#upperTransLimitScaleStart", "Upper translation limit start")
223 cSchema:register(XMLValueType.VECTOR_3, cKey .. "#upperTransLimitScaleEnd", "Upper translation limit end")
224
225 cSchema:register(XMLValueType.ANGLE, cKey .. "#lowerRotationOffsetStart", "Lower rotation offset start")
226 cSchema:register(XMLValueType.ANGLE, cKey .. "#lowerRotationOffsetEnd", "Lower rotation offset end")
227 cSchema:register(XMLValueType.ANGLE, cKey .. "#upperRotationOffsetStart", "Upper rotation offset start")
228 cSchema:register(XMLValueType.ANGLE, cKey .. "#upperRotationOffsetEnd", "Upper rotation offset end")
229
230 cSchema:register(XMLValueType.FLOAT, cKey .. "#lowerDistanceToGroundStart", "Lower distance to ground start")
231 cSchema:register(XMLValueType.FLOAT, cKey .. "#lowerDistanceToGroundEnd", "Lower distance to ground end")
232 cSchema:register(XMLValueType.FLOAT, cKey .. "#upperDistanceToGroundStart", "Upper distance to ground start")
233 cSchema:register(XMLValueType.FLOAT, cKey .. "#upperDistanceToGroundEnd", "Upper distance to ground end")
234 end)
235
236 schema:setXMLSpecializationType()
237
238 local schemaSavegame = Vehicle.xmlSchemaSavegame
239 schemaSavegame:register(XMLValueType.FLOAT, "vehicles.vehicle(?).attachable#lowerAnimTime", "Lower animation time")
240end

isAttachAllowed

Description
Returns true if attaching the vehicle is allowed
Definition
isAttachAllowed(integer farmId, table attacherVehicle)
Arguments
integerfarmIdfarmId of attacher vehicle
tableattacherVehicleattacher vehicle
Return Values
booleandetachAlloweddetach is allowed
stringwarning[optional] warning text to display
Code
1269function Attachable:isAttachAllowed(farmId, attacherVehicle)
1270 if not g_currentMission.accessHandler:canFarmAccess(farmId, self) then
1271 return false, nil
1272 end
1273
1274 return true, nil
1275end

isDetachAllowed

Description
Returns true if detach is allowed
Definition
isDetachAllowed()
Return Values
booleandetachAlloweddetach is allowed
stringwarning[optional] warning text to display
Code
1230function Attachable:isDetachAllowed()
1231 local spec = self.spec_attachable
1232 if spec.attacherJoint ~= nil then
1233 if spec.attacherJoint.allowsDetaching == false then
1234 return false, nil, false
1235 end
1236
1237 if spec.attacherJoint.allowDetachWhileParentLifted == false then
1238 local attacherVehicle = self:getAttacherVehicle()
1239 if attacherVehicle ~= nil then
1240 if attacherVehicle.getIsLowered ~= nil and not attacherVehicle:getIsLowered(true) then
1241 return false, string.format(spec.texts.lowerImplementFirst, attacherVehicle.typeDesc), true
1242 end
1243 end
1244 end
1245 end
1246
1247 if spec.isAdditionalAttachment then
1248 return false
1249 end
1250
1251 -- block detach while the attaching is still in progress
1252 local attacherVehicle = self:getAttacherVehicle()
1253 if attacherVehicle ~= nil then
1254 local implement = attacherVehicle:getImplementByObject(self)
1255 if implement ~= nil and implement.attachingIsInProgress then
1256 return false
1257 end
1258 end
1259
1260 return true, nil
1261end

loadAdditionalLightAttributesFromXML

Description
Definition
loadAdditionalLightAttributesFromXML()
Code
2014function Attachable:loadAdditionalLightAttributesFromXML(superFunc, xmlFile, key, light)
2015 if not superFunc(self, xmlFile, key, light) then
2016 return false
2017 end
2018
2019 light.inputAttacherJointIndex = xmlFile:getValue(key .. "#inputAttacherJointIndex")
2020
2021 return true
2022end

loadAttacherJointHeightNode

Description
Load height node from XML
Definition
loadAttacherJointHeightNode(table xmlFile, string key, table heightNode)
Arguments
tablexmlFilexml file object
stringkeyheight node xml key
tableheightNodeheight node target table
Code
1041function Attachable:loadAttacherJointHeightNode(xmlFile, key, heightNode, attacherJointNode)
1042 heightNode.node = xmlFile:getValue(key .. "#node", nil, self.components, self.i3dMappings)
1043 heightNode.attacherJointNode = attacherJointNode
1044
1045 return true
1046end

loadDashboardGroupFromXML

Description
Definition
loadDashboardGroupFromXML()
Code
2105function Attachable:loadDashboardGroupFromXML(superFunc, xmlFile, key, group)
2106 if not superFunc(self, xmlFile, key, group) then
2107 return false
2108 end
2109
2110 group.isAttached = xmlFile:getValue(key .. "#isAttached")
2111
2112 return true
2113end

loadInputAttacherJoint

Description
Called on loading
Definition
loadInputAttacherJoint(table savegame)
Arguments
tablesavegamesavegame
Code
780function Attachable:loadInputAttacherJoint(xmlFile, key, inputAttacherJoint, index)
781 XMLUtil.checkDeprecatedXMLElements(xmlFile, key .. "#index", key .. "#node") -- FS17 to FS19
782 XMLUtil.checkDeprecatedXMLElements(xmlFile, key .. "#indexVisual", key .. "#nodeVisual") -- FS17 to FS19
783 XMLUtil.checkDeprecatedXMLElements(xmlFile, key .. "#ptoInputNode", "vehicle.powerTakeOffs.input") -- FS17 to FS19
784 XMLUtil.checkDeprecatedXMLElements(xmlFile, key .. "#lowerDistanceToGround", key..".distanceToGround#lower") -- FS17 to FS19
785 XMLUtil.checkDeprecatedXMLElements(xmlFile, key .. "#upperDistanceToGround", key..".distanceToGround#upper") -- FS17 to FS19
786
787 local node = xmlFile:getValue(key .. "#node", nil, self.components, self.i3dMappings)
788 if node ~= nil then
789 inputAttacherJoint.node = node
790
791 inputAttacherJoint.heightNodes = {}
792 xmlFile:iterate(key .. ".heightNode", function(_, heightNodeKey)
793 local heightNode = {}
794 if self:loadAttacherJointHeightNode(xmlFile, heightNodeKey, heightNode, node) then
795 table.insert(inputAttacherJoint.heightNodes, heightNode)
796 end
797 end)
798
799 local jointTypeStr = xmlFile:getValue(key .. "#jointType")
800 local jointType
801 if jointTypeStr ~= nil then
802 jointType = AttacherJoints.jointTypeNameToInt[jointTypeStr]
803 if jointType == nil then
804 Logging.xmlWarning(self.xmlFile, "Invalid jointType '%s' for inputAttacherJoint '%s'!", tostring(jointTypeStr), key)
805 end
806 else
807 Logging.xmlWarning(self.xmlFile, "Missing jointType for inputAttacherJoint '%s'!", key)
808 end
809 if jointType == nil then
810 local needsTrailerJoint = xmlFile:getValue(key .. "#needsTrailerJoint", false)
811 local needsLowTrailerJoint = xmlFile:getValue(key .. "#needsLowJoint", false)
812 if needsTrailerJoint then
813 if needsLowTrailerJoint then
814 jointType = AttacherJoints.JOINTTYPE_TRAILERLOW
815 else
816 jointType = AttacherJoints.JOINTTYPE_TRAILER
817 end
818 else
819 jointType = AttacherJoints.JOINTTYPE_IMPLEMENT
820 end
821 end
822 inputAttacherJoint.jointType = jointType
823
824 local subTypeStr = xmlFile:getValue(key.. ".subType#name")
825 inputAttacherJoint.subTypes = string.split(subTypeStr, " ")
826 if #inputAttacherJoint.subTypes == 0 then
827 inputAttacherJoint.subTypes = nil
828 end
829 inputAttacherJoint.subTypeShowWarning = xmlFile:getValue(key.. ".subType#showWarning", true)
830
831 inputAttacherJoint.jointOrigTrans = { getTranslation(inputAttacherJoint.node) }
832 inputAttacherJoint.jointOrigOffsetComponent = { localToLocal(self:getParentComponent(inputAttacherJoint.node), inputAttacherJoint.node, 0, 0, 0) }
833 inputAttacherJoint.jointOrigDirOffsetComponent = { localDirectionToLocal(self:getParentComponent(inputAttacherJoint.node), inputAttacherJoint.node, 0, 0, 1) }
834 inputAttacherJoint.topReferenceNode = xmlFile:getValue(key .. "#topReferenceNode", nil, self.components, self.i3dMappings)
835 inputAttacherJoint.rootNode = xmlFile:getValue(key .. "#rootNode", self.components[1].node, self.components, self.i3dMappings)
836 inputAttacherJoint.rootNodeBackup = inputAttacherJoint.rootNode
837 inputAttacherJoint.allowsDetaching = xmlFile:getValue(key .. "#allowsDetaching", true)
838 inputAttacherJoint.fixedRotation = xmlFile:getValue(key .. "#fixedRotation", false)
839 inputAttacherJoint.hardAttach = xmlFile:getValue(key .. "#hardAttach", false)
840 if inputAttacherJoint.hardAttach and #self.components > 1 then
841 Logging.xmlWarning(self.xmlFile, "hardAttach only available for single component vehicles! InputAttacherJoint '%s'!", key)
842 inputAttacherJoint.hardAttach = false
843 end
844 inputAttacherJoint.visualNode = xmlFile:getValue(key .. "#nodeVisual", nil, self.components, self.i3dMappings)
845 if inputAttacherJoint.hardAttach and inputAttacherJoint.visualNode ~= nil then
846 inputAttacherJoint.visualNodeData = {
847 parent = getParent(inputAttacherJoint.visualNode),
848 translation = { getTranslation(inputAttacherJoint.visualNode) },
849 rotation = { getRotation(inputAttacherJoint.visualNode) },
850 index = getChildIndex(inputAttacherJoint.visualNode)
851 }
852 end
853
854
855 if jointType == AttacherJoints.JOINTTYPE_IMPLEMENT
856 or jointType == AttacherJoints.JOINTTYPE_CUTTER
857 or jointType == AttacherJoints.JOINTTYPE_CUTTERHARVESTER then
858 if xmlFile:getValue(key .. ".distanceToGround#lower") == nil then
859 Logging.xmlWarning(self.xmlFile, "Missing '.distanceToGround#lower' for inputAttacherJoint '%s'!", key)
860 end
861 if xmlFile:getValue(key .. ".distanceToGround#upper") == nil then
862 Logging.xmlWarning(self.xmlFile, "Missing '.distanceToGround#upper' for inputAttacherJoint '%s'!", key)
863 end
864 end
865
866 inputAttacherJoint.lowerDistanceToGround = xmlFile:getValue(key .. ".distanceToGround#lower", 0.7)
867 inputAttacherJoint.upperDistanceToGround = xmlFile:getValue(key .. ".distanceToGround#upper", 1.0)
868 if inputAttacherJoint.lowerDistanceToGround > inputAttacherJoint.upperDistanceToGround then
869 Logging.xmlWarning(self.xmlFile, "distanceToGround#lower may not be larger than distanceToGround#upper for inputAttacherJoint '%s'. Switching values!", key)
870 local copy = inputAttacherJoint.lowerDistanceToGround
871 inputAttacherJoint.lowerDistanceToGround = inputAttacherJoint.upperDistanceToGround
872 inputAttacherJoint.upperDistanceToGround = copy
873 end
874
875 inputAttacherJoint.distanceToGroundByVehicle = {}
876 xmlFile:iterate(key .. ".distanceToGround.vehicle", function(_, vehicleKey)
877 local entry = {}
878 entry.filename = xmlFile:getValue(vehicleKey .. "#filename")
879 if entry.filename ~= nil then
880 entry.filename = entry.filename:lower()
881 entry.lower = xmlFile:getValue(vehicleKey .. "#lower", inputAttacherJoint.lowerDistanceToGround)
882 entry.upper = xmlFile:getValue(vehicleKey .. "#upper", inputAttacherJoint.upperDistanceToGround)
883
884 table.insert(inputAttacherJoint.distanceToGroundByVehicle, entry)
885 end
886 end)
887
888 inputAttacherJoint.lowerDistanceToGroundOriginal = inputAttacherJoint.lowerDistanceToGround
889 inputAttacherJoint.upperDistanceToGroundOriginal = inputAttacherJoint.upperDistanceToGround
890
891 inputAttacherJoint.lowerRotationOffset = xmlFile:getValue(key .. "#lowerRotationOffset", 0)
892
893 local defaultUpperRotationOffset = 0
894 if jointType == AttacherJoints.JOINTTYPE_IMPLEMENT then
895 defaultUpperRotationOffset = 8
896 end
897
898 inputAttacherJoint.upperRotationOffset = xmlFile:getValue(key .. "#upperRotationOffset", defaultUpperRotationOffset)
899
900 inputAttacherJoint.allowsJointRotLimitMovement = xmlFile:getValue(key .. "#allowsJointRotLimitMovement", true)
901 inputAttacherJoint.allowsJointTransLimitMovement = xmlFile:getValue(key .. "#allowsJointTransLimitMovement", true)
902
903 inputAttacherJoint.needsToolbar = xmlFile:getValue(key .. "#needsToolbar", false)
904 if inputAttacherJoint.needsToolbar and jointType ~= AttacherJoints.JOINTTYPE_IMPLEMENT then
905 Logging.xmlWarning(self.xmlFile, "'needsToolbar' requires jointType 'implement' for inputAttacherJoint '%s'!", key)
906 inputAttacherJoint.needsToolbar = false
907 end
908
909 inputAttacherJoint.steeringBarLeftNode = xmlFile:getValue(key .. "#steeringBarLeftNode", nil, self.components, self.i3dMappings)
910 inputAttacherJoint.steeringBarRightNode = xmlFile:getValue(key .. "#steeringBarRightNode", nil, self.components, self.i3dMappings)
911
912 --load joint limit scales
913 inputAttacherJoint.upperRotLimitScale = xmlFile:getValue( key .. "#upperRotLimitScale", "0 0 0", true)
914 local x, y, z = xmlFile:getValue( key .. "#lowerRotLimitScale")
915 if jointType == AttacherJoints.JOINTTYPE_IMPLEMENT then
916 inputAttacherJoint.lowerRotLimitScale = { Utils.getNoNil(x, 0), Utils.getNoNil(y, 0), Utils.getNoNil(z, 1) }
917 else
918 inputAttacherJoint.lowerRotLimitScale = { Utils.getNoNil(x, 1), Utils.getNoNil(y, 1), Utils.getNoNil(z, 1) }
919 end
920 inputAttacherJoint.rotLimitThreshold = xmlFile:getValue( key .. "#rotLimitThreshold", 0)
921
922 inputAttacherJoint.upperTransLimitScale = xmlFile:getValue( key .. "#upperTransLimitScale", "0 0 0", true)
923 inputAttacherJoint.lowerTransLimitScale = xmlFile:getValue( key .. "#lowerTransLimitScale", "0 1 0", true)
924 inputAttacherJoint.transLimitThreshold = xmlFile:getValue( key .. "#transLimitThreshold", 0)
925
926 inputAttacherJoint.rotLimitSpring = xmlFile:getValue( key.."#rotLimitSpring", "0 0 0", true)
927 inputAttacherJoint.rotLimitDamping = xmlFile:getValue( key.."#rotLimitDamping", "1 1 1", true)
928 inputAttacherJoint.rotLimitForceLimit = xmlFile:getValue( key.."#rotLimitForceLimit", "-1 -1 -1", true)
929
930 inputAttacherJoint.transLimitSpring = xmlFile:getValue( key.."#transLimitSpring", "0 0 0", true)
931 inputAttacherJoint.transLimitDamping = xmlFile:getValue( key.."#transLimitDamping", "1 1 1", true)
932 inputAttacherJoint.transLimitForceLimit = xmlFile:getValue( key.."#transLimitForceLimit", "-1 -1 -1", true)
933
934 inputAttacherJoint.attachAngleLimitAxis = xmlFile:getValue(key .. "#attachAngleLimitAxis", 1)
935
936 inputAttacherJoint.attacherHeight = xmlFile:getValue(key .. "#attacherHeight")
937 if inputAttacherJoint.attacherHeight == nil then
938 if jointType == AttacherJoints.JOINTTYPE_TRAILER then
939 inputAttacherJoint.attacherHeight = 0.9
940 elseif jointType == AttacherJoints.JOINTTYPE_TRAILERLOW then
941 inputAttacherJoint.attacherHeight = 0.55
942 end
943 end
944
945 local defaultNeedsLowering = true
946 local defaultAllowsLowering = false
947 if inputAttacherJoint.jointType == AttacherJoints.JOINTTYPE_TRAILER or inputAttacherJoint.jointType == AttacherJoints.JOINTTYPE_TRAILERLOW then
948 defaultNeedsLowering = false
949 end
950 if inputAttacherJoint.jointType ~= AttacherJoints.JOINTTYPE_TRAILER and inputAttacherJoint.jointType ~= AttacherJoints.JOINTTYPE_TRAILERLOW then
951 defaultAllowsLowering = true
952 end
953 inputAttacherJoint.needsLowering = xmlFile:getValue(key.. "#needsLowering", defaultNeedsLowering)
954 inputAttacherJoint.allowsLowering = xmlFile:getValue(key.. "#allowsLowering", defaultAllowsLowering)
955 inputAttacherJoint.isDefaultLowered = xmlFile:getValue(key.. "#isDefaultLowered", false)
956 inputAttacherJoint.useFoldingLoweredState = xmlFile:getValue(key.. "#useFoldingLoweredState", false)
957 inputAttacherJoint.forceSelection = xmlFile:getValue(key.."#forceSelectionOnAttach", true)
958 inputAttacherJoint.forceAllowDetachWhileLifted = xmlFile:getValue(key.."#forceAllowDetachWhileLifted", false)
959 inputAttacherJoint.forcedAttachingDirection = xmlFile:getValue(key.."#forcedAttachingDirection", 0)
960
961 inputAttacherJoint.allowFolding = xmlFile:getValue(key.."#allowFolding", true)
962 inputAttacherJoint.allowTurnOn = xmlFile:getValue(key.."#allowTurnOn", true)
963 inputAttacherJoint.allowAI = xmlFile:getValue(key.."#allowAI", true)
964 inputAttacherJoint.allowDetachWhileParentLifted = xmlFile:getValue(key.."#allowDetachWhileParentLifted", true)
965
966 inputAttacherJoint.dependentAttacherJoints = {}
967 local k = 0
968 while true do
969 local dependentKey = string.format(key .. ".dependentAttacherJoint(%d)", k)
970 if not xmlFile:hasProperty(dependentKey) then
971 break
972 end
973 local attacherJointIndex = xmlFile:getValue(dependentKey.."#attacherJointIndex")
974 if attacherJointIndex ~= nil then
975 table.insert(inputAttacherJoint.dependentAttacherJoints, attacherJointIndex)
976 end
977 k = k + 1
978 end
979
980 -- reset values if hardAttach is active
981 if inputAttacherJoint.hardAttach then
982 inputAttacherJoint.needsLowering = false
983 inputAttacherJoint.allowsLowering = false
984 inputAttacherJoint.isDefaultLowered = false
985 inputAttacherJoint.upperRotationOffset = 0
986 end
987
988 inputAttacherJoint.changeObjects = {}
989 ObjectChangeUtil.loadObjectChangeFromXML(xmlFile, key, inputAttacherJoint.changeObjects, self.components, self)
990
991 inputAttacherJoint.additionalObjects = {}
992 local i = 0
993 while true do
994 local baseKey = string.format("%s.additionalObjects.additionalObject(%d)", key, i)
995 if not xmlFile:hasProperty(baseKey) then
996 break
997 end
998
999 local entry = {}
1000 entry.node = xmlFile:getValue(baseKey .. "#node", nil, self.components, self.i3dMappings)
1001 entry.attacherVehiclePath = xmlFile:getValue(baseKey.."#attacherVehiclePath")
1002
1003 if entry.node ~= nil and entry.attacherVehiclePath ~= nil then
1004 entry.attacherVehiclePath = NetworkUtil.convertToNetworkFilename(entry.attacherVehiclePath)
1005 table.insert(inputAttacherJoint.additionalObjects, entry)
1006 end
1007
1008 i = i + 1
1009 end
1010
1011 inputAttacherJoint.additionalAttachment = {}
1012 local filename = xmlFile:getValue(key..".additionalAttachment#filename")
1013 if filename ~= nil then
1014 inputAttacherJoint.additionalAttachment.filename = Utils.getFilename(filename, self.customEnvironment)
1015 end
1016 inputAttacherJoint.additionalAttachment.inputAttacherJointIndex = xmlFile:getValue(key..".additionalAttachment#inputAttacherJointIndex", 1)
1017 inputAttacherJoint.additionalAttachment.needsLowering = xmlFile:getValue(key..".additionalAttachment#needsLowering", false)
1018
1019 local additionalJointTypeStr = xmlFile:getValue(key..".additionalAttachment#jointType")
1020 local additionalJointType
1021 if additionalJointTypeStr ~= nil then
1022 additionalJointType = AttacherJoints.jointTypeNameToInt[additionalJointTypeStr]
1023 if additionalJointType == nil then
1024 Logging.xmlWarning(self.xmlFile, "Invalid jointType '%s' for additonal implement '%s'!", tostring(additionalJointTypeStr), inputAttacherJoint.additionalAttachment.filename)
1025 end
1026 end
1027
1028 inputAttacherJoint.additionalAttachment.jointType = additionalJointType or AttacherJoints.JOINTTYPE_IMPLEMENT
1029
1030 return true
1031 end
1032
1033 return false
1034end

loadSteeringAngleNodeFromXML

Description
Load steering angle node from xml
Definition
loadSteeringAngleNodeFromXML()
Code
1341function Attachable:loadSteeringAngleNodeFromXML(entry, xmlFile, key)
1342 entry.node = xmlFile:getValue(key.."#node", nil, self.components, self.i3dMappings)
1343 entry.speed = xmlFile:getValue(key.."#speed", 25) / 1000
1344 entry.scale = xmlFile:getValue(key.."#scale", 1)
1345 entry.offset = xmlFile:getValue(key.."#offset", 0)
1346 entry.minSpeed = xmlFile:getValue(key.."#minSpeed", 0)
1347
1348 entry.currentAngle = 0
1349
1350 return true
1351end

loadSteeringAxleFromXML

Description
Definition
loadSteeringAxleFromXML()
Code
1309function Attachable:loadSteeringAxleFromXML(spec, xmlFile, key)
1310 spec.steeringAxleAngleScaleStart = xmlFile:getValue(key.."#startSpeed", 10)
1311 spec.steeringAxleAngleScaleEnd = xmlFile:getValue(key.."#endSpeed", 30)
1312 spec.steeringAxleAngleScaleSpeedDependent = xmlFile:getValue(key.."#speedDependent", true)
1313 spec.steeringAxleUpdateBackwards = xmlFile:getValue(key.."#backwards", false)
1314 spec.steeringAxleAngleSpeed = xmlFile:getValue(key.."#speed", 0.001)
1315 spec.steeringAxleUseSuperAttachable = xmlFile:getValue(key.."#useSuperAttachable", false)
1316 spec.steeringAxleTargetNode = xmlFile:getValue(key..".targetNode#node", nil, self.components, self.i3dMappings)
1317 spec.steeringAxleTargetNodeRefAngle = xmlFile:getValue(key..".targetNode#refAngle")
1318 spec.steeringAxleAngleMinRot = xmlFile:getValue(key.."#minRot", 0)
1319 spec.steeringAxleAngleMaxRot = xmlFile:getValue(key.."#maxRot", 0)
1320 spec.steeringAxleDirection = xmlFile:getValue(key.."#direction", 1)
1321 spec.steeringAxleForceUsage = xmlFile:getValue(key.."#forceUsage", spec.steeringAxleTargetNode ~= nil)
1322 spec.steeringAxleDistanceDelay = xmlFile:getValue(key.."#distanceDelay", 0)
1323
1324 local referenceComponentIndex = xmlFile:getValue(key.."#referenceComponentIndex")
1325 if referenceComponentIndex ~= nil then
1326 local component = self.components[referenceComponentIndex]
1327 if component ~= nil then
1328 spec.steeringAxleReferenceComponentNode = component.node
1329 end
1330 end
1331end

loadSupportAnimationFromXML

Description
Loads support animation from xml
Definition
loadSupportAnimationFromXML(table supportAnimation, int xmlFile, string key)
Arguments
tablesupportAnimationsupportAnimation
intxmlFilexmlFile id
stringkeykey to load from
Code
1147function Attachable:loadSupportAnimationFromXML(supportAnimation, xmlFile, key)
1148 supportAnimation.animationName = xmlFile:getValue(key.."#animationName")
1149 supportAnimation.delayedOnLoad = xmlFile:getValue(key.."#delayedOnLoad", false) -- defines if the animation is played onPostLoad or onLoadFinished -> useful if the animation collides e.g. with the folding animation
1150 supportAnimation.delayedOnAttach = xmlFile:getValue(key.."#delayedOnAttach", true) -- defines if the animation is played before or after the attaching process
1151 supportAnimation.detachAfterAnimation = xmlFile:getValue(key.."#detachAfterAnimation", true) -- defines if the vehicle is detached after the animation has played
1152 supportAnimation.detachAnimationTime = xmlFile:getValue(key.."#detachAnimationTime", 1) -- defines when in the support animation the vehicle is detached
1153
1154 return supportAnimation.animationName ~= nil
1155end

mountDynamic

Description
Definition
mountDynamic()
Code
1954function Attachable:mountDynamic(superFunc, object, objectActorId, jointNode, mountType, forceAcceleration)
1955 local spec = self.spec_attachable
1956
1957 if spec.attacherVehicle ~= nil then
1958 return false
1959 end
1960
1961 return superFunc(self, object, objectActorId, jointNode, mountType, forceAcceleration)
1962end

onDeactivate

Description
Called on deactivate
Definition
onDeactivate()
Code
1723function Attachable:onDeactivate()
1724 if self.brake ~= nil then
1725 local brakeForce = self:getBrakeForce()
1726 if brakeForce > 0 then
1727 self:brake(brakeForce, true)
1728 end
1729 end
1730end

onDelete

Description
Definition
onDelete()
Code
570function Attachable:onDelete()
571 local spec = self.spec_attachable
572
573 if spec.toolCameras ~= nil then
574 for _, camera in ipairs(spec.toolCameras) do
575 camera:delete()
576 end
577 end
578end

onFoldStateChanged

Description
Called while folding state changes
Definition
onFoldStateChanged()
Code
2203function Attachable:onFoldStateChanged(direction, moveToMiddle)
2204 local spec = self.spec_foldable
2205 if spec.foldMiddleAnimTime ~= nil then
2206 if not moveToMiddle and direction == spec.turnOnFoldDirection then
2207 SpecializationUtil.raiseEvent(self, "onSetLowered", true)
2208 else
2209 SpecializationUtil.raiseEvent(self, "onSetLowered", false)
2210 end
2211 end
2212end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
323function Attachable:onLoad(savegame)
324 local spec = self.spec_attachable
325
326 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.attacherJoint", "vehicle.inputAttacherJoints.inputAttacherJoint") -- FS15 to FS17
327 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.needsLowering", "vehicle.inputAttacherJoints.inputAttacherJoint#needsLowering") -- FS15 to FS17
328 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.allowsLowering", "vehicle.inputAttacherJoints.inputAttacherJoint#allowsLowering") -- FS15 to FS17
329 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.isDefaultLowered", "vehicle.inputAttacherJoints.inputAttacherJoint#isDefaultLowered") -- FS15 to FS17
330 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.forceSelectionOnAttach#value", "vehicle.inputAttacherJoints.inputAttacherJoint#forceSelectionOnAttach") -- FS15 to FS17
331 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.topReferenceNode#index", "vehicle.attacherJoint#topReferenceNode") -- FS15 to FS17
332 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.attachRootNode#index", "vehicle.attacherJoint#rootNode") -- FS15 to FS17
333
334 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.inputAttacherJoints", "vehicle.attachable.inputAttacherJoints") -- FS17 to FS19
335 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.inputAttacherJointConfigurations", "vehicle.attachable.inputAttacherJointConfigurations") -- FS17 to FS19
336 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.brakeForce", "vehicle.attachable.brakeForce#force") -- FS17 to FS22
337 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.attachable.brakeForce", "vehicle.attachable.brakeForce#force", nil, true) -- FS19 to FS22
338 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.steeringAxleAngleScale", "vehicle.attachable.steeringAxleAngleScale") -- FS17 to FS19
339 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.support", "vehicle.attachable.support") -- FS17 to FS19
340 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.lowerAnimation", "vehicle.attachable.lowerAnimation") -- FS17 to FS19
341 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.toolCameras", "vehicle.attachable.toolCameras") -- FS17 to FS19
342 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.attachable.toolCameras#count", "vehicle.attachable.toolCameras") -- FS17 to FS19
343 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.attachable.toolCameras.toolCamera1", "vehicle.attachable.toolCamera") -- FS17 to FS19
344 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.attachable.toolCameras.toolCamera2", "vehicle.attachable.toolCamera") -- FS17 to FS19
345 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.attachable.toolCameras.toolCamera3", "vehicle.attachable.toolCamera") -- FS17 to FS19
346
347 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.foldable.foldingParts#onlyFoldOnDetach", "vehicle.attachable#allowFoldingWhileAttached") -- FS17 to FS19
348 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.maximalAirConsumptionPerFullStop", "vehicle.attachable.airConsumer#usage (is now in usage per second at full brake power)") --FS17 to FS19
349
350 XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.attachable.steeringAxleAngleScale#targetNode", "vehicle.attachable.steeringAxleAngleScale.targetNode#node") --FS19 to FS22
351
352 spec.attacherJoint = nil
353
354 spec.inputAttacherJoints = {}
355 self.xmlFile:iterate("vehicle.attachable.inputAttacherJoints.inputAttacherJoint", function(i, key)
356 local inputAttacherJoint = {}
357 if self:loadInputAttacherJoint(self.xmlFile, key, inputAttacherJoint, i - 1) then
358 table.insert(spec.inputAttacherJoints, inputAttacherJoint)
359
360 inputAttacherJoint.jointInfo = g_currentMission:registerInputAttacherJoint(self, #spec.inputAttacherJoints, inputAttacherJoint)
361 end
362 end)
363
364 if self.configurations["inputAttacherJoint"] ~= nil then
365 local attacherConfigs = string.format("vehicle.attachable.inputAttacherJointConfigurations.inputAttacherJointConfiguration(%d)", self.configurations["inputAttacherJoint"]-1)
366 self.xmlFile:iterate(attacherConfigs..".inputAttacherJoint", function(i, baseName)
367 local inputAttacherJoint = {}
368 if self:loadInputAttacherJoint(self.xmlFile, baseName, inputAttacherJoint, i - 1) then
369 table.insert(spec.inputAttacherJoints, inputAttacherJoint)
370
371 inputAttacherJoint.jointInfo = g_currentMission:registerInputAttacherJoint(self, #spec.inputAttacherJoints, inputAttacherJoint)
372 end
373 end)
374 ObjectChangeUtil.updateObjectChanges(self.xmlFile, "vehicle.attachable.inputAttacherJointConfigurations.inputAttacherJointConfiguration", self.configurations["inputAttacherJoint"], self.components, self)
375 end
376
377 spec.brakeForce = self.xmlFile:getValue("vehicle.attachable.brakeForce#force", 0) * 10
378 spec.maxBrakeForce = self.xmlFile:getValue("vehicle.attachable.brakeForce#maxForce", 0) * 10
379 spec.loweredBrakeForce = self.xmlFile:getValue("vehicle.attachable.brakeForce#loweredForce", -1) * 10
380 spec.maxBrakeForceMass = self.xmlFile:getValue("vehicle.attachable.brakeForce#maxForceMass", 0) / 1000
381
382 spec.airConsumerUsage = self.xmlFile:getValue("vehicle.attachable.airConsumer#usage", 0)
383
384 spec.allowFoldingWhileAttached = self.xmlFile:getValue("vehicle.attachable#allowFoldingWhileAttached", true)
385 spec.allowFoldingWhileLowered = self.xmlFile:getValue("vehicle.attachable#allowFoldingWhileLowered", true)
386 spec.blockFoliageDestruction = self.xmlFile:getValue("vehicle.attachable#blockFoliageDestruction", false)
387
388 spec.requiresExternalPower = self.xmlFile:getValue("vehicle.attachable.power#requiresExternalPower", true)
389 spec.attachToPowerWarning = self.xmlFile:getValue("vehicle.attachable.power#attachToPowerWarning", "warning_attachToPower", self.customEnvironment)
390
391 spec.updateWheels = true
392 spec.updateSteeringAxleAngle = true
393
394 spec.isSelected = false
395 spec.attachTime = 0
396
397 spec.steeringAxleAngle = 0
398 spec.steeringAxleTargetAngle = 0
399
400 self:loadSteeringAxleFromXML(spec, self.xmlFile, "vehicle.attachable.steeringAxleAngleScale")
401
402 if spec.steeringAxleDistanceDelay > 0 then
403 spec.steeringAxleTargetAngleHistory = {}
404 for i=1, math.floor(spec.steeringAxleDistanceDelay / 0.1) do
405 spec.steeringAxleTargetAngleHistory[i] = 0
406 end
407 spec.steeringAxleTargetAngleHistoryIndex = 1
408 spec.steeringAxleTargetAngleHistoryMoved = 1
409 end
410
411 spec.steeringAngleNodes = {}
412 self.xmlFile:iterate("vehicle.attachable.steeringAngleNodes.steeringAngleNode", function(_, key)
413 local entry = {}
414 if self:loadSteeringAngleNodeFromXML(entry, self.xmlFile, key) then
415 table.insert(spec.steeringAngleNodes, entry)
416 end
417 end)
418
419 spec.detachingInProgress = false
420
421 spec.supportAnimations = {}
422 self.xmlFile:iterate("vehicle.attachable.support", function(_, baseKey)
423 local entry = {}
424 if self:loadSupportAnimationFromXML(entry, self.xmlFile, baseKey) then
425 table.insert(spec.supportAnimations, entry)
426 end
427 end)
428
429 spec.lowerAnimation = self.xmlFile:getValue("vehicle.attachable.lowerAnimation#name")
430 spec.lowerAnimationSpeed = self.xmlFile:getValue("vehicle.attachable.lowerAnimation#speed", 1)
431 spec.lowerAnimationDirectionOnDetach = self.xmlFile:getValue("vehicle.attachable.lowerAnimation#directionOnDetach", 0)
432 spec.lowerAnimationDefaultLowered = self.xmlFile:getValue("vehicle.attachable.lowerAnimation#defaultLowered", false)
433
434 spec.toolCameras = {}
435 self.xmlFile:iterate("vehicle.attachable.toolCameras.toolCamera", function(_, cameraKey)
436 local camera = VehicleCamera.new(self)
437 if camera:loadFromXML(self.xmlFile, cameraKey) then
438 table.insert(spec.toolCameras, camera)
439 end
440 end)
441
442 spec.isHardAttached = false
443 spec.isAdditionalAttachment = false
444
445 spec.texts = {}
446 spec.texts.liftObject = g_i18n:getText("action_liftOBJECT")
447 spec.texts.lowerObject = g_i18n:getText("action_lowerOBJECT")
448 spec.texts.warningFoldingAttached = g_i18n:getText("warning_foldingNotWhileAttached")
449 spec.texts.warningFoldingLowered = g_i18n:getText("warning_foldingNotWhileLowered")
450 spec.texts.warningFoldingAttacherJoint = g_i18n:getText("warning_foldingNotWhileAttachedToAttacherJoint")
451 spec.texts.lowerImplementFirst = g_i18n:getText("warning_lowerImplementFirst")
452end

onLoadFinished

Description
Called on load finished
Definition
onLoadFinished(table savegame)
Arguments
tablesavegamesavegame
Code
536function Attachable:onLoadFinished(savegame)
537 local spec = self.spec_attachable
538
539 for _, supportAnimation in ipairs(spec.supportAnimations) do
540 if supportAnimation.delayedOnLoad then
541 if self:getIsSupportAnimationAllowed(supportAnimation) then
542 self:playAnimation(supportAnimation.animationName, 1, nil, true, false)
543 AnimatedVehicle.updateAnimationByName(self, supportAnimation.animationName, 9999999, true)
544 end
545 end
546 end
547end

onPostLoad

Description
Called after loading
Definition
onPostLoad(table savegame)
Arguments
tablesavegamesavegame
Code
457function Attachable:onPostLoad(savegame)
458 local spec = self.spec_attachable
459
460 for _, supportAnimation in ipairs(spec.supportAnimations) do
461 if not supportAnimation.delayedOnLoad then
462 if self:getIsSupportAnimationAllowed(supportAnimation) then
463 self:playAnimation(supportAnimation.animationName, 1, nil, true, false)
464 AnimatedVehicle.updateAnimationByName(self, supportAnimation.animationName, 9999999, true)
465 end
466 end
467 end
468
469 if savegame ~= nil and not savegame.resetVehicles then
470 if spec.lowerAnimation ~= nil and self.playAnimation ~= nil then
471 local lowerAnimTime = savegame.xmlFile:getValue(savegame.key..".attachable#lowerAnimTime")
472 if lowerAnimTime ~= nil then
473 local speed = 1
474 if lowerAnimTime < 0.5 then
475 speed = -1
476 end
477 self:playAnimation(spec.lowerAnimation, speed, nil, true, false)
478 self:setAnimationTime(spec.lowerAnimation, lowerAnimTime)
479 AnimatedVehicle.updateAnimationByName(self, spec.lowerAnimation, 9999999, true)
480
481 if self.updateCylinderedInitial ~= nil then
482 self:updateCylinderedInitial(false)
483 end
484 end
485 end
486 else
487 if spec.lowerAnimationDefaultLowered then
488 self:playAnimation(spec.lowerAnimation, 1, nil, true, false)
489 AnimatedVehicle.updateAnimationByName(self, spec.lowerAnimation, 9999999, true)
490 end
491 end
492
493 for _, inputAttacherJoint in pairs(spec.inputAttacherJoints) do
494 if self.getMovingPartByNode ~= nil then
495 if inputAttacherJoint.steeringBarLeftNode ~= nil then
496 local movingPart = self:getMovingPartByNode(inputAttacherJoint.steeringBarLeftNode)
497 if movingPart ~= nil then
498 inputAttacherJoint.steeringBarLeftMovingPart = movingPart
499 else
500 inputAttacherJoint.steeringBarLeftNode = nil
501 end
502 end
503 if inputAttacherJoint.steeringBarRightNode ~= nil then
504 local movingPart = self:getMovingPartByNode(inputAttacherJoint.steeringBarRightNode)
505 if movingPart ~= nil then
506 inputAttacherJoint.steeringBarRightMovingPart = movingPart
507 else
508 inputAttacherJoint.steeringBarRightNode = nil
509 end
510 end
511 else
512 inputAttacherJoint.steeringBarLeftNode = nil
513 inputAttacherJoint.steeringBarRightNode = nil
514 end
515 end
516
517 if self.brake ~= nil then
518 local brakeForce = self:getBrakeForce()
519 if brakeForce > 0 then
520 self:brake(brakeForce, true)
521 end
522 end
523
524 spec.updateSteeringAxleAngle = #spec.steeringAngleNodes > 0 or spec.steeringAxleTargetNode ~= nil or (self.getWheels ~= nil and #self:getWheels() > 0)
525
526 if #spec.inputAttacherJoints > 0 then
527 g_currentMission:addAttachableVehicle(self)
528 else
529 SpecializationUtil.removeEventListener(self, "onUpdate", Attachable)
530 end
531end

onPreDelete

Description
Called on before deleting
Definition
onPreDelete()
Code
551function Attachable:onPreDelete()
552 local spec = self.spec_attachable
553
554 if spec.attacherVehicle ~= nil then
555 spec.attacherVehicle:detachImplementByObject(self, true)
556 end
557
558 if spec.inputAttacherJoints ~= nil then
559 for i=1, #spec.inputAttacherJoints do
560 local inputAttacherJoint = spec.inputAttacherJoints[i]
561 g_currentMission:removeInputAttacherJoint(inputAttacherJoint.jointInfo)
562 end
563 end
564
565 g_currentMission:removeAttachableVehicle(self)
566end

onReadStream

Description
Called on client side on join
Definition
onReadStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
594function Attachable:onReadStream(streamId, connection)
595 if streamReadBool(streamId) then
596 local object = NetworkUtil.readNodeObject(streamId)
597 local inputJointDescIndex = streamReadInt8(streamId)
598 local jointDescIndex = streamReadInt8(streamId)
599 local moveDown = streamReadBool(streamId)
600 local implementIndex = streamReadInt8(streamId)
601 if object ~= nil and object:getIsSynchronized() then
602 object:attachImplement(self, inputJointDescIndex, jointDescIndex, true, implementIndex, moveDown, true, true)
603 object:setJointMoveDown(jointDescIndex, moveDown, true)
604 end
605 end
606end

onRegisterAnimationValueTypes

Description
Called on pre load to register animation value types
Definition
onRegisterAnimationValueTypes()
Code
2216function Attachable:onRegisterAnimationValueTypes()
2217 local loadInputAttacherJoint = function(value, xmlFile, xmlKey)
2218 value.inputAttacherJointIndex = xmlFile:getValue(xmlKey .. "#inputAttacherJointIndex")
2219
2220 if value.inputAttacherJointIndex ~= nil then
2221 value:setWarningInformation("inputAttacherJointIndex: " .. value.inputAttacherJointIndex)
2222 value:addCompareParameters("inputAttacherJointIndex")
2223
2224 return true
2225 end
2226
2227 return false
2228 end
2229
2230 local resolveAttacherJoint = function(value)
2231 if value.inputAttacherJoint == nil then
2232 value.inputAttacherJoint = self:getInputAttacherJointByJointDescIndex(value.inputAttacherJointIndex)
2233 if value.inputAttacherJoint == nil then
2234 Logging.xmlWarning(self.xmlFile, "Unknown inputAttacherJointIndex '%s' for animation part.", value.inputAttacherJointIndex)
2235 value.inputAttacherJointIndex = nil
2236 return 0
2237 end
2238 end
2239 end
2240
2241 local updateJointSettings = function(...)
2242 local attacherVehicle = self:getAttacherVehicle()
2243 if attacherVehicle ~= nil then
2244 attacherVehicle:updateAttacherJointSettingsByObject(self, ...)
2245 end
2246 end
2247
2248 self:registerAnimationValueType("lowerRotLimitScale", "lowerRotLimitScaleStart", "lowerRotLimitScaleEnd", false, AnimationValueFloat,
2249 loadInputAttacherJoint,
2250
2251 function(value)
2252 if value.inputAttacherJointIndex ~= nil then
2253 resolveAttacherJoint(value)
2254 end
2255
2256 if value.inputAttacherJoint ~= nil then
2257 return unpack(value.inputAttacherJoint.lowerRotLimitScale)
2258 else
2259 return 0, 0, 0
2260 end
2261 end,
2262
2263 function(value, x, y, z)
2264 if value.inputAttacherJoint ~= nil then
2265 value.inputAttacherJoint.lowerRotLimitScale[1] = x
2266 value.inputAttacherJoint.lowerRotLimitScale[2] = y
2267 value.inputAttacherJoint.lowerRotLimitScale[3] = z
2268 updateJointSettings(true)
2269 end
2270 end)
2271
2272 self:registerAnimationValueType("upperRotLimitScale", "upperRotLimitScaleStart", "upperRotLimitScaleEnd", false, AnimationValueFloat,
2273 loadInputAttacherJoint,
2274
2275 function(value)
2276 if value.inputAttacherJointIndex ~= nil then
2277 resolveAttacherJoint(value)
2278 end
2279
2280 if value.inputAttacherJoint ~= nil then
2281 return unpack(value.inputAttacherJoint.upperRotLimitScale)
2282 else
2283 return 0, 0, 0
2284 end
2285 end,
2286
2287 function(value, x, y, z)
2288 if value.inputAttacherJoint ~= nil then
2289 value.inputAttacherJoint.upperRotLimitScale[1] = x
2290 value.inputAttacherJoint.upperRotLimitScale[2] = y
2291 value.inputAttacherJoint.upperRotLimitScale[3] = z
2292 updateJointSettings(true)
2293 end
2294 end)
2295
2296 self:registerAnimationValueType("lowerTransLimitScale", "lowerTransLimitScaleStart", "lowerTransLimitScaleEnd", false, AnimationValueFloat,
2297 loadInputAttacherJoint,
2298
2299 function(value)
2300 if value.inputAttacherJointIndex ~= nil then
2301 resolveAttacherJoint(value)
2302 end
2303
2304 if value.inputAttacherJoint ~= nil then
2305 return unpack(value.inputAttacherJoint.lowerTransLimitScale)
2306 else
2307 return 0, 0, 0
2308 end
2309 end,
2310
2311 function(value, x, y, z)
2312 if value.inputAttacherJoint ~= nil then
2313 value.inputAttacherJoint.lowerTransLimitScale[1] = x
2314 value.inputAttacherJoint.lowerTransLimitScale[2] = y
2315 value.inputAttacherJoint.lowerTransLimitScale[3] = z
2316 updateJointSettings(true)
2317 end
2318 end)
2319
2320 self:registerAnimationValueType("upperTransLimitScale", "upperTransLimitScaleStart", "upperTransLimitScaleEnd", false, AnimationValueFloat,
2321 loadInputAttacherJoint,
2322
2323 function(value)
2324 if value.inputAttacherJointIndex ~= nil then
2325 resolveAttacherJoint(value)
2326 end
2327
2328 if value.inputAttacherJoint ~= nil then
2329 return unpack(value.inputAttacherJoint.upperTransLimitScale)
2330 else
2331 return 0, 0, 0
2332 end
2333 end,
2334
2335 function(value, x, y, z)
2336 if value.inputAttacherJoint ~= nil then
2337 value.inputAttacherJoint.upperTransLimitScale[1] = x
2338 value.inputAttacherJoint.upperTransLimitScale[2] = y
2339 value.inputAttacherJoint.upperTransLimitScale[3] = z
2340 updateJointSettings(true)
2341 end
2342 end)
2343
2344 self:registerAnimationValueType("lowerRotationOffset", "lowerRotationOffsetStart", "lowerRotationOffsetEnd", false, AnimationValueFloat,
2345 loadInputAttacherJoint,
2346
2347 function(value)
2348 if value.inputAttacherJointIndex ~= nil then
2349 resolveAttacherJoint(value)
2350 end
2351
2352 if value.inputAttacherJoint ~= nil then
2353 return value.inputAttacherJoint.lowerRotationOffset
2354 else
2355 return 0
2356 end
2357 end,
2358
2359 function(value, lowerRotationOffset)
2360 if value.inputAttacherJoint ~= nil then
2361 value.inputAttacherJoint.lowerRotationOffset = lowerRotationOffset
2362 updateJointSettings(false, true)
2363 end
2364 end)
2365
2366 self:registerAnimationValueType("upperRotationOffset", "upperRotationOffsetStart", "upperRotationOffsetEnd", false, AnimationValueFloat,
2367 loadInputAttacherJoint,
2368
2369 function(value)
2370 if value.inputAttacherJointIndex ~= nil then
2371 resolveAttacherJoint(value)
2372 end
2373
2374 if value.inputAttacherJoint ~= nil then
2375 return value.inputAttacherJoint.upperRotationOffset
2376 else
2377 return 0
2378 end
2379 end,
2380
2381 function(value, upperRotationOffset)
2382 if value.inputAttacherJoint ~= nil then
2383 value.inputAttacherJoint.upperRotationOffset = upperRotationOffset
2384 updateJointSettings(false, true)
2385 end
2386 end)
2387
2388 self:registerAnimationValueType("lowerDistanceToGround", "lowerDistanceToGroundStart", "lowerDistanceToGroundEnd", false, AnimationValueFloat,
2389 loadInputAttacherJoint,
2390
2391 function(value)
2392 if value.inputAttacherJointIndex ~= nil then
2393 resolveAttacherJoint(value)
2394 end
2395
2396 if value.inputAttacherJoint ~= nil then
2397 return value.inputAttacherJoint.lowerDistanceToGround
2398 else
2399 return 0
2400 end
2401 end,
2402
2403 function(value, lowerDistanceToGround)
2404 if value.inputAttacherJoint ~= nil then
2405 value.inputAttacherJoint.lowerDistanceToGround = lowerDistanceToGround
2406 updateJointSettings(false, false, true)
2407 end
2408 end)
2409
2410 self:registerAnimationValueType("upperDistanceToGround", "upperDistanceToGroundStart", "upperDistanceToGroundEnd", false, AnimationValueFloat,
2411 loadInputAttacherJoint,
2412
2413 function(value)
2414 if value.inputAttacherJointIndex ~= nil then
2415 resolveAttacherJoint(value)
2416 end
2417
2418 if value.inputAttacherJoint ~= nil then
2419 return value.inputAttacherJoint.upperDistanceToGround
2420 else
2421 return 0
2422 end
2423 end,
2424
2425 function(value, upperDistanceToGround)
2426 if value.inputAttacherJoint ~= nil then
2427 value.inputAttacherJoint.upperDistanceToGround = upperDistanceToGround
2428 updateJointSettings(false, false, true)
2429 end
2430 end)
2431end

onRootVehicleChanged

Description
Called if root vehicle changes
Definition
onRootVehicleChanged(table rootVehicle)
Arguments
tablerootVehicleroot vehicle
Code
2191function Attachable:onRootVehicleChanged(rootVehicle)
2192 local spec = self.spec_attachable
2193 local actionController = rootVehicle.actionController
2194 if actionController ~= nil then
2195 if spec.controlledAction ~= nil then
2196 spec.controlledAction:updateParent(actionController)
2197 end
2198 end
2199end

onSelect

Description
Definition
onSelect()
Code
1734function Attachable:onSelect(subSelectionIndex)
1735 local attacherVehicle = self:getAttacherVehicle()
1736 if attacherVehicle ~= nil then
1737 attacherVehicle:setSelectedImplementByObject(self)
1738 end
1739end

onStateChange

Description
Definition
onStateChange()
Code
2176function Attachable:onStateChange(state, data)
2177 if self.getAILowerIfAnyIsLowered ~= nil then
2178 if self:getAILowerIfAnyIsLowered() then
2179 if state == Vehicle.STATE_CHANGE_AI_START_LINE then
2180 Attachable.actionControllerLowerImplementEvent(self, 1)
2181 elseif state == Vehicle.STATE_CHANGE_AI_END_LINE then
2182 Attachable.actionControllerLowerImplementEvent(self, -1)
2183 end
2184 end
2185 end
2186end

onUnselect

Description
Definition
onUnselect()
Code
1743function Attachable:onUnselect()
1744 local attacherVehicle = self:getAttacherVehicle()
1745 if attacherVehicle ~= nil then
1746 attacherVehicle:setSelectedImplementByObject(nil)
1747 end
1748end

onUpdate

Description
Called on update
Definition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
637function Attachable:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
638 local spec = self.spec_attachable
639
640 local yRot
641 if spec.updateSteeringAxleAngle then
642 if self:getLastSpeed() > 0.25 or not self.finishedFirstUpdate then
643 local steeringAngle = 0
644 local baseVehicle = self:getSteeringAxleBaseVehicle()
645 if (baseVehicle ~= nil or spec.steeringAxleReferenceComponentNode ~= nil) and (self.movingDirection >= 0 or spec.steeringAxleUpdateBackwards) then
646 yRot = Utils.getYRotationBetweenNodes(self.steeringAxleNode, spec.steeringAxleReferenceComponentNode or baseVehicle.steeringAxleNode)
647
648 local scale = 1
649 if spec.steeringAxleAngleScaleSpeedDependent then
650 local startSpeed = spec.steeringAxleAngleScaleStart
651 local endSpeed = spec.steeringAxleAngleScaleEnd
652 scale = MathUtil.clamp(1 + (self:getLastSpeed()-startSpeed) * 1.0/(startSpeed-endSpeed), 0, 1)
653 end
654 steeringAngle = yRot * scale
655 elseif self:getLastSpeed() > 0.2 then
656 steeringAngle = 0
657 end
658
659 if not self:getIsSteeringAxleAllowed() then
660 steeringAngle = 0
661 end
662
663 if spec.steeringAxleDistanceDelay > 0 then
664 spec.steeringAxleTargetAngleHistoryMoved = spec.steeringAxleTargetAngleHistoryMoved + self.lastMovedDistance
665 if spec.steeringAxleTargetAngleHistoryMoved > 0.1 then
666 spec.steeringAxleTargetAngleHistory[spec.steeringAxleTargetAngleHistoryIndex] = steeringAngle
667
668 spec.steeringAxleTargetAngleHistoryIndex = spec.steeringAxleTargetAngleHistoryIndex + 1
669 if spec.steeringAxleTargetAngleHistoryIndex > #spec.steeringAxleTargetAngleHistory then
670 spec.steeringAxleTargetAngleHistoryIndex = 1
671 end
672 end
673
674 local lastIndex = spec.steeringAxleTargetAngleHistoryIndex + 1
675 if lastIndex > #spec.steeringAxleTargetAngleHistory then
676 lastIndex = 1
677 end
678 spec.steeringAxleTargetAngle = spec.steeringAxleTargetAngleHistory[lastIndex]
679 else
680 spec.steeringAxleTargetAngle = steeringAngle
681 end
682
683 local dir = MathUtil.sign(spec.steeringAxleTargetAngle - spec.steeringAxleAngle)
684 local speed = spec.steeringAxleAngleSpeed
685 if not self.finishedFirstUpdate then
686 speed = 9999
687 end
688 if dir == 1 then
689 spec.steeringAxleAngle = math.min(spec.steeringAxleAngle + dir*dt*speed, spec.steeringAxleTargetAngle)
690 else
691 spec.steeringAxleAngle = math.max(spec.steeringAxleAngle + dir*dt*speed, spec.steeringAxleTargetAngle)
692 end
693
694 if spec.steeringAxleTargetNode ~= nil then
695 local angle
696 if spec.steeringAxleTargetNodeRefAngle ~= nil then
697 local alpha = MathUtil.clamp(spec.steeringAxleAngle / spec.steeringAxleTargetNodeRefAngle, -1, 1)
698 if alpha >= 0 then
699 angle = spec.steeringAxleAngleMaxRot * alpha
700 else
701 angle = spec.steeringAxleAngleMinRot * -alpha
702 end
703 else
704 angle = MathUtil.clamp(spec.steeringAxleAngle, spec.steeringAxleAngleMinRot, spec.steeringAxleAngleMaxRot)
705 end
706
707 setRotation(spec.steeringAxleTargetNode, 0, angle * spec.steeringAxleDirection, 0)
708 self:setMovingToolDirty(spec.steeringAxleTargetNode)
709 end
710 end
711 end
712
713 local numSteeringAngleNodes = #spec.steeringAngleNodes
714 if numSteeringAngleNodes > 0 and yRot == nil then
715 local baseVehicle = self:getSteeringAxleBaseVehicle()
716 if baseVehicle ~= nil then
717 yRot = Utils.getYRotationBetweenNodes(self.steeringAxleNode, baseVehicle.steeringAxleNode)
718 end
719 end
720 if yRot ~= nil then
721 for i=1, numSteeringAngleNodes do
722 self:updateSteeringAngleNode(spec.steeringAngleNodes[i], yRot, dt)
723 end
724 end
725
726 local attacherVehicle = self:getAttacherVehicle()
727
728 if spec.detachingInProgress then
729 local doDetach = false
730 for i=1, #spec.supportAnimations do
731 local animation = spec.supportAnimations[i]
732 if animation.detachAfterAnimation then
733 if not self:getIsAnimationPlaying(animation.animationName) then
734 doDetach = true
735 elseif animation.detachAnimationTime < 1 then
736 if self:getAnimationTime(animation.animationName) > animation.detachAnimationTime then
737 doDetach = true
738 end
739 end
740 end
741 end
742
743 if doDetach then
744 if attacherVehicle ~= nil then
745 attacherVehicle:detachImplementByObject(self)
746 end
747
748 spec.detachingInProgress = false
749 end
750 end
751
752 if attacherVehicle ~= nil then
753 if self.currentUpdateDistance < attacherVehicle.spec_attacherJoints.maxUpdateDistance then
754 if self.updateLoopIndex == attacherVehicle.updateLoopIndex then
755 local implement = attacherVehicle:getImplementByObject(self)
756 if implement ~= nil then
757 attacherVehicle:updateAttacherJointGraphics(implement, dt, true)
758 end
759 end
760 end
761 end
762end

onUpdateTick

Description
Called on update tick
Definition
onUpdateTick(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
769function Attachable:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
770 local spec = self.spec_attachable
771 for i=1, #spec.inputAttacherJoints do
772 local inputAttacherJoint = spec.inputAttacherJoints[i]
773 g_currentMission:updateInputAttacherJoint(inputAttacherJoint.jointInfo)
774 end
775end

onWriteStream

Description
Called on server side on join
Definition
onWriteStream(integer streamId, integer connection)
Arguments
integerstreamIdstreamId
integerconnectionconnection
Code
612function Attachable:onWriteStream(streamId, connection)
613 local spec = self.spec_attachable
614
615 streamWriteBool(streamId, spec.attacherVehicle ~= nil)
616 if spec.attacherVehicle ~= nil then
617 local attacherJointVehicleSpec = spec.attacherVehicle.spec_attacherJoints
618 local implementIndex = spec.attacherVehicle:getImplementIndexByObject(self)
619 local implement = attacherJointVehicleSpec.attachedImplements[implementIndex]
620 local inputJointDescIndex = spec.inputAttacherJointDescIndex
621 local jointDescIndex = implement.jointDescIndex
622 local jointDesc = attacherJointVehicleSpec.attacherJoints[jointDescIndex]
623 local moveDown = jointDesc.moveDown
624 NetworkUtil.writeNodeObject(streamId, spec.attacherVehicle)
625 streamWriteInt8(streamId, inputJointDescIndex)
626 streamWriteInt8(streamId, jointDescIndex)
627 streamWriteBool(streamId, moveDown)
628 streamWriteInt8(streamId, implementIndex)
629 end
630end

postAttach

Description
Called if vehicle gets attached
Definition
postAttach(table attacherVehicle, integer inputJointDescIndex, integer jointDescIndex, boolean loadFromSavegame)
Arguments
tableattacherVehicleattacher vehicle
integerinputJointDescIndexindex of input attacher joint
integerjointDescIndexindex of attacher joint it gets attached to
booleanloadFromSavegameattachment is loaded from savegame
Code
1459function Attachable:postAttach(attacherVehicle, inputJointDescIndex, jointDescIndex, loadFromSavegame)
1460 local spec = self.spec_attachable
1461
1462 -- only activate tool if root vehicle is controlled (activated). We don't want to activate a tool that is attached during loading
1463 local rootVehicle = self.rootVehicle
1464 if rootVehicle ~= nil and rootVehicle.getIsControlled ~= nil and rootVehicle:getIsControlled() then
1465 self:activate()
1466 end
1467
1468 if self.setLightsTypesMask ~= nil then
1469 local lightsSpecAttacherVehicle = attacherVehicle.spec_lights
1470 if lightsSpecAttacherVehicle ~= nil then
1471 self:setLightsTypesMask(lightsSpecAttacherVehicle.lightsTypesMask, true, true)
1472 self:setBeaconLightsVisibility(lightsSpecAttacherVehicle.beaconLightsActive, true, true)
1473 self:setTurnLightState(lightsSpecAttacherVehicle.turnLightState, true, true)
1474 end
1475 end
1476
1477 spec.attachTime = g_currentMission.time
1478
1479 for _, supportAnimation in ipairs(spec.supportAnimations) do
1480 if self:getIsSupportAnimationAllowed(supportAnimation) then
1481 if supportAnimation.delayedOnAttach then
1482 local skipAnimation = self.propertyState == Vehicle.PROPERTY_STATE_SHOP_CONFIG or loadFromSavegame
1483
1484 self:playAnimation(supportAnimation.animationName, -1, nil, true, not skipAnimation)
1485 if skipAnimation then
1486 AnimatedVehicle.updateAnimationByName(self, supportAnimation.animationName, 9999999, true)
1487 end
1488 end
1489 end
1490 end
1491
1492 self:attachableAddToolCameras()
1493
1494 ObjectChangeUtil.setObjectChanges(spec.attacherJoint.changeObjects, true, self, self.setMovingToolDirty)
1495
1496 local jointDesc = attacherVehicle:getAttacherJointByJointDescIndex(jointDescIndex)
1497 if jointDesc.steeringBarLeftNode ~= nil and spec.attacherJoint.steeringBarLeftMovingPart ~= nil then
1498 for _,movingPart in pairs(self.spec_cylindered.movingParts) do
1499 if movingPart.referencePoint == spec.attacherJoint.steeringBarLeftMovingPart.referencePoint and movingPart ~= spec.attacherJoint.steeringBarLeftMovingPart then
1500 movingPart.referencePoint = jointDesc.steeringBarLeftNode
1501 end
1502 end
1503 spec.attacherJoint.steeringBarLeftMovingPart.referencePoint = jointDesc.steeringBarLeftNode
1504 end
1505 if jointDesc.steeringBarRightNode ~= nil and spec.attacherJoint.steeringBarRightMovingPart ~= nil then
1506 for _,movingPart in pairs(self.spec_cylindered.movingParts) do
1507 if movingPart.referencePoint == spec.attacherJoint.steeringBarRightMovingPart.referencePoint and movingPart ~= spec.attacherJoint.steeringBarRightMovingPart then
1508 movingPart.referencePoint = jointDesc.steeringBarRightNode
1509 end
1510 end
1511 spec.attacherJoint.steeringBarRightMovingPart.referencePoint = jointDesc.steeringBarRightNode
1512 end
1513
1514 local actionController = self.rootVehicle.actionController
1515 if actionController ~= nil then
1516 local inputJointDesc = self:getActiveInputAttacherJoint()
1517 if inputJointDesc ~= nil then
1518 if inputJointDesc.needsLowering and inputJointDesc.allowsLowering and jointDesc.allowsLowering then
1519 spec.controlledAction = actionController:registerAction("lower", InputAction.LOWER_IMPLEMENT, 2)
1520 spec.controlledAction:setCallback(self, Attachable.actionControllerLowerImplementEvent)
1521 spec.controlledAction:setFinishedFunctions(self, self.getIsLowered, true, false)
1522 spec.controlledAction:setIsSaved(true)
1523 if self:getAINeedsLowering() then
1524 spec.controlledAction:addAIEventListener(self, "onAIImplementStartLine", 1, true)
1525 spec.controlledAction:addAIEventListener(self, "onAIImplementEndLine", -1)
1526 spec.controlledAction:addAIEventListener(self, "onAIImplementPrepare", -1)
1527 end
1528 end
1529 end
1530 end
1531
1532 SpecializationUtil.raiseEvent(self, "onPostAttach", attacherVehicle, inputJointDescIndex, jointDescIndex, loadFromSavegame)
1533end

postDetach

Description
Definition
postDetach()
Code
1548function Attachable:postDetach(implementIndex)
1549 local spec = self.spec_attachable
1550
1551 self:deactivate()
1552
1553 ObjectChangeUtil.setObjectChanges(spec.attacherJoint.changeObjects, false, self, self.setMovingToolDirty)
1554
1555
1556 if self.playAnimation ~= nil then
1557 for _, supportAnimation in ipairs(spec.supportAnimations) do
1558 if self:getIsSupportAnimationAllowed(supportAnimation) then
1559 if not supportAnimation.detachAfterAnimation then
1560 self:playAnimation(supportAnimation.animationName, 1, nil, true)
1561 else
1562 if self:getAnimationTime(supportAnimation.animationName) < 1 then
1563 self:playAnimation(supportAnimation.animationName, 1, nil, true)
1564 end
1565 end
1566 end
1567 end
1568
1569 if spec.lowerAnimation ~= nil and spec.lowerAnimationDirectionOnDetach ~= 0 then
1570 self:playAnimation(spec.lowerAnimation, spec.lowerAnimationDirectionOnDetach, nil, true)
1571 end
1572 end
1573
1574 self:attachableRemoveToolCameras()
1575
1576 for _, additionalObject in ipairs(spec.attacherJoint.additionalObjects) do
1577 setVisibility(additionalObject.node, false)
1578 end
1579
1580 spec.attacherVehicle = nil
1581
1582 spec.attacherJoint = nil
1583 spec.attacherJointIndex = nil
1584
1585 spec.inputAttacherJointDescIndex = nil
1586
1587 SpecializationUtil.raiseEvent(self, "onPostDetach")
1588end

preAttach

Description
Called before vehicle gets attached
Definition
preAttach(table attacherVehicle, integer inputAttacherJointDescIndex, boolean loadFromSavegame)
Arguments
tableattacherVehicleattacher vehicle
integerinputAttacherJointDescIndexindex of input attacher joint
booleanloadFromSavegameattachment is loaded from savegame
Code
1407function Attachable:preAttach(attacherVehicle, inputJointDescIndex, jointDescIndex, loadFromSavegame)
1408 local spec = self.spec_attachable
1409
1410 spec.attacherVehicle = attacherVehicle
1411 spec.attacherJoint = spec.inputAttacherJoints[inputJointDescIndex]
1412 spec.inputAttacherJointDescIndex = inputJointDescIndex
1413
1414
1415 local distanceToGroundByVehicle = spec.attacherJoint.distanceToGroundByVehicle
1416 if #spec.attacherJoint.distanceToGroundByVehicle > 0 then
1417 local useDefault = true
1418 for i=1, #distanceToGroundByVehicle do
1419 local vehicleData = distanceToGroundByVehicle[i]
1420 if attacherVehicle.configFileName:lower():endsWith(vehicleData.filename) then
1421 spec.attacherJoint.lowerDistanceToGround = vehicleData.lower
1422 spec.attacherJoint.upperDistanceToGround = vehicleData.upper
1423 useDefault = false
1424 end
1425 end
1426
1427 if useDefault then
1428 spec.attacherJoint.lowerDistanceToGround = spec.attacherJoint.lowerDistanceToGroundOriginal
1429 spec.attacherJoint.upperDistanceToGround = spec.attacherJoint.upperDistanceToGroundOriginal
1430 end
1431 end
1432
1433 for _, additionalObject in ipairs(spec.attacherJoint.additionalObjects) do
1434 setVisibility(additionalObject.node, additionalObject.attacherVehiclePath == NetworkUtil.convertToNetworkFilename(attacherVehicle.configFileName))
1435 end
1436
1437 for _, supportAnimation in ipairs(spec.supportAnimations) do
1438 if self:getIsSupportAnimationAllowed(supportAnimation) then
1439 if not supportAnimation.delayedOnAttach then
1440 local skipAnimation = self.propertyState == Vehicle.PROPERTY_STATE_SHOP_CONFIG or loadFromSavegame
1441
1442 self:playAnimation(supportAnimation.animationName, -1, nil, true, not skipAnimation)
1443 if skipAnimation then
1444 AnimatedVehicle.updateAnimationByName(self, supportAnimation.animationName, 9999999, true)
1445 end
1446 end
1447 end
1448 end
1449
1450 SpecializationUtil.raiseEvent(self, "onPreAttach", attacherVehicle, inputJointDescIndex, jointDescIndex)
1451end

preDetach

Description
Definition
preDetach()
Code
1537function Attachable:preDetach(attacherVehicle, implement)
1538 local spec = self.spec_attachable
1539 if spec.controlledAction ~= nil then
1540 spec.controlledAction:remove()
1541 end
1542
1543 SpecializationUtil.raiseEvent(self, "onPreDetach", attacherVehicle, implement)
1544end

prerequisitesPresent

Description
Checks if all prerequisite specializations are loaded
Definition
prerequisitesPresent(table specializations)
Arguments
tablespecializationsspecializations
Return Values
booleanhasPrerequisitetrue if all prerequisite specializations are loaded
Code
23function Attachable.prerequisitesPresent(specializations)
24 return true
25end

registerEventListeners

Description
Definition
registerEventListeners()
Code
119function Attachable.registerEventListeners(vehicleType)
120 SpecializationUtil.registerEventListener(vehicleType, "onLoad", Attachable)
121 SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", Attachable)
122 SpecializationUtil.registerEventListener(vehicleType, "onLoadFinished", Attachable)
123 SpecializationUtil.registerEventListener(vehicleType, "onPreDelete", Attachable)
124 SpecializationUtil.registerEventListener(vehicleType, "onDelete", Attachable)
125 SpecializationUtil.registerEventListener(vehicleType, "onReadStream", Attachable)
126 SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", Attachable)
127 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", Attachable)
128 SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", Attachable)
129 SpecializationUtil.registerEventListener(vehicleType, "onDeactivate", Attachable)
130 SpecializationUtil.registerEventListener(vehicleType, "onSelect", Attachable)
131 SpecializationUtil.registerEventListener(vehicleType, "onUnselect", Attachable)
132 SpecializationUtil.registerEventListener(vehicleType, "onStateChange", Attachable)
133 SpecializationUtil.registerEventListener(vehicleType, "onRootVehicleChanged", Attachable)
134 SpecializationUtil.registerEventListener(vehicleType, "onFoldStateChanged", Attachable)
135 SpecializationUtil.registerEventListener(vehicleType, "onRegisterAnimationValueTypes", Attachable)
136end

registerEvents

Description
Definition
registerEvents()
Code
29function Attachable.registerEvents(vehicleType)
30 SpecializationUtil.registerEvent(vehicleType, "onPreAttach")
31 SpecializationUtil.registerEvent(vehicleType, "onPostAttach")
32 SpecializationUtil.registerEvent(vehicleType, "onPreDetach")
33 SpecializationUtil.registerEvent(vehicleType, "onPostDetach")
34 SpecializationUtil.registerEvent(vehicleType, "onSetLowered")
35 SpecializationUtil.registerEvent(vehicleType, "onSetLoweredAll")
36 SpecializationUtil.registerEvent(vehicleType, "onLeaveRootVehicle")
37end

registerFunctions

Description
Definition
registerFunctions()
Code
41function Attachable.registerFunctions(vehicleType)
42 SpecializationUtil.registerFunction(vehicleType, "loadInputAttacherJoint", Attachable.loadInputAttacherJoint)
43 SpecializationUtil.registerFunction(vehicleType, "loadAttacherJointHeightNode", Attachable.loadAttacherJointHeightNode)
44 SpecializationUtil.registerFunction(vehicleType, "getIsAttacherJointHeightNodeActive", Attachable.getIsAttacherJointHeightNodeActive)
45 SpecializationUtil.registerFunction(vehicleType, "getInputAttacherJointByJointDescIndex", Attachable.getInputAttacherJointByJointDescIndex)
46 SpecializationUtil.registerFunction(vehicleType, "getInputAttacherJointIndexByNode", Attachable.getInputAttacherJointIndexByNode)
47 SpecializationUtil.registerFunction(vehicleType, "getAttacherVehicle", Attachable.getAttacherVehicle)
48 SpecializationUtil.registerFunction(vehicleType, "getInputAttacherJoints", Attachable.getInputAttacherJoints)
49 SpecializationUtil.registerFunction(vehicleType, "getIsAttachedTo", Attachable.getIsAttachedTo)
50 SpecializationUtil.registerFunction(vehicleType, "getActiveInputAttacherJointDescIndex", Attachable.getActiveInputAttacherJointDescIndex)
51 SpecializationUtil.registerFunction(vehicleType, "getActiveInputAttacherJoint", Attachable.getActiveInputAttacherJoint)
52 SpecializationUtil.registerFunction(vehicleType, "getAllowsLowering", Attachable.getAllowsLowering)
53 SpecializationUtil.registerFunction(vehicleType, "loadSupportAnimationFromXML", Attachable.loadSupportAnimationFromXML)
54 SpecializationUtil.registerFunction(vehicleType, "getIsSupportAnimationAllowed", Attachable.getIsSupportAnimationAllowed)
55 SpecializationUtil.registerFunction(vehicleType, "startDetachProcess", Attachable.startDetachProcess)
56 SpecializationUtil.registerFunction(vehicleType, "getIsImplementChainLowered", Attachable.getIsImplementChainLowered)
57 SpecializationUtil.registerFunction(vehicleType, "getIsInWorkPosition", Attachable.getIsInWorkPosition)
58 SpecializationUtil.registerFunction(vehicleType, "getAttachbleAirConsumerUsage", Attachable.getAttachbleAirConsumerUsage)
59 SpecializationUtil.registerFunction(vehicleType, "isDetachAllowed", Attachable.isDetachAllowed)
60 SpecializationUtil.registerFunction(vehicleType, "isAttachAllowed", Attachable.isAttachAllowed)
61 SpecializationUtil.registerFunction(vehicleType, "getIsInputAttacherActive", Attachable.getIsInputAttacherActive)
62 SpecializationUtil.registerFunction(vehicleType, "getSteeringAxleBaseVehicle", Attachable.getSteeringAxleBaseVehicle)
63 SpecializationUtil.registerFunction(vehicleType, "loadSteeringAxleFromXML", Attachable.loadSteeringAxleFromXML)
64 SpecializationUtil.registerFunction(vehicleType, "getIsSteeringAxleAllowed", Attachable.getIsSteeringAxleAllowed)
65 SpecializationUtil.registerFunction(vehicleType, "loadSteeringAngleNodeFromXML", Attachable.loadSteeringAngleNodeFromXML)
66 SpecializationUtil.registerFunction(vehicleType, "updateSteeringAngleNode", Attachable.updateSteeringAngleNode)
67 SpecializationUtil.registerFunction(vehicleType, "attachableAddToolCameras", Attachable.attachableAddToolCameras)
68 SpecializationUtil.registerFunction(vehicleType, "attachableRemoveToolCameras", Attachable.attachableRemoveToolCameras)
69 SpecializationUtil.registerFunction(vehicleType, "preAttach", Attachable.preAttach)
70 SpecializationUtil.registerFunction(vehicleType, "postAttach", Attachable.postAttach)
71 SpecializationUtil.registerFunction(vehicleType, "preDetach", Attachable.preDetach)
72 SpecializationUtil.registerFunction(vehicleType, "postDetach", Attachable.postDetach)
73 SpecializationUtil.registerFunction(vehicleType, "setLowered", Attachable.setLowered)
74 SpecializationUtil.registerFunction(vehicleType, "setLoweredAll", Attachable.setLoweredAll)
75 SpecializationUtil.registerFunction(vehicleType, "setIsAdditionalAttachment", Attachable.setIsAdditionalAttachment)
76 SpecializationUtil.registerFunction(vehicleType, "getIsAdditionalAttachment", Attachable.getIsAdditionalAttachment)
77 SpecializationUtil.registerFunction(vehicleType, "setIsSupportVehicle", Attachable.setIsSupportVehicle)
78 SpecializationUtil.registerFunction(vehicleType, "getIsSupportVehicle", Attachable.getIsSupportVehicle)
79 SpecializationUtil.registerFunction(vehicleType, "registerLoweringActionEvent", Attachable.registerLoweringActionEvent)
80 SpecializationUtil.registerFunction(vehicleType, "getLoweringActionEventState", Attachable.getLoweringActionEventState)
81 SpecializationUtil.registerFunction(vehicleType, "getAllowMultipleAttachments", Attachable.getAllowMultipleAttachments)
82 SpecializationUtil.registerFunction(vehicleType, "resolveMultipleAttachments", Attachable.resolveMultipleAttachments)
83 SpecializationUtil.registerFunction(vehicleType, "getBlockFoliageDestruction", Attachable.getBlockFoliageDestruction)
84end

registerInputAttacherJointXMLPaths

Description
Definition
registerInputAttacherJointXMLPaths()
Code
244function Attachable.registerInputAttacherJointXMLPaths(schema, baseName)
245 schema:register(XMLValueType.NODE_INDEX, baseName .. "#node", "Joint Node")
246 schema:register(XMLValueType.NODE_INDEX, baseName .. ".heightNode(?)#node", "Height Node")
247
248 schema:register(XMLValueType.STRING, baseName .. "#jointType", "Joint type")
249 schema:register(XMLValueType.STRING, baseName .. ".subType#name", "If defined this type needs to match with the sub type in the attacher vehicle")
250 schema:register(XMLValueType.BOOL, baseName .. ".subType#showWarning", "Show warning if user tries to attach with a different sub type", true)
251
252 schema:register(XMLValueType.BOOL, baseName .. "#needsTrailerJoint", "Needs trailer joint (only if no joint type is given)", false)
253 schema:register(XMLValueType.BOOL, baseName .. "#needsLowJoint", "Needs low trailer joint (only if no joint type is given)", false)
254
255 schema:register(XMLValueType.NODE_INDEX, baseName .. "#topReferenceNode", "Top Reference Node")
256 schema:register(XMLValueType.NODE_INDEX, baseName .. "#rootNode", "Root node", "first component")
257
258 schema:register(XMLValueType.BOOL, baseName .. "#allowsDetaching", "Allows detaching", true)
259 schema:register(XMLValueType.BOOL, baseName .. "#fixedRotation", "Fixed rotation (Rot limit is freezed)", false)
260 schema:register(XMLValueType.BOOL, baseName .. "#hardAttach", "Implement is hard attached", false)
261
262 schema:register(XMLValueType.NODE_INDEX, baseName .. "#nodeVisual", "Visual joint node")
263 schema:register(XMLValueType.FLOAT, baseName .. ".distanceToGround#lower", "Lower distance to ground")
264 schema:register(XMLValueType.FLOAT, baseName .. ".distanceToGround#upper", "Upper distance to ground")
265 schema:register(XMLValueType.STRING, baseName .. ".distanceToGround.vehicle(?)#filename", "Vehicle filename to activate these distances")
266 schema:register(XMLValueType.FLOAT, baseName .. ".distanceToGround.vehicle(?)#lower", "Lower distance to ground while attached to this vehicle")
267 schema:register(XMLValueType.FLOAT, baseName .. ".distanceToGround.vehicle(?)#upper", "Upper distance to ground while attached to this vehicle")
268 schema:register(XMLValueType.ANGLE, baseName .. "#lowerRotationOffset", "Rotation offset if lowered")
269 schema:register(XMLValueType.ANGLE, baseName .. "#upperRotationOffset", "Rotation offset if lifted", "8 degrees for implements")
270 schema:register(XMLValueType.BOOL, baseName .. "#allowsJointRotLimitMovement", "Rotation limit is changed during lifting/lowering", true)
271 schema:register(XMLValueType.BOOL, baseName .. "#allowsJointTransLimitMovement", "Translation limit is changed during lifting/lowering", true)
272 schema:register(XMLValueType.BOOL, baseName .. "#needsToolbar", "Needs toolbar", false)
273
274 schema:register(XMLValueType.NODE_INDEX, baseName .. "#steeringBarLeftNode", "Left steering bar node")
275 schema:register(XMLValueType.NODE_INDEX, baseName .. "#steeringBarRightNode", "Right steering bar node")
276
277 schema:register(XMLValueType.VECTOR_3, baseName .. "#upperRotLimitScale", "Upper rot limit scale", "0 0 0")
278 schema:register(XMLValueType.VECTOR_3, baseName .. "#lowerRotLimitScale", "Lower rot limit scale", "0 0 0")
279 schema:register(XMLValueType.FLOAT, baseName .. "#rotLimitThreshold", "Defines when the transition from upper to lower rot limit starts (0: directly, 0.9: after 90% of lowering)", 0)
280
281 schema:register(XMLValueType.VECTOR_3, baseName .. "#upperTransLimitScale", "Upper trans limit scale", "0 0 0")
282 schema:register(XMLValueType.VECTOR_3, baseName .. "#lowerTransLimitScale", "Lower trans limit scale", "0 0 0")
283 schema:register(XMLValueType.FLOAT, baseName .. "#transLimitThreshold", "Defines when the transition from upper to lower trans limit starts (0: directly, 0.9: after 90% of lowering)", 0)
284
285 schema:register(XMLValueType.VECTOR_3, baseName .. "#rotLimitSpring", "Rotation limit spring", "0 0 0")
286 schema:register(XMLValueType.VECTOR_3, baseName .. "#rotLimitDamping", "Rotation limit damping", "1 1 1")
287 schema:register(XMLValueType.VECTOR_3, baseName .. "#rotLimitForceLimit", "Rotation limit force limit", "-1 -1 -1")
288
289 schema:register(XMLValueType.VECTOR_3, baseName .. "#transLimitSpring", "Translation limit spring", "0 0 0")
290 schema:register(XMLValueType.VECTOR_3, baseName .. "#transLimitDamping", "Translation limit damping", "1 1 1")
291 schema:register(XMLValueType.VECTOR_3, baseName .. "#transLimitForceLimit", "Translation limit force limit", "-1 -1 -1")
292
293 schema:register(XMLValueType.INT, baseName .. "#attachAngleLimitAxis", "Direction axis which is used to calculate angle to enable attach", 1)
294
295 schema:register(XMLValueType.FLOAT, baseName .. "#attacherHeight", "Height of attacher", "0.9 for trailer, 0.55 for trailer low")
296
297 schema:register(XMLValueType.BOOL, baseName .. "#needsLowering", "Needs lowering")
298 schema:register(XMLValueType.BOOL, baseName .. "#allowsLowering", "Allows lowering")
299 schema:register(XMLValueType.BOOL, baseName .. "#isDefaultLowered", "Is default lowered", false)
300 schema:register(XMLValueType.BOOL, baseName .. "#useFoldingLoweredState", "Use folding lowered state", false)
301 schema:register(XMLValueType.BOOL, baseName .. "#forceSelectionOnAttach", "Is selected on attach", true)
302 schema:register(XMLValueType.BOOL, baseName .. "#forceAllowDetachWhileLifted", "Attacher vehicle can be always detached no matter if we are lifted or not", false)
303 schema:register(XMLValueType.INT, baseName .. "#forcedAttachingDirection", "Tool can be only attached in this direction", 0)
304 schema:register(XMLValueType.BOOL, baseName .. "#allowFolding", "Folding is allowed while attached to this attacher joint", true)
305 schema:register(XMLValueType.BOOL, baseName .. "#allowTurnOn", "Turn on is allowed while attached to this attacher joint", true)
306 schema:register(XMLValueType.BOOL, baseName .. "#allowAI", "Toggeling of AI is allowed while attached to this attacher joint", true)
307 schema:register(XMLValueType.BOOL, baseName .. "#allowDetachWhileParentLifted", "If set to false the parent vehicle needs to be lowered to be able to detach this implement", true)
308
309 schema:register(XMLValueType.INT, baseName .. ".dependentAttacherJoint(?)#attacherJointIndex", "Dependent attacher joint index")
310
311 schema:register(XMLValueType.NODE_INDEX, baseName .. ".additionalObjects.additionalObject(?)#node", "Additional object node")
312 schema:register(XMLValueType.STRING, baseName .. ".additionalObjects.additionalObject(?)#attacherVehiclePath", "Path to vehicle for object activation")
313
314 schema:register(XMLValueType.STRING, baseName .. ".additionalAttachment#filename", "Path to additional attachment")
315 schema:register(XMLValueType.INT, baseName .. ".additionalAttachment#inputAttacherJointIndex", "Input attacher joint index of additional attachment")
316 schema:register(XMLValueType.BOOL, baseName .. ".additionalAttachment#needsLowering", "Additional implements needs lowering")
317 schema:register(XMLValueType.STRING, baseName .. ".additionalAttachment#jointType", "Additional implement joint type")
318end

registerLoweringActionEvent

Description
Definition
registerLoweringActionEvent()
Code
1675function Attachable:registerLoweringActionEvent(actionEventsTable, inputAction, target, callback, triggerUp, triggerDown, triggerAlways, startActive, callbackState, customIconName)
1676 self:addPoweredActionEvent(actionEventsTable, inputAction, target, callback, triggerUp, triggerDown, triggerAlways, startActive, callbackState, customIconName)
1677end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
88function Attachable.registerOverwrittenFunctions(vehicleType)
89 SpecializationUtil.registerOverwrittenFunction(vehicleType, "findRootVehicle", Attachable.findRootVehicle)
90 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsActive", Attachable.getIsActive)
91 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsOperating", Attachable.getIsOperating)
92 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getBrakeForce", Attachable.getBrakeForce)
93 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsFoldAllowed", Attachable.getIsFoldAllowed)
94 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanToggleTurnedOn", Attachable.getCanToggleTurnedOn)
95 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanImplementBeUsedForAI", Attachable.getCanImplementBeUsedForAI)
96 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanAIImplementContinueWork", Attachable.getCanAIImplementContinueWork)
97 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDeactivateOnLeave", Attachable.getDeactivateOnLeave)
98 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getActiveFarm", Attachable.getActiveFarm)
99 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeSelected", Attachable.getCanBeSelected)
100 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsLowered", Attachable.getIsLowered)
101 SpecializationUtil.registerOverwrittenFunction(vehicleType, "mountDynamic", Attachable.mountDynamic)
102 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getOwner", Attachable.getOwner)
103 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsInUse", Attachable.getIsInUse)
104 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getUpdatePriority", Attachable.getUpdatePriority)
105 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getCanBeReset", Attachable.getCanBeReset)
106 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadAdditionalLightAttributesFromXML", Attachable.loadAdditionalLightAttributesFromXML)
107 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsLightActive", Attachable.getIsLightActive)
108 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsPowered", Attachable.getIsPowered)
109 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getConnectionHoseConfigIndex", Attachable.getConnectionHoseConfigIndex)
110 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsMapHotspotVisible", Attachable.getIsMapHotspotVisible)
111 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getPowerTakeOffConfigIndex", Attachable.getPowerTakeOffConfigIndex)
112 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadDashboardGroupFromXML", Attachable.loadDashboardGroupFromXML)
113 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsDashboardGroupActive", Attachable.getIsDashboardGroupActive)
114 SpecializationUtil.registerOverwrittenFunction(vehicleType, "setWorldPositionQuaternion", Attachable.setWorldPositionQuaternion)
115end

resolveMultipleAttachments

Description
Function that is called before attaching a attachable to second vehicle
Definition
resolveMultipleAttachments()
Code
1711function Attachable:resolveMultipleAttachments()
1712end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
582function Attachable:saveToXMLFile(xmlFile, key, usedModNames)
583 local spec = self.spec_attachable
584 if spec.lowerAnimation ~= nil and self.playAnimation ~= nil then
585 local lowerAnimTime = self:getAnimationTime(spec.lowerAnimation)
586 xmlFile:setValue(key.."#lowerAnimTime", lowerAnimTime)
587 end
588end

setIsAdditionalAttachment

Description
Sets if vehicle is a additional attachment -> can not be detached or lowered
Definition
setIsAdditionalAttachment()
Code
1634function Attachable:setIsAdditionalAttachment(needsLowering, vehicleLoaded)
1635 local spec = self.spec_attachable
1636 spec.isAdditionalAttachment = true
1637 spec.additionalAttachmentNeedsLowering = needsLowering
1638
1639 if vehicleLoaded then
1640 self:requestActionEventUpdate()
1641
1642 if not needsLowering then
1643 if spec.controlledAction ~= nil then
1644 spec.controlledAction:remove()
1645 end
1646 end
1647 end
1648end

setIsSupportVehicle

Description
Sets if vehicle is a additional attachment -> can not be detached or lowered
Definition
setIsSupportVehicle()
Code
1658function Attachable:setIsSupportVehicle(state)
1659 local spec = self.spec_attachable
1660 if state == nil then
1661 state = true
1662 end
1663
1664 spec.isSupportVehicle = state
1665end

setLowered

Description
Set attachables lowering state
Definition
setLowered(boolean lowered)
Arguments
booleanloweredattachable is lowered
Code
1593function Attachable:setLowered(lowered)
1594 local spec = self.spec_attachable
1595
1596 if spec.lowerAnimation ~= nil and self.playAnimation ~= nil then
1597 if lowered then
1598 self:playAnimation(spec.lowerAnimation, spec.lowerAnimationSpeed, self:getAnimationTime(spec.lowerAnimation), true)
1599 else
1600 self:playAnimation(spec.lowerAnimation, -spec.lowerAnimationSpeed, self:getAnimationTime(spec.lowerAnimation), true)
1601 end
1602 end
1603
1604 if spec.attacherJoint ~= nil then
1605 for _, dependentAttacherJointIndex in pairs(spec.attacherJoint.dependentAttacherJoints) do
1606 if self.getAttacherJoints ~= nil then
1607 local attacherJoints = self:getAttacherJoints()
1608 if attacherJoints[dependentAttacherJointIndex] ~= nil then
1609 self:setJointMoveDown(dependentAttacherJointIndex, lowered, true)
1610 else
1611 Logging.xmlWarning(self.xmlFile, "Failed to lower dependent attacher joint index '%d', No attacher joint defined!", dependentAttacherJointIndex)
1612 end
1613 else
1614 Logging.xmlWarning(self.xmlFile, "Failed to lower dependent attacher joint index '%d', AttacherJoint specialization is missing!", dependentAttacherJointIndex)
1615 end
1616 end
1617 end
1618
1619 SpecializationUtil.raiseEvent(self, "onSetLowered", lowered)
1620end

setLoweredAll

Description
Set attachables lowering all state
Definition
setLoweredAll(boolean doLowering)
Arguments
booleandoLoweringdo lowering
Code
1626function Attachable:setLoweredAll(doLowering, jointDescIndex)
1627 self:getAttacherVehicle():handleLowerImplementByAttacherJointIndex(jointDescIndex, doLowering)
1628
1629 SpecializationUtil.raiseEvent(self, "onSetLoweredAll", doLowering, jointDescIndex)
1630end

setWorldPositionQuaternion

Description
Set world position and quaternion rotation of component
Definition
setWorldPositionQuaternion(float x, float y, float z, float qx, float qy, float qz, float qw, Integer i, boolean changeInterp)
Arguments
floatxx position
floatyy position
floatzz position
floatqxx rotation
floatqyy rotation
floatqzz rotation
floatqww rotation
Integeriindex if component
booleanchangeInterpchange interpolation
Code
2138function Attachable:setWorldPositionQuaternion(superFunc, x, y, z, qx, qy, qz, qw, i, changeInterp)
2139 if not self.isServer then
2140 -- while the object is hard attached and linked to the attacher vehicles
2141 -- received positions are not applied since the position is dependent on the attacher vehicle
2142 if not self.spec_attachable.isHardAttached then
2143 return superFunc(self, x, y, z, qx, qy, qz, qw, i, changeInterp)
2144 end
2145
2146 return
2147 end
2148
2149 return superFunc(self, x, y, z, qx, qy, qz, qw, i, changeInterp)
2150end

startDetachProcess

Description
Detaches the vehicle if no support animation has 'detachAfterAnimation' set or start the support animation and detaches the implement afterwards
Definition
startDetachProcess()
Code
1165function Attachable:startDetachProcess()
1166 local spec = self.spec_attachable
1167 local playedAnimation = false
1168 for i=1, #spec.supportAnimations do
1169 if spec.supportAnimations[i].detachAfterAnimation then
1170 if self:getIsSupportAnimationAllowed(spec.supportAnimations[i]) then
1171 self:playAnimation(spec.supportAnimations[i].animationName, 1, nil, true)
1172 playedAnimation = true
1173 end
1174 end
1175 end
1176
1177 spec.detachingInProgress = playedAnimation
1178
1179 if not playedAnimation then
1180 local attacherVehicle = self:getAttacherVehicle()
1181 if attacherVehicle ~= nil then
1182 attacherVehicle:detachImplementByObject(self)
1183 end
1184 end
1185
1186 return playedAnimation
1187end

updateSteeringAngleNode

Description
Update steering angle nodes
Definition
updateSteeringAngleNode()
Code
1355function Attachable:updateSteeringAngleNode(steeringAngleNode, angle, dt)
1356 if self.lastSpeed * 3600 > steeringAngleNode.minSpeed then
1357 local direction = MathUtil.sign(angle - steeringAngleNode.currentAngle)
1358 local limit = direction < 0 and math.max or math.min
1359 local newAngle = limit(steeringAngleNode.currentAngle + steeringAngleNode.speed * dt * direction, angle)
1360 if newAngle ~= steeringAngleNode.currentAngle then
1361 steeringAngleNode.currentAngle = newAngle
1362 setRotation(steeringAngleNode.node, 0, steeringAngleNode.offset + steeringAngleNode.currentAngle * steeringAngleNode.scale, 0)
1363
1364 if self.setMovingToolDirty ~= nil then
1365 self:setMovingToolDirty(steeringAngleNode.node)
1366 end
1367 end
1368 end
1369end