60 | function Lights.initSpecialization() |
61 | local schema = Vehicle.xmlSchema |
62 | schema:setXMLSpecializationType("Lights") |
63 | |
64 | schema:register(XMLValueType.FLOAT, "vehicle.lights#reverseLightActivationSpeed", "Speed which needs to be reached to activate reverse lights (km/h)", 1) |
65 | |
66 | schema:register(XMLValueType.VECTOR_N, "vehicle.lights.states.state(?)#lightTypes", "Light states") |
67 | |
68 | schema:register(XMLValueType.VECTOR_N, "vehicle.lights.states.aiState#lightTypes", "Light states while ai is active", "0") |
69 | schema:register(XMLValueType.VECTOR_N, "vehicle.lights.states.aiState#lightTypesWork", "Light states while ai is working", "0 1 2") |
70 | |
71 | |
72 | schema:register(XMLValueType.STRING, "vehicle.lights.sharedLight(?)#filename", "Shared light filename") |
73 | schema:register(XMLValueType.NODE_INDEX, "vehicle.lights.sharedLight(?)#linkNode", "Link node", "0>") |
74 | schema:register(XMLValueType.VECTOR_N, "vehicle.lights.sharedLight(?)#lightTypes", "Light types") |
75 | schema:register(XMLValueType.VECTOR_N, "vehicle.lights.sharedLight(?)#excludedLightTypes", "Excluded light types") |
76 | schema:register(XMLValueType.STRING, "vehicle.lights.sharedLight(?).rotationNode(?)#name", "Rotation node name") |
77 | schema:register(XMLValueType.VECTOR_ROT, "vehicle.lights.sharedLight(?).rotationNode(?)#rotation", "Rotation") |
78 | |
79 | Lights.registerRealLightSetupXMLPath(schema, "vehicle.lights.realLights.low") |
80 | Lights.registerRealLightSetupXMLPath(schema, "vehicle.lights.realLights.high") |
81 | |
82 | Lights.registerStaticLightXMLPath(schema, "vehicle.lights.defaultLights.defaultLight(?)") |
83 | Lights.registerStaticLightXMLPath(schema, "vehicle.lights.brakeLights.brakeLight(?)") |
84 | Lights.registerStaticLightXMLPath(schema, "vehicle.lights.reverseLights.reverseLight(?)") |
85 | Lights.registerStaticLightXMLPath(schema, "vehicle.lights.turnLights.turnLightLeft(?)") |
86 | Lights.registerStaticLightXMLPath(schema, "vehicle.lights.turnLights.turnLightRight(?)") |
87 | |
88 | schema:register(XMLValueType.NODE_INDEX, "vehicle.lights.beaconLights.beaconLight(?)#node", "Link node") |
89 | schema:register(XMLValueType.STRING, "vehicle.lights.beaconLights.beaconLight(?)#filename", "Beacon light xml file") |
90 | schema:register(XMLValueType.FLOAT, "vehicle.lights.beaconLights.beaconLight(?)#speed", "Beacon light speed override") |
91 | schema:register(XMLValueType.FLOAT, "vehicle.lights.beaconLights.beaconLight(?)#realLightRange", "Factor that is applied on real light range of the beacon light", 1) |
92 | schema:register(XMLValueType.INT, "vehicle.lights.beaconLights.beaconLight(?)#intensity", "Beacon light intensity override") |
93 | |
94 | schema:register(XMLValueType.NODE_INDEX, "vehicle.lights.beaconLights.beaconLight(?).realLight#node", "Real light node") |
95 | schema:register(XMLValueType.NODE_INDEX, "vehicle.lights.beaconLights.beaconLight(?).rotator#node", "Rotator node") |
96 | schema:register(XMLValueType.BOOL, "vehicle.lights.beaconLights.beaconLight(?)#multiBlink", "Is multiblink light") |
97 | |
98 | BeaconLightManager.registerXMLPaths(schema, "vehicle.lights.beaconLights.beaconLight(?).device") |
99 | |
100 | SoundManager.registerSampleXMLPaths(schema, "vehicle.lights.sounds", "toggleLights") |
101 | SoundManager.registerSampleXMLPaths(schema, "vehicle.lights.sounds", "turnLight") |
102 | |
103 | Dashboard.registerDashboardXMLPaths(schema, "vehicle.lights.dashboards", "lightState | turnLightLeft | turnLightRight | turnLight | turnLightHazard | turnLightAny | beaconLight") |
104 | schema:register(XMLValueType.VECTOR_N, "vehicle.lights.dashboards.dashboard(?)#lightTypes", "Light types") |
105 | schema:register(XMLValueType.VECTOR_N, "vehicle.lights.dashboards.dashboard(?)#excludedLightTypes", "Excluded light types") |
106 | |
107 | schema:setXMLSpecializationType() |
108 | |
109 | local sharedLightXMLSchema = XMLSchema.new("sharedLight") |
110 | |
111 | sharedLightXMLSchema:register(XMLValueType.STRING, "light.filename", "Path to i3d file", nil, true) |
112 | sharedLightXMLSchema:register(XMLValueType.NODE_INDEX, "light.rootNode#node", "Node index", "0") |
113 | |
114 | Lights.registerSharedLightXMLPath(sharedLightXMLSchema, "light.defaultLight(?)") |
115 | Lights.registerSharedLightXMLPath(sharedLightXMLSchema, "light.brakeLight(?)") |
116 | Lights.registerSharedLightXMLPath(sharedLightXMLSchema, "light.reverseLight(?)") |
117 | Lights.registerSharedLightXMLPath(sharedLightXMLSchema, "light.turnLightLeft(?)") |
118 | Lights.registerSharedLightXMLPath(sharedLightXMLSchema, "light.turnLightRight(?)") |
119 | |
120 | sharedLightXMLSchema:register(XMLValueType.STRING, "light.rotationNode(?)#name", "Name for reference in vehicle xml") |
121 | sharedLightXMLSchema:register(XMLValueType.NODE_INDEX, "light.rotationNode(?)#node", "Node") |
122 | |
123 | Lights.sharedLightXMLSchema = sharedLightXMLSchema |
124 | |
125 | local beaconLightXMLSchema = XMLSchema.new("beaconLight") |
126 | |
127 | beaconLightXMLSchema:register(XMLValueType.STRING, "beaconLight.filename", "Path to i3d file", nil, true) |
128 | beaconLightXMLSchema:register(XMLValueType.NODE_INDEX, "beaconLight.rootNode#node", "Root node") |
129 | beaconLightXMLSchema:register(XMLValueType.NODE_INDEX, "beaconLight.rotator#node", "Node that is rotating") |
130 | beaconLightXMLSchema:register(XMLValueType.FLOAT, "beaconLight.rotator#speed", "Rotating speed", 0.015) |
131 | beaconLightXMLSchema:register(XMLValueType.NODE_INDEX, "beaconLight.light#node", "Visibility toggle node") |
132 | beaconLightXMLSchema:register(XMLValueType.NODE_INDEX, "beaconLight.light#shaderNode", "Light control shader node") |
133 | beaconLightXMLSchema:register(XMLValueType.FLOAT, "beaconLight.light#intensity", "Light intensity of shader node", 1000) |
134 | beaconLightXMLSchema:register(XMLValueType.BOOL, "beaconLight.light#multiBlink", "Uses multiblink functionality", false) |
135 | beaconLightXMLSchema:register(XMLValueType.NODE_INDEX, "beaconLight.realLight#node", "Real light source node") |
136 | |
137 | BeaconLightManager.registerXMLPaths(beaconLightXMLSchema, "beaconLight.device") |
138 | |
139 | Lights.beaconLightXMLSchema = beaconLightXMLSchema |
140 | end |
1678 | function Lights:loadBeaconLightFromXML(xmlFile, key) |
1679 | local spec = self.spec_lights |
1680 | |
1681 | local beaconLight = {} |
1682 | beaconLight.node = xmlFile:getValue(key.."#node", nil, self.components, self.i3dMappings) |
1683 | if beaconLight.node ~= nil then |
1684 | local lightXmlFilename = xmlFile:getValue(key.."#filename") |
1685 | beaconLight.speed = xmlFile:getValue(key.."#speed") |
1686 | beaconLight.realLightRange = xmlFile:getValue(key.."#realLightRange", 1) |
1687 | beaconLight.intensity = xmlFile:getValue(key.."#intensity") |
1688 | if lightXmlFilename ~= nil then |
1689 | lightXmlFilename = Utils.getFilename(lightXmlFilename, self.baseDirectory) |
1690 | |
1691 | local beaconLightXMLFile = XMLFile.load("beaconLightXML", lightXmlFilename, Lights.beaconLightXMLSchema) |
1692 | if beaconLightXMLFile ~= nil then |
1693 | spec.xmlLoadingHandles[beaconLightXMLFile] = true |
1694 | |
1695 | beaconLight.xmlFile = beaconLightXMLFile |
1696 | local i3dFilename = beaconLightXMLFile:getValue("beaconLight.filename") |
1697 | if i3dFilename ~= nil then |
1698 | beaconLight.filename = Utils.getFilename(i3dFilename, self.baseDirectory) |
1699 | local sharedLoadRequestId = self:loadSubSharedI3DFile(beaconLight.filename, false, false, self.onBeaconLightI3DLoaded, self, beaconLight) |
1700 | table.insert(spec.sharedLoadRequestIds, sharedLoadRequestId) |
1701 | end |
1702 | end |
1703 | else |
1704 | beaconLight.lightShaderNode = beaconLight.node |
1705 | beaconLight.realLightNode = xmlFile:getValue(key..".realLight#node", nil, self.components, self.i3dMappings) |
1706 | beaconLight.rotatorNode = xmlFile:getValue(key..".rotator#node", nil, self.components, self.i3dMappings) |
1707 | |
1708 | beaconLight.multiBlink = xmlFile:getValue(key .. "#multiBlink", false) |
1709 | |
1710 | beaconLight.device = BeaconLightManager.loadDeviceFromXML(xmlFile, key .. ".device") |
1711 | |
1712 | if beaconLight.realLightNode ~= nil then |
1713 | beaconLight.defaultColor = {getLightColor(beaconLight.realLightNode)} |
1714 | setVisibility(beaconLight.realLightNode, false) |
1715 | |
1716 | beaconLight.defaultLightRange = getLightRange(beaconLight.realLightNode) |
1717 | setLightRange(beaconLight.realLightNode, beaconLight.defaultLightRange * beaconLight.realLightRange) |
1718 | end |
1719 | |
1720 | table.insert(spec.beaconLights, beaconLight) |
1721 | end |
1722 | end |
1723 | end |
1545 | function Lights:loadRealLights(xmlFile, key, globalTargetTable, specificTargetTable) |
1546 | xmlFile:iterate(key, function (_, realLightKey) |
1547 | local node = xmlFile:getValue(realLightKey .. "#node", nil, self.components, self.i3dMappings) |
1548 | if node ~= nil then |
1549 | if getHasClassId(node, ClassIds.LIGHT_SOURCE) then |
1550 | local realLight = {} |
1551 | realLight.node = node |
1552 | realLight.toggleVisibility = true |
1553 | |
1554 | local newRealLight = true |
1555 | for i=1, #globalTargetTable do |
1556 | local globalRealLight = globalTargetTable[i] |
1557 | if globalRealLight.node == realLight.node then |
1558 | realLight = globalRealLight |
1559 | newRealLight = false |
1560 | end |
1561 | end |
1562 | |
1563 | I3DUtil.interateRecursively(node, function(childNode) |
1564 | if not getVisibility(childNode) then |
1565 | Logging.xmlWarning(xmlFile, "Real light source '%s' is hidden in '%s'!", getName(childNode), realLightKey) |
1566 | end |
1567 | end) |
1568 | |
1569 | setVisibility(node, false) |
1570 | realLight.defaultColor = realLight.defaultColor or {getLightColor(node)} |
1571 | |
1572 | local excludedLightTypes = xmlFile:getValue(realLightKey.."#excludedLightTypes", nil, true) |
1573 | if realLight.excludedLightTypes == nil then |
1574 | realLight.excludedLightTypes = excludedLightTypes |
1575 | else |
1576 | for j=1, #excludedLightTypes do |
1577 | table.insert(realLight.excludedLightTypes, excludedLightTypes[j]) |
1578 | end |
1579 | end |
1580 | |
1581 | local lightTypes = xmlFile:getValue(realLightKey .. "#lightTypes", nil, true) |
1582 | if realLight.lightTypes == nil then |
1583 | realLight.lightTypes = lightTypes |
1584 | else |
1585 | for j=1, #lightTypes do |
1586 | table.insert(realLight.lightTypes, lightTypes[j]) |
1587 | end |
1588 | end |
1589 | |
1590 | self:loadAdditionalLightAttributesFromXML(xmlFile, realLightKey, realLight) |
1591 | |
1592 | if newRealLight then |
1593 | table.insert(globalTargetTable, realLight) |
1594 | end |
1595 | |
1596 | table.insert(specificTargetTable, realLight) |
1597 | else |
1598 | Logging.xmlWarning(xmlFile, "Node '%s' is not a real light source in '%s'", getName(node), key) |
1599 | end |
1600 | else |
1601 | Logging.xmlWarning(xmlFile, "RealLight node missing for light '%s'", key) |
1602 | end |
1603 | end) |
1604 | end |
1140 | function Lights:loadSharedLight(xmlFile, key, targetTable) |
1141 | local spec = self.spec_lights |
1142 | local xmlFilename = xmlFile:getValue(key .. "#filename") |
1143 | if xmlFilename ~= nil then |
1144 | xmlFilename = Utils.getFilename(xmlFilename, self.baseDirectory) |
1145 | local lightXMLFile = XMLFile.load("sharedLight", xmlFilename, Lights.sharedLightXMLSchema) |
1146 | |
1147 | if lightXMLFile ~= nil then |
1148 | local filename = lightXMLFile:getValue("light.filename") |
1149 | if filename == nil then |
1150 | Logging.xmlWarning(lightXMLFile, "Missing light i3d filename!") |
1151 | lightXMLFile:delete() |
1152 | return |
1153 | end |
1154 | |
1155 | local sharedLight = {} |
1156 | |
1157 | sharedLight.linkNode = xmlFile:getValue(key .. "#linkNode", "0>", self.components, self.i3dMappings) |
1158 | if sharedLight.linkNode == nil then |
1159 | Logging.xmlWarning(xmlFile, "Missing light linkNode in '%s'!", key) |
1160 | lightXMLFile:delete() |
1161 | return |
1162 | end |
1163 | sharedLight.lightTypes = xmlFile:getValue(key.."#lightTypes", nil, true) |
1164 | sharedLight.excludedLightTypes = xmlFile:getValue(key.."#excludedLightTypes", nil, true) |
1165 | |
1166 | local rotations = {} |
1167 | local i = 0 |
1168 | while true do |
1169 | local rotKey = string.format("%s.rotationNode(%d)", key, i) |
1170 | if not xmlFile:hasProperty(rotKey) then |
1171 | break |
1172 | end |
1173 | local name = xmlFile:getValue(rotKey.."#name") |
1174 | local rotation = xmlFile:getValue(rotKey.."#rotation", nil, true) |
1175 | if name ~= nil then |
1176 | rotations[name] = rotation |
1177 | end |
1178 | i = i + 1 |
1179 | end |
1180 | |
1181 | filename = Utils.getFilename(filename, self.baseDirectory) |
1182 | sharedLight.filename = filename |
1183 | |
1184 | spec.xmlLoadingHandles[lightXMLFile] = true |
1185 | |
1186 | local arguments = { |
1187 | xmlFile = xmlFile, |
1188 | key = key, |
1189 | lightXMLFile = lightXMLFile, |
1190 | sharedLight = sharedLight, |
1191 | targetTable = targetTable, |
1192 | rotations = rotations |
1193 | } |
1194 | local sharedLoadRequestId = self:loadSubSharedI3DFile(filename, false, false, self.loadSharedLightI3DLoaded, self, arguments) |
1195 | table.insert(spec.sharedLoadRequestIds, sharedLoadRequestId) |
1196 | else |
1197 | for old, new in pairs(FS22_RENAMED_LIGHTS) do |
1198 | if xmlFilename:find(old) then |
1199 | local newPath = xmlFilename:gsub(old, new) |
1200 | if fileExists(newPath) then |
1201 | Logging.xmlWarning(xmlFile, "Light '%s' has been renamed to '%s' in '%s'!", old, new, key) |
1202 | end |
1203 | end |
1204 | end |
1205 | end |
1206 | end |
1207 | end |
1275 | function Lights:loadSharedLightI3DLoaded(i3dNode, failedReason, args) |
1276 | local spec = self.spec_lights |
1277 | |
1278 | local xmlFile = args.xmlFile |
1279 | local key = args.key |
1280 | local lightXMLFile = args.lightXMLFile |
1281 | local sharedLight = args.sharedLight |
1282 | local targetTable = args.targetTable |
1283 | local rotations = args.rotations |
1284 | |
1285 | if i3dNode ~= 0 then |
1286 | sharedLight.node = lightXMLFile:getValue("light.rootNode#node", "0", i3dNode) |
1287 | |
1288 | self:loadStaticLightNodesFromSharedLight(xmlFile, key, lightXMLFile, "light.defaultLight", i3dNode, spec.staticLights, spec.defaultLightsStatic, sharedLight, true) |
1289 | self:loadStaticLightNodesFromSharedLight(xmlFile, key, lightXMLFile, "light.brakeLight", i3dNode, spec.staticLights, spec.brakeLightsStatic, sharedLight) |
1290 | self:loadStaticLightNodesFromSharedLight(xmlFile, key, lightXMLFile, "light.reverseLight", i3dNode, spec.staticLights, spec.reverseLightsStatic, sharedLight) |
1291 | self:loadStaticLightNodesFromSharedLight(xmlFile, key, lightXMLFile, "light.turnLightLeft", i3dNode, spec.staticLights, spec.turnLightsLeftStatic, sharedLight) |
1292 | self:loadStaticLightNodesFromSharedLight(xmlFile, key, lightXMLFile, "light.turnLightRight", i3dNode, spec.staticLights, spec.turnLightsRightStatic, sharedLight) |
1293 | |
1294 | lightXMLFile:iterate("light.rotationNode", function (_, baseKey) |
1295 | local name = lightXMLFile:getValue(baseKey .."#name") |
1296 | if name ~= nil then |
1297 | local node = lightXMLFile:getValue(baseKey .. "#node", nil, i3dNode) |
1298 | if rotations[name] ~= nil then |
1299 | setRotation(node, unpack(rotations[name])) |
1300 | end |
1301 | end |
1302 | end) |
1303 | |
1304 | link(sharedLight.linkNode, sharedLight.node) |
1305 | delete(i3dNode) |
1306 | |
1307 | table.insert(targetTable, sharedLight) |
1308 | end |
1309 | |
1310 | lightXMLFile:delete() |
1311 | spec.xmlLoadingHandles[lightXMLFile] = nil |
1312 | end |
1608 | function Lights:loadStaticLightNodes(xmlFile, key, globalTargetTable, specificTargetTable) |
1609 | xmlFile:iterate(key, function (_, staticLightKey) |
1610 | local node = xmlFile:getValue(staticLightKey .. "#node", nil, self.components, self.i3dMappings) |
1611 | local shaderNode = xmlFile:getValue(staticLightKey .. "#shaderNode", nil, self.components, self.i3dMappings) |
1612 | |
1613 | if node ~= nil or shaderNode ~= nil then |
1614 | local staticLight = {} |
1615 | staticLight.node = node or shaderNode |
1616 | |
1617 | local newStaticLight = true |
1618 | for i=1, #globalTargetTable do |
1619 | local globalStaticLight = globalTargetTable[i] |
1620 | if globalStaticLight.node == staticLight.node then |
1621 | staticLight = globalStaticLight |
1622 | newStaticLight = false |
1623 | end |
1624 | end |
1625 | |
1626 | if shaderNode ~= nil then |
1627 | staticLight.useShaderParameter = true |
1628 | staticLight.intensity = xmlFile:getValue(staticLightKey .. "#intensity", 25) |
1629 | |
1630 | I3DUtil.setShaderParameterRec(shaderNode, "lightControl", 0, nil, nil, nil) |
1631 | end |
1632 | |
1633 | staticLight.toggleVisibility = xmlFile:getValue(staticLightKey .. "#toggleVisibility", node ~= nil) |
1634 | if staticLight.toggleVisibility then |
1635 | setVisibility(staticLight.node, false) |
1636 | end |
1637 | |
1638 | local excludedLightTypes = xmlFile:getValue(staticLightKey.."#excludedLightTypes", nil, true) |
1639 | if staticLight.excludedLightTypes == nil then |
1640 | staticLight.excludedLightTypes = excludedLightTypes |
1641 | else |
1642 | for j=1, #excludedLightTypes do |
1643 | table.insert(staticLight.excludedLightTypes, excludedLightTypes[j]) |
1644 | end |
1645 | end |
1646 | |
1647 | local lightTypes = xmlFile:getValue(staticLightKey .. "#lightTypes", nil, true) |
1648 | if staticLight.lightTypes == nil then |
1649 | staticLight.lightTypes = lightTypes |
1650 | else |
1651 | for j=1, #lightTypes do |
1652 | table.insert(staticLight.lightTypes, lightTypes[j]) |
1653 | end |
1654 | end |
1655 | |
1656 | self:loadAdditionalLightAttributesFromXML(xmlFile, staticLightKey, staticLight) |
1657 | |
1658 | if newStaticLight then |
1659 | table.insert(globalTargetTable, staticLight) |
1660 | end |
1661 | |
1662 | table.insert(specificTargetTable, staticLight) |
1663 | end |
1664 | end) |
1665 | end |
1211 | function Lights:loadStaticLightNodesFromSharedLight(vehicleXMLFile, vehicleXMLKey, lightXMLFile, lightXMLFileKey, i3dNode, globalTargetTable, specificTargetTable, sharedLight, loadLightTypes) |
1212 | lightXMLFile:iterate(lightXMLFileKey, function (_, staticLightKey) |
1213 | local node = lightXMLFile:getValue(staticLightKey .. "#node", "0", i3dNode) |
1214 | if node ~= nil then |
1215 | if I3DUtil.getIsLinkedToNode(sharedLight.node, node) then |
1216 | if getHasShaderParameter(node, "lightControl") then |
1217 | local staticLight = {} |
1218 | staticLight.node = node |
1219 | |
1220 | local newStaticLight = true |
1221 | for i=1, #globalTargetTable do |
1222 | local globalStaticLight = globalTargetTable[i] |
1223 | if globalStaticLight.node == staticLight.node then |
1224 | staticLight = globalStaticLight |
1225 | newStaticLight = false |
1226 | end |
1227 | end |
1228 | |
1229 | staticLight.useShaderParameter = true |
1230 | staticLight.intensity = lightXMLFile:getValue(staticLightKey .. "#intensity", 25) |
1231 | I3DUtil.setShaderParameterRec(node, "lightControl", 0, nil, nil, nil) |
1232 | |
1233 | staticLight.toggleVisibility = lightXMLFile:getValue(staticLightKey .. "#toggleVisibility", false) |
1234 | if staticLight.toggleVisibility then |
1235 | setVisibility(staticLight.node, false) |
1236 | end |
1237 | |
1238 | if loadLightTypes then |
1239 | staticLight.excludedLightTypes = lightXMLFile:getValue(staticLightKey.."#excludedLightTypes", staticLight.excludedLightTypes, true) |
1240 | if sharedLight.excludedLightTypes ~= nil and #sharedLight.excludedLightTypes > 0 then |
1241 | staticLight.excludedLightTypes = table.copy(sharedLight.excludedLightTypes) |
1242 | end |
1243 | |
1244 | staticLight.lightTypes = lightXMLFile:getValue(staticLightKey .. "#lightTypes", staticLight.lightTypes, true) |
1245 | if sharedLight.lightTypes ~= nil and #sharedLight.lightTypes > 0 then |
1246 | staticLight.lightTypes = table.copy(sharedLight.lightTypes) |
1247 | end |
1248 | else |
1249 | staticLight.excludedLightTypes = staticLight.excludedLightTypes or {} |
1250 | staticLight.lightTypes = staticLight.lightTypes or {} |
1251 | end |
1252 | |
1253 | self:loadAdditionalLightAttributesFromXML(vehicleXMLFile, vehicleXMLKey, staticLight) |
1254 | |
1255 | if newStaticLight then |
1256 | table.insert(globalTargetTable, staticLight) |
1257 | end |
1258 | |
1259 | table.insert(specificTargetTable, staticLight) |
1260 | else |
1261 | Logging.xmlWarning(lightXMLFile, "Node '%s' has no shaderparameter 'lightControl'. Ignoring node!", getName(node)) |
1262 | end |
1263 | else |
1264 | Logging.xmlWarning(lightXMLFile, "Defined node '%s' is not a child of the static light root node in '%s!", getName(node), staticLightKey) |
1265 | end |
1266 | else |
1267 | Logging.xmlWarning(lightXMLFile, "Could not find node for '%s'!", staticLightKey) |
1268 | end |
1269 | end) |
1270 | end |
1727 | function Lights:onBeaconLightI3DLoaded(i3dNode, failedReason, beaconLight) |
1728 | local spec = self.spec_lights |
1729 | local xmlFile = beaconLight.xmlFile |
1730 | if i3dNode ~= 0 then |
1731 | |
1732 | local rootNode = xmlFile:getValue("beaconLight.rootNode#node", nil, i3dNode) |
1733 | local lightNode = xmlFile:getValue("beaconLight.light#node", nil, i3dNode) |
1734 | local lightShaderNode = xmlFile:getValue("beaconLight.light#shaderNode", nil, i3dNode) |
1735 | if rootNode ~= nil and (lightNode ~= nil or lightShaderNode ~= nil) then |
1736 | beaconLight.rootNode = rootNode |
1737 | beaconLight.lightNode = lightNode |
1738 | beaconLight.lightShaderNode = lightShaderNode |
1739 | beaconLight.realLightNode = xmlFile:getValue("beaconLight.realLight#node", nil, i3dNode) |
1740 | beaconLight.rotatorNode = xmlFile:getValue("beaconLight.rotator#node", nil, i3dNode) |
1741 | |
1742 | beaconLight.speed = xmlFile:getValue("beaconLight.rotator#speed", beaconLight.speed or 0.015) |
1743 | beaconLight.intensity = xmlFile:getValue("beaconLight.light#intensity", beaconLight.intensity or 1000) |
1744 | beaconLight.multiBlink = xmlFile:getValue("beaconLight.light#multiBlink", false) |
1745 | |
1746 | beaconLight.device = BeaconLightManager.loadDeviceFromXML(xmlFile, "beaconLight.device") |
1747 | |
1748 | link(beaconLight.node, rootNode) |
1749 | setTranslation(rootNode, 0, 0, 0) |
1750 | |
1751 | if beaconLight.realLightNode ~= nil then |
1752 | beaconLight.defaultColor = {getLightColor(beaconLight.realLightNode)} |
1753 | setVisibility(beaconLight.realLightNode, false) |
1754 | |
1755 | beaconLight.defaultLightRange = getLightRange(beaconLight.realLightNode) |
1756 | setLightRange(beaconLight.realLightNode, beaconLight.defaultLightRange * beaconLight.realLightRange) |
1757 | end |
1758 | |
1759 | if lightNode ~= nil then |
1760 | setVisibility(lightNode, false) |
1761 | end |
1762 | if lightShaderNode ~= nil then |
1763 | local _,y,z,w = getShaderParameter(lightShaderNode, "lightControl") |
1764 | setShaderParameter(lightShaderNode, "lightControl", 0, y, z, w, false) |
1765 | end |
1766 | |
1767 | if beaconLight.speed > 0 then |
1768 | local rot = math.random(0, math.pi * 2) |
1769 | if beaconLight.rotatorNode ~= nil then |
1770 | setRotation(beaconLight.rotatorNode, 0, rot, 0) |
1771 | end |
1772 | end |
1773 | |
1774 | table.insert(spec.beaconLights, beaconLight) |
1775 | end |
1776 | |
1777 | delete(i3dNode) |
1778 | end |
1779 | |
1780 | xmlFile:delete() |
1781 | beaconLight.xmlFile = nil |
1782 | spec.xmlLoadingHandles[xmlFile] = nil |
1783 | end |
264 | function Lights:onLoad(savegame) |
265 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.lights.low.light#decoration", "vehicle.lights.defaultLights#node") --FS17 to FS19 |
266 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.lights.high.light#decoration", "vehicle.lights.defaultLights#node") --FS17 to FS19 |
267 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.lights.low.light#realLight", "vehicle.lights.realLights.low.light#node") --FS17 to FS19 |
268 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.lights.high.light#realLight", "vehicle.lights.realLights.high.light#node") --FS17 to FS19 |
269 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.brakeLights.brakeLight#realLight", "vehicle.lights.realLights.high.brakeLight#node") --FS17 to FS19 |
270 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.brakeLights.brakeLight#decoration", "vehicle.lights.brakeLights.brakeLight#node") --FS17 to FS19 |
271 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.reverseLights.reverseLight#realLight", "vehicle.lights.realLights.high.reverseLight#node") --FS17 to FS19 |
272 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.reverseLights.reverseLight#decoration", "vehicle.lights.reverseLights.reverseLight#node") --FS17 to FS19 |
273 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnLights.turnLightLeft#realLight", "vehicle.lights.realLights.high.turnLightLeft#node") --FS17 to FS19 |
274 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnLights.turnLightLeft#decoration", "vehicle.lights.turnLights.turnLightLeft#node") --FS17 to FS19 |
275 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnLights.turnLightRight#realLight", "vehicle.lights.realLights.high.turnLightRight#node") --FS17 to FS19 |
276 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.turnLights.turnLightRight#decoration", "vehicle.lights.turnLights.turnLightRight#node") --FS17 to FS19 |
277 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.reverseLights.reverseLight#realLight", "vehicle.lights.realLights.high.reverseLight#node") --FS17 to FS19 |
278 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, "vehicle.reverseLights.reverseLight#decoration", "vehicle.lights.reverseLights.reverseLight#node") --FS17 to FS19 |
279 | |
280 | local spec = self.spec_lights |
281 | |
282 | spec.reverseLightActivationSpeed = self.xmlFile:getValue("vehicle.lights#reverseLightActivationSpeed", 1) / 3600 |
283 | |
284 | spec.sharedLoadRequestIds = {} |
285 | spec.xmlLoadingHandles = {} |
286 | |
287 | spec.shaderDefaultLights = {} |
288 | spec.shaderBrakeLights = {} |
289 | spec.shaderLeftTurnLights = {} |
290 | spec.shaderRightTurnLights = {} |
291 | spec.shaderReverseLights = {} |
292 | |
293 | spec.realLights = {} |
294 | spec.realLights.low = {} |
295 | spec.realLights.high = {} |
296 | |
297 | spec.defaultLights = {} |
298 | spec.brakeLights = {} |
299 | spec.reverseLights = {} |
300 | spec.turnLightsLeft = {} |
301 | spec.turnLightsRight = {} |
302 | |
303 | spec.lightsTypesMask = 0 |
304 | spec.currentLightState = 0 |
305 | spec.numLightTypes = 0 |
306 | spec.lightStates = {} |
307 | |
308 | local registeredLightTypes = {} |
309 | local i = 0 |
310 | while true do |
311 | local key = string.format("vehicle.lights.states.state(%d)", i) |
312 | if not self.xmlFile:hasProperty(key) then |
313 | break |
314 | end |
315 | local lightTypes = self.xmlFile:getValue(key.."#lightTypes", nil, true) |
316 | for _, lightType in pairs(lightTypes) do |
317 | if registeredLightTypes[lightType] == nil then |
318 | registeredLightTypes[lightType] = lightType |
319 | spec.numLightTypes = spec.numLightTypes + 1 |
320 | end |
321 | end |
322 | |
323 | table.insert(spec.lightStates, lightTypes) |
324 | i = i + 1 |
325 | end |
326 | |
327 | local loadLightsMaskFromXML = function(xmlFile, key, default) |
328 | local lightTypes = xmlFile:getValue(key, default, true) |
329 | local lightsTypesMask = 0 |
330 | for _, lightType in pairs(lightTypes) do |
331 | lightsTypesMask = bitOR(lightsTypesMask, 2^lightType) |
332 | end |
333 | |
334 | return lightsTypesMask |
335 | end |
336 | |
337 | spec.aiLightsTypesMask = loadLightsMaskFromXML(self.xmlFile, "vehicle.lights.states.aiState#lightTypes", "0") |
338 | spec.aiLightsTypesMaskWork = loadLightsMaskFromXML(self.xmlFile, "vehicle.lights.states.aiState#lightTypesWork", "0 1 2") |
339 | |
340 | spec.interiorLightsBrightness = 0 |
341 | spec.interiorLightsAvailable = false |
342 | |
343 | self:loadRealLightSetup(self.xmlFile, "vehicle.lights.realLights.low", spec.realLights.low) |
344 | self:loadRealLightSetup(self.xmlFile, "vehicle.lights.realLights.high", spec.realLights.high) |
345 | |
346 | spec.staticLights = {} |
347 | spec.defaultLightsStatic = {} |
348 | spec.brakeLightsStatic = {} |
349 | spec.reverseLightsStatic = {} |
350 | spec.turnLightsLeftStatic = {} |
351 | spec.turnLightsRightStatic = {} |
352 | |
353 | self:loadStaticLightNodes(self.xmlFile, "vehicle.lights.defaultLights.defaultLight", spec.staticLights, spec.defaultLightsStatic) |
354 | self:loadStaticLightNodes(self.xmlFile, "vehicle.lights.brakeLights.brakeLight", spec.staticLights, spec.brakeLightsStatic) |
355 | self:loadStaticLightNodes(self.xmlFile, "vehicle.lights.reverseLights.reverseLight", spec.staticLights, spec.reverseLightsStatic) |
356 | self:loadStaticLightNodes(self.xmlFile, "vehicle.lights.turnLights.turnLightLeft", spec.staticLights, spec.turnLightsLeftStatic) |
357 | self:loadStaticLightNodes(self.xmlFile, "vehicle.lights.turnLights.turnLightRight", spec.staticLights, spec.turnLightsRightStatic) |
358 | |
359 | spec.sharedLights = {} |
360 | self.xmlFile:iterate("vehicle.lights.sharedLight", function (_, key) |
361 | self:loadSharedLight(self.xmlFile, key, spec.sharedLights) |
362 | end) |
363 | |
364 | spec.maxLightState = Lights.LIGHT_TYPE_HIGHBEAM |
365 | for j=1, #spec.staticLights do |
366 | for _, lightType in pairs(spec.staticLights[j].lightTypes) do |
367 | spec.maxLightState = math.max(spec.maxLightState, lightType) |
368 | end |
369 | end |
370 | |
371 | for j=1, #spec.realLights.low.realLights do |
372 | for _, lightType in pairs(spec.realLights.low.realLights[j].lightTypes) do |
373 | spec.maxLightState = math.max(spec.maxLightState, lightType) |
374 | end |
375 | end |
376 | |
377 | for j=1, #spec.realLights.high.realLights do |
378 | for _, lightType in pairs(spec.realLights.high.realLights[j].lightTypes) do |
379 | spec.maxLightState = math.max(spec.maxLightState, lightType) |
380 | end |
381 | end |
382 | |
383 | spec.maxLightStateMask = 2 ^ (spec.maxLightState + 1) - 1 |
384 | |
385 | spec.additionalLightTypes = {} |
386 | spec.additionalLightTypes.brakeLight = spec.maxLightState + 1 |
387 | spec.additionalLightTypes.turnLightLeft = spec.maxLightState + 2 |
388 | spec.additionalLightTypes.turnLightRight = spec.maxLightState + 3 |
389 | spec.additionalLightTypes.turnLightAny = spec.maxLightState + 4 |
390 | spec.additionalLightTypes.reverseLight = spec.maxLightState + 5 |
391 | spec.additionalLightTypes.interiorLight = spec.maxLightState + 6 |
392 | spec.totalNumLightTypes = spec.additionalLightTypes.interiorLight |
393 | if spec.totalNumLightTypes > 31 then |
394 | Logging.xmlError(self.xmlFile, "Max. number of light types reached (31). Please reduce them.") |
395 | spec.totalNumLightTypes = 31 |
396 | end |
397 | |
398 | spec.brakeLightsVisibility = false |
399 | spec.reverseLightsVisibility = false |
400 | spec.turnLightState = Lights.TURNLIGHT_OFF |
401 | spec.turnLightTriState = 0.5 |
402 | spec.hasTurnLights = #spec.turnLightsLeft > 0 or #spec.turnLightsRight > 0 |
403 | spec.turnLightRepetitionCount = 0 |
404 | |
405 | spec.actionEventsActiveChange = {} |
406 | |
407 | spec.beaconLightsActive = false |
408 | spec.hasRealBeaconLights = g_gameSettings:getValue("realBeaconLights") |
409 | spec.beaconLights = {} |
410 | self.xmlFile:iterate("vehicle.lights.beaconLights.beaconLight", function (_, key) |
411 | self:loadBeaconLightFromXML(self.xmlFile, key) |
412 | end) |
413 | |
414 | if self.isClient ~= nil then |
415 | spec.samples = {} |
416 | spec.samples.toggleLights = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.lights.sounds", "toggleLights", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
417 | spec.samples.turnLight = g_soundManager:loadSampleFromXML(self.xmlFile, "vehicle.lights.sounds", "turnLight", self.baseDirectory, self.components, 1, AudioGroup.VEHICLE, self.i3dMappings, self) |
418 | end |
419 | |
420 | if self.loadDashboardsFromXML ~= nil then |
421 | self:loadDashboardsFromXML(self.xmlFile, "vehicle.lights.dashboards", {valueTypeToLoad = "lightState", |
422 | valueObject = spec, |
423 | valueFunc = "lightsTypesMask", |
424 | additionalAttributesFunc = Lights.dashboardLightAttributes, |
425 | stateFunc = Lights.dashboardLightState}) |
426 | |
427 | self:loadDashboardsFromXML(self.xmlFile, "vehicle.lights.dashboards", {valueTypeToLoad = "turnLightLeft", |
428 | valueObject = spec, |
429 | valueFunc = "turnLightState", |
430 | valueCompare = {Lights.TURNLIGHT_LEFT, Lights.TURNLIGHT_HAZARD}}) |
431 | |
432 | self:loadDashboardsFromXML(self.xmlFile, "vehicle.lights.dashboards", {valueTypeToLoad = "turnLightRight", |
433 | valueObject = spec, |
434 | valueFunc = "turnLightState", |
435 | valueCompare = {Lights.TURNLIGHT_RIGHT, Lights.TURNLIGHT_HAZARD}}) |
436 | |
437 | self:loadDashboardsFromXML(self.xmlFile, "vehicle.lights.dashboards", {valueTypeToLoad = "turnLight", |
438 | valueObject = spec, |
439 | idleValue = 0.5, |
440 | valueFunc = "turnLightTriState"}) |
441 | |
442 | self:loadDashboardsFromXML(self.xmlFile, "vehicle.lights.dashboards", {valueTypeToLoad = "turnLightHazard", |
443 | valueObject = spec, |
444 | valueFunc = "turnLightState", |
445 | valueCompare = {Lights.TURNLIGHT_HAZARD}}) |
446 | |
447 | self:loadDashboardsFromXML(self.xmlFile, "vehicle.lights.dashboards", {valueTypeToLoad = "turnLightAny", |
448 | valueObject = spec, |
449 | valueFunc = "turnLightState", |
450 | valueCompare = {Lights.TURNLIGHT_LEFT, Lights.TURNLIGHT_RIGHT, Lights.TURNLIGHT_HAZARD}}) |
451 | |
452 | self:loadDashboardsFromXML(self.xmlFile, "vehicle.lights.dashboards", {valueTypeToLoad = "beaconLight", |
453 | valueObject = spec, |
454 | valueFunc = function(_spec) return _spec.beaconLightsActive and 1 or 0 end}) |
455 | end |
456 | |
457 | if g_currentMission ~= nil and g_currentMission.environment ~= nil then |
458 | g_messageCenter:subscribe(MessageType.WEATHER_CHANGED, self.lightsWeatherChanged, self) |
459 | end |
460 | end |
1355 | function Lights:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection) |
1356 | if self.isClient then |
1357 | if self.getIsEntered ~= nil and self:getIsEntered() then |
1358 | local spec = self.spec_lights |
1359 | self:clearActionEventsTable(spec.actionEvents) |
1360 | |
1361 | if isActiveForInputIgnoreSelection then |
1362 | local _ |
1363 | _, spec.actionEventIdLight = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_LIGHTS, self, Lights.actionEventToggleLights, false, true, false, true, nil) |
1364 | local _, actionEventIdReverse = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_LIGHTS_BACK, self, Lights.actionEventToggleLightsBack, false, true, false, true, nil) |
1365 | local _, actionEventIdFront = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_LIGHT_FRONT, self, Lights.actionEventToggleLightFront, false, true, false, true, nil) |
1366 | local _, actionEventIdWorkBack = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_WORK_LIGHT_BACK, self, Lights.actionEventToggleWorkLightBack, false, true, false, true, nil) |
1367 | local _, actionEventIdWorkFront = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_WORK_LIGHT_FRONT, self, Lights.actionEventToggleWorkLightFront, false, true, false, true, nil) |
1368 | local _, actionEventIdHighBeam = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_HIGH_BEAM_LIGHT, self, Lights.actionEventToggleHighBeamLight, false, true, false, true, nil) |
1369 | self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_TURNLIGHT_HAZARD, self, Lights.actionEventToggleTurnLightHazard, false, true, false, true, nil) |
1370 | self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_TURNLIGHT_LEFT, self, Lights.actionEventToggleTurnLightLeft, false, true, false, true, nil) |
1371 | self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_TURNLIGHT_RIGHT, self, Lights.actionEventToggleTurnLightRight, false, true, false, true, nil) |
1372 | local _, actionEventIdBeacon = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_BEACON_LIGHTS, self, Lights.actionEventToggleBeaconLights, false, true, false, true, nil) |
1373 | |
1374 | -- action events that are only active if getIsActiveForLights |
1375 | spec.actionEventsActiveChange = {actionEventIdFront, actionEventIdWorkBack, actionEventIdWorkFront, actionEventIdHighBeam, actionEventIdBeacon} |
1376 | |
1377 | for _,actionEvent in pairs(spec.actionEvents) do |
1378 | if actionEvent.actionEventId ~= nil then |
1379 | g_inputBinding:setActionEventTextVisibility(actionEvent.actionEventId, false) |
1380 | g_inputBinding:setActionEventTextPriority(actionEvent.actionEventId, GS_PRIO_LOW) |
1381 | end |
1382 | end |
1383 | |
1384 | g_inputBinding:setActionEventTextVisibility(spec.actionEventIdLight, not g_currentMission.environment.isSunOn) |
1385 | g_inputBinding:setActionEventTextVisibility(actionEventIdReverse, false) |
1386 | end |
1387 | end |
1388 | end |
1389 | end |
544 | function Lights:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
545 | if self.isClient then |
546 | local spec = self.spec_lights |
547 | if spec.beaconLightsActive then |
548 | for _, beaconLight in pairs(spec.beaconLights) do |
549 | if beaconLight.rotatorNode ~= nil then |
550 | rotate(beaconLight.rotatorNode, 0, beaconLight.speed*dt, 0) |
551 | end |
552 | |
553 | if beaconLight.realLightNode ~= nil then |
554 | if spec.hasRealBeaconLights and beaconLight.multiBlink then |
555 | local x, y, z, _ = getShaderParameter(beaconLight.lightShaderNode or spec.beaconLights[1].lightShaderNode, "blinkOffset") |
556 | local cTime_s = getShaderTimeSec() |
557 | local alpha = MathUtil.clamp((math.sin(cTime_s * z) - math.max(((cTime_s * z) % (((x * 2) + y * 2) * math.pi)) - (x*2-1)*math.pi, 0)) + 0.2, 0, 1) |
558 | |
559 | local r, g, b = beaconLight.defaultColor[1], beaconLight.defaultColor[2], beaconLight.defaultColor[3] |
560 | setLightColor(beaconLight.realLightNode, r * alpha, g * alpha, b * alpha) |
561 | for i=0, getNumOfChildren(beaconLight.realLightNode) - 1 do |
562 | setLightColor(getChildAt(beaconLight.realLightNode, i), r * alpha, g * alpha, b * alpha) |
563 | end |
564 | end |
565 | end |
566 | end |
567 | |
568 | self:raiseActive() |
569 | end |
570 | |
571 | if spec.turnLightState ~= Lights.TURNLIGHT_OFF then |
572 | local shaderTime = 7 * getShaderTimeSec() |
573 | local alpha = MathUtil.clamp((math.cos(shaderTime) + 0.2), 0, 1) |
574 | |
575 | if spec.turnLightState == Lights.TURNLIGHT_LEFT or spec.turnLightState == Lights.TURNLIGHT_HAZARD then |
576 | for _, light in pairs(spec.activeTurnLightSetup.turnLightsLeft) do |
577 | setLightColor(light.node, light.defaultColor[1]*alpha, light.defaultColor[2]*alpha, light.defaultColor[3]*alpha) |
578 | for i=0, getNumOfChildren(light.node)-1 do |
579 | setLightColor(getChildAt(light.node, i), light.defaultColor[1]*alpha, light.defaultColor[2]*alpha, light.defaultColor[3]*alpha) |
580 | end |
581 | end |
582 | end |
583 | if spec.turnLightState == Lights.TURNLIGHT_RIGHT or spec.turnLightState == Lights.TURNLIGHT_HAZARD then |
584 | for _, light in pairs(spec.activeTurnLightSetup.turnLightsRight) do |
585 | setLightColor(light.node, light.defaultColor[1]*alpha, light.defaultColor[2]*alpha, light.defaultColor[3]*alpha) |
586 | for i=0, getNumOfChildren(light.node)-1 do |
587 | setLightColor(getChildAt(light.node, i), light.defaultColor[1]*alpha, light.defaultColor[2]*alpha, light.defaultColor[3]*alpha) |
588 | end |
589 | end |
590 | end |
591 | |
592 | if spec.samples.turnLight ~= nil then |
593 | if isActiveForInputIgnoreSelection then |
594 | local turnLightRepetitionCount = math.floor((shaderTime + math.acos(-0.2)) / (math.pi*2)) |
595 | if spec.turnLightRepetitionCount ~= nil and turnLightRepetitionCount ~= spec.turnLightRepetitionCount then |
596 | g_soundManager:playSample(spec.samples.turnLight) |
597 | end |
598 | spec.turnLightRepetitionCount = turnLightRepetitionCount |
599 | end |
600 | end |
601 | |
602 | self:raiseActive() |
603 | end |
604 | end |
605 | end |
194 | function Lights.registerFunctions(vehicleType) |
195 | SpecializationUtil.registerFunction(vehicleType, "loadRealLightSetup", Lights.loadRealLightSetup) |
196 | SpecializationUtil.registerFunction(vehicleType, "loadRealLights", Lights.loadRealLights) |
197 | SpecializationUtil.registerFunction(vehicleType, "loadStaticLightNodes", Lights.loadStaticLightNodes) |
198 | SpecializationUtil.registerFunction(vehicleType, "applyAdditionalActiveLightType", Lights.applyAdditionalActiveLightType) |
199 | SpecializationUtil.registerFunction(vehicleType, "loadBeaconLightFromXML", Lights.loadBeaconLightFromXML) |
200 | SpecializationUtil.registerFunction(vehicleType, "onBeaconLightI3DLoaded", Lights.onBeaconLightI3DLoaded) |
201 | SpecializationUtil.registerFunction(vehicleType, "getIsActiveForLights", Lights.getIsActiveForLights) |
202 | SpecializationUtil.registerFunction(vehicleType, "getIsActiveForInteriorLights", Lights.getIsActiveForInteriorLights) |
203 | SpecializationUtil.registerFunction(vehicleType, "getCanToggleLight", Lights.getCanToggleLight) |
204 | SpecializationUtil.registerFunction(vehicleType, "getUseHighProfile", Lights.getUseHighProfile) |
205 | SpecializationUtil.registerFunction(vehicleType, "setNextLightsState", Lights.setNextLightsState) |
206 | SpecializationUtil.registerFunction(vehicleType, "setLightsTypesMask", Lights.setLightsTypesMask) |
207 | SpecializationUtil.registerFunction(vehicleType, "getLightsTypesMask", Lights.getLightsTypesMask) |
208 | SpecializationUtil.registerFunction(vehicleType, "setTurnLightState", Lights.setTurnLightState) |
209 | SpecializationUtil.registerFunction(vehicleType, "getTurnLightState", Lights.getTurnLightState) |
210 | SpecializationUtil.registerFunction(vehicleType, "setBrakeLightsVisibility", Lights.setBrakeLightsVisibility) |
211 | SpecializationUtil.registerFunction(vehicleType, "setBeaconLightsVisibility", Lights.setBeaconLightsVisibility) |
212 | SpecializationUtil.registerFunction(vehicleType, "getBeaconLightsVisibility", Lights.getBeaconLightsVisibility) |
213 | SpecializationUtil.registerFunction(vehicleType, "setReverseLightsVisibility", Lights.setReverseLightsVisibility) |
214 | SpecializationUtil.registerFunction(vehicleType, "setInteriorLightsVisibility", Lights.setInteriorLightsVisibility) |
215 | SpecializationUtil.registerFunction(vehicleType, "getInteriorLightBrightness", Lights.getInteriorLightBrightness) |
216 | SpecializationUtil.registerFunction(vehicleType, "setLightsState", Lights.setLightsState) |
217 | SpecializationUtil.registerFunction(vehicleType, "setLightState", Lights.setLightState) |
218 | SpecializationUtil.registerFunction(vehicleType, "setRealLightState", Lights.setRealLightState) |
219 | SpecializationUtil.registerFunction(vehicleType, "setStaticLightState", Lights.setStaticLightState) |
220 | SpecializationUtil.registerFunction(vehicleType, "deactivateLights", Lights.deactivateLights) |
221 | SpecializationUtil.registerFunction(vehicleType, "getDeactivateLightsOnLeave", Lights.getDeactivateLightsOnLeave) |
222 | SpecializationUtil.registerFunction(vehicleType, "loadSharedLight", Lights.loadSharedLight) |
223 | SpecializationUtil.registerFunction(vehicleType, "loadStaticLightNodesFromSharedLight", Lights.loadStaticLightNodesFromSharedLight) |
224 | SpecializationUtil.registerFunction(vehicleType, "loadSharedLightI3DLoaded", Lights.loadSharedLightI3DLoaded) |
225 | SpecializationUtil.registerFunction(vehicleType, "loadAdditionalLightAttributesFromXML", Lights.loadAdditionalLightAttributesFromXML) |
226 | SpecializationUtil.registerFunction(vehicleType, "getIsLightActive", Lights.getIsLightActive) |
227 | SpecializationUtil.registerFunction(vehicleType, "updateAILights", Lights.updateAILights) |
228 | SpecializationUtil.registerFunction(vehicleType, "lightsWeatherChanged", Lights.lightsWeatherChanged) |
229 | SpecializationUtil.registerFunction(vehicleType, "deactivateBeaconLights", Lights.deactivateBeaconLights) |
230 | end |
729 | function Lights:setLightsTypesMask(lightsTypesMask, force, noEventSend) |
730 | local spec = self.spec_lights |
731 | |
732 | -- as server we apply the bits for the additional light types, client already receives the mask including these bits |
733 | if self.isServer then |
734 | lightsTypesMask = bitAND(lightsTypesMask, spec.maxLightStateMask) |
735 | if spec.turnLightState == Lights.TURNLIGHT_LEFT then |
736 | lightsTypesMask = bitOR(lightsTypesMask, 2 ^ spec.additionalLightTypes.turnLightLeft) |
737 | end |
738 | if spec.turnLightState == Lights.TURNLIGHT_RIGHT then |
739 | lightsTypesMask = bitOR(lightsTypesMask, 2 ^ spec.additionalLightTypes.turnLightRight) |
740 | end |
741 | if spec.turnLightState == Lights.TURNLIGHT_HAZARD then |
742 | lightsTypesMask = bitOR(lightsTypesMask, 2 ^ spec.additionalLightTypes.turnLightAny) |
743 | end |
744 | if spec.brakeLightsVisibility then |
745 | lightsTypesMask = bitOR(lightsTypesMask, 2 ^ spec.additionalLightTypes.brakeLight) |
746 | end |
747 | if spec.reverseLightsVisibility then |
748 | lightsTypesMask = bitOR(lightsTypesMask, 2 ^ spec.additionalLightTypes.reverseLight) |
749 | end |
750 | if spec.interiorLightsVisibility then |
751 | lightsTypesMask = bitOR(lightsTypesMask, 2 ^ spec.additionalLightTypes.interiorLight) |
752 | end |
753 | else |
754 | -- interior light bit is fully controlled by client side since we only need the time to calculate it |
755 | lightsTypesMask = bitXOR(lightsTypesMask, 2 ^ spec.additionalLightTypes.interiorLight) |
756 | |
757 | if spec.interiorLightsVisibility then |
758 | lightsTypesMask = bitOR(lightsTypesMask, 2 ^ spec.additionalLightTypes.interiorLight) |
759 | end |
760 | end |
761 | |
762 | if lightsTypesMask ~= spec.lightsTypesMask or force then |
763 | if noEventSend == nil or noEventSend == false then |
764 | if g_server ~= nil then |
765 | g_server:broadcastEvent(VehicleSetLightEvent.new(self, lightsTypesMask, spec.totalNumLightTypes), nil, nil, self) |
766 | else |
767 | g_client:getServerConnection():sendEvent(VehicleSetLightEvent.new(self, lightsTypesMask, spec.totalNumLightTypes)) |
768 | end |
769 | end |
770 | |
771 | -- only check for manual switched light states |
772 | if bitAND(lightsTypesMask, spec.maxLightStateMask) ~= bitAND(spec.lightsTypesMask, spec.maxLightStateMask) then |
773 | if self.isClient then |
774 | g_soundManager:playSample(spec.samples.toggleLights) |
775 | end |
776 | end |
777 | |
778 | local activeLightSetup = spec.realLights.low |
779 | local inactiveLightSetup = spec.realLights.high |
780 | if self:getUseHighProfile() then |
781 | activeLightSetup = spec.realLights.high |
782 | inactiveLightSetup = spec.realLights.low |
783 | end |
784 | |
785 | self:setLightsState(inactiveLightSetup.realLights, false) |
786 | self:setLightsState(activeLightSetup.realLights, lightsTypesMask) |
787 | |
788 | self:setLightsState(spec.staticLights, lightsTypesMask) |
789 | |
790 | spec.lightsTypesMask = lightsTypesMask |
791 | |
792 | SpecializationUtil.raiseEvent(self, "onLightsTypesMaskChanged", lightsTypesMask) |
793 | end |
794 | |
795 | return true |
796 | end |