79 | function Lights.loadLightSetup(self, xmlFile, key, lights, realLightToLight) |
80 | local i = 0; |
81 | local numLightTypes = 0; |
82 | while true do |
83 | local lightKey = string.format(key..".light(%d)", i); |
84 | if not hasXMLProperty(xmlFile, lightKey) then |
85 | break; |
86 | end; |
87 | |
88 | local light = Lights.loadLights(self, xmlFile, lightKey) |
89 | local enableDirection = getXMLInt(xmlFile, lightKey .. "#enableDirection"); |
90 | local lightTypes = {Utils.getVectorFromString(getXMLString(xmlFile, lightKey .. "#lightTypes"))}; |
91 | local excludedLightTypes = {Utils.getVectorFromString(getXMLString(xmlFile, lightKey.."#excludedLightTypes"))}; |
92 | if #lightTypes >= 0 then |
93 | if light.realLight ~= nil or light.decoration ~= nil then |
94 | if light.realLight ~= nil then |
95 | realLightToLight[light.realLight] = light; |
96 | end |
97 | |
98 | for i=#lightTypes, 1, -1 do |
99 | local lightType = lightTypes[i] |
100 | if lightType >= 0 and lightType <= 30 then |
101 | numLightTypes = math.max(numLightTypes, lightType+1); |
102 | else |
103 | table.remove(lightTypes, i); |
104 | print("Warning: lightType must be between 0 and 30 for light '" ..lightKey.."' in '"..self.configFileName.."'"); |
105 | end |
106 | end |
107 | |
108 | light.excludedLightTypes = excludedLightTypes; |
109 | light.enableDirection = enableDirection; |
110 | light.lightTypes = lightTypes; |
111 | |
112 | table.insert(lights, light); |
113 | else |
114 | print("Warning: decoration or/and realLight missing for light '" ..lightKey.."' in '"..self.configFileName.."'") |
115 | end |
116 | else |
117 | print("Warning: lightType missing for light '" ..lightKey.."' in '"..self.configFileName.."'"); |
118 | end; |
119 | i = i + 1; |
120 | end; |
121 | |
122 | return numLightTypes; |
123 | end |
128 | function Lights:load(savegame) |
129 | if hasXMLProperty(self.xmlFile, "vehicle.lights.light1") then |
130 | print("Warning: lights.light in '".. self.configFileName .."' is not supported anymore. Use lights.light#realLight instead."); |
131 | end |
132 | if hasXMLProperty(self.xmlFile, "vehicle.lightCoronas.lightCorona") then |
133 | print("Warning: lightCoronas.lightCorona in '".. self.configFileName .."' is not supported anymore. Use lights.light#decoration instead."); |
134 | end |
135 | if hasXMLProperty(self.xmlFile, "vehicle.lightCones.lightCone") then |
136 | print("Warning: lightCones.lightCone in '".. self.configFileName .."' is not supported anymore."); |
137 | end |
138 | if getXMLString(self.xmlFile, "vehicle.brakeLights.brakeLight(0)#index") ~= nil then |
139 | print("Warning: brakeLights.brakeLight#index in '".. self.configFileName .."' is not supported anymore. Use brakeLights.brakeLight#realLight and brakeLights.brakeLight#decoration instead."); |
140 | end |
141 | if getXMLString(self.xmlFile, "vehicle.reverseLights.reverseLight(0)#index") ~= nil then |
142 | print("Warning: reverseLights.reverseLight#index in '".. self.configFileName .."' is not supported anymore. Use reverseLights.reverseLight#realLight and reverseLights.reverseLight#decoration instead."); |
143 | end |
144 | if getXMLString(self.xmlFile, "vehicle.turnSignals.turnSignalLeft(0)#index") ~= nil then |
145 | print("Warning: turnSignals.turnSignalLeft#index in '".. self.configFileName .."' is not supported anymore. Use turnLights.turnLightLeft#realLight and turnLights.turnLightLeft#decoration instead."); |
146 | end |
147 | if getXMLString(self.xmlFile, "vehicle.turnSignals.turnSignalRight(0)#index") ~= nil then |
148 | print("Warning: turnSignals.turnSignalRight#index in '".. self.configFileName .."' is not supported anymore. Use turnLights.turnLightRight#realLight and turnLights.turnLightRight#decoration instead."); |
149 | end |
150 | |
151 | self.maxNumRealLights = g_maxNumRealVehicleLights; |
152 | |
153 | self.lights = {}; |
154 | self.lights.low = {}; |
155 | self.lights.high = {} |
156 | self.numLightTypes = 0; |
157 | |
158 | local realLightToLight = {}; |
159 | |
160 | local numLowLightTypes = Lights.loadLightSetup(self, self.xmlFile, "vehicle.lights.low", self.lights.low, realLightToLight); |
161 | local numHighLightTypes = Lights.loadLightSetup(self, self.xmlFile, "vehicle.lights.high", self.lights.high, realLightToLight); |
162 | if numLowLightTypes == numHighLightTypes then |
163 | self.numLightTypes = numHighLightTypes; |
164 | else |
165 | print("Warning: Low- and high-profile light setups are different. Both light setups must have equal number of lightTypes.") |
166 | end |
167 | |
168 | self.lightStates = {}; |
169 | local i = 0; |
170 | while true do |
171 | local key = string.format("vehicle.lights.states.state(%d)", i); |
172 | if not hasXMLProperty(self.xmlFile, key) then |
173 | break; |
174 | end; |
175 | local lightTypes = {Utils.getVectorFromString(getXMLString(self.xmlFile, key.."#lightTypes"))}; |
176 | table.insert(self.lightStates, lightTypes); |
177 | i = i + 1; |
178 | end |
179 | |
180 | self.brakeLights = {}; |
181 | local i = 0; |
182 | while true do |
183 | local key = string.format("vehicle.brakeLights.brakeLight(%d)", i); |
184 | if not hasXMLProperty(self.xmlFile, key) then |
185 | break; |
186 | end; |
187 | local light = Lights.loadLights(self, self.xmlFile, key) |
188 | if light.realLight ~= nil or light.decoration ~= nil then |
189 | if light.realLight ~= nil and realLightToLight[light.realLight] ~= nil then |
190 | light.backLight = realLightToLight[light.realLight]; |
191 | realLightToLight[light.realLight].brakeLight = light; |
192 | end |
193 | |
194 | table.insert(self.brakeLights, light); |
195 | end; |
196 | i = i + 1; |
197 | end; |
198 | self.brakeLightsVisibility = false; |
199 | |
200 | self.reverseLights = {}; |
201 | local i = 0; |
202 | while true do |
203 | local key = string.format("vehicle.reverseLights.reverseLight(%d)", i); |
204 | if not hasXMLProperty(self.xmlFile, key) then |
205 | break; |
206 | end; |
207 | local light = Lights.loadLights(self, self.xmlFile, key) |
208 | if light.realLight ~= nil or light.decoration ~= nil then |
209 | table.insert(self.reverseLights, light); |
210 | end; |
211 | i = i + 1; |
212 | end; |
213 | self.reverseLightsVisibility = false; |
214 | |
215 | self.turnLights = {}; |
216 | self.turnLights.left = {}; |
217 | self.turnLights.right = {}; |
218 | local i = 0; |
219 | while true do |
220 | local keyLeft = string.format("vehicle.turnLights.turnLightLeft(%d)", i); |
221 | local keyRight = string.format("vehicle.turnLights.turnLightRight(%d)", i); |
222 | if not hasXMLProperty(self.xmlFile, keyLeft) and not hasXMLProperty(self.xmlFile, keyRight) then |
223 | break; |
224 | end; |
225 | |
226 | if hasXMLProperty(self.xmlFile, keyLeft) then |
227 | local light = Lights.loadLights(self, self.xmlFile, keyLeft) |
228 | if light.realLight ~= nil or light.decoration ~= nil then |
229 | if light.realLight ~= nil then |
230 | light.defaultColor = {getLightColor(light.realLight)}; |
231 | end |
232 | table.insert(self.turnLights.left, light); |
233 | end; |
234 | end; |
235 | |
236 | if hasXMLProperty(self.xmlFile, keyRight) then |
237 | local light = Lights.loadLights(self, self.xmlFile, keyRight) |
238 | if light.realLight ~= nil or light.decoration ~= nil then |
239 | if light.realLight ~= nil then |
240 | light.defaultColor = {getLightColor(light.realLight)}; |
241 | end |
242 | table.insert(self.turnLights.right, light); |
243 | end; |
244 | end; |
245 | i = i + 1; |
246 | end; |
247 | self.turnLightState = Lights.TURNLIGHT_OFF; |
248 | self.hasTurnLights = #self.turnLights.left > 0 or #self.turnLights.right > 0 |
249 | |
250 | local realBeaconLights = g_gameSettings:getValue("realBeaconLights") |
251 | |
252 | self.beaconLights = {}; |
253 | local i = 0; |
254 | while true do |
255 | local key = string.format("vehicle.beaconLights.beaconLight(%d)", i); |
256 | if not hasXMLProperty(self.xmlFile, key) then |
257 | break; |
258 | end; |
259 | local light = Lights.loadLights(self, self.xmlFile, key); |
260 | local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#index")); |
261 | light.rotationNode = Utils.indexToObject(self.components, getXMLString(self.xmlFile, key.."#rotationNode")); |
262 | local filename = getXMLString(self.xmlFile, key.."#filename"); |
263 | if filename ~= nil then |
264 | local i3dNode = Utils.loadSharedI3DFile(filename, self.baseDirectory, false, false, false); |
265 | if i3dNode ~= 0 then |
266 | light.filename = filename; |
267 | local rootNode = getChildAt(i3dNode, 0); |
268 | link(node, rootNode); |
269 | delete(i3dNode); |
270 | setTranslation(rootNode, 0,0,0); |
271 | |
272 | local rotationIndex = getUserAttribute(rootNode, "rotation"); |
273 | if rotationIndex ~= nil then |
274 | light.rotationNode = Utils.indexToObject(rootNode, rotationIndex); |
275 | end; |
276 | local decorationIndex = getUserAttribute(rootNode, "decoration"); |
277 | if decorationIndex ~= nil then |
278 | light.decoration = Utils.indexToObject(rootNode, decorationIndex); |
279 | end; |
280 | local realLightIndex = getUserAttribute(rootNode, "realLight"); |
281 | if realLightIndex ~= nil then |
282 | light.realLight = Utils.indexToObject(rootNode, realLightIndex); |
283 | if light.realLight ~= nil then |
284 | if realBeaconLights then |
285 | light.defaultColor = {getLightColor(light.realLight)}; |
286 | else |
287 | setVisibility(light.realLight, false) |
288 | end |
289 | end; |
290 | end; |
291 | end |
292 | end; |
293 | |
294 | if node ~= nil then |
295 | light.speed = Utils.getNoNil(getXMLFloat(self.xmlFile, key.."#speed"), 0.02); |
296 | if light.speed > 0 then |
297 | local rot = math.random(0, math.pi*2); |
298 | if light.rotationNode ~= nil then |
299 | setRotation(light.rotationNode, 0, rot, 0); |
300 | end; |
301 | end; |
302 | if light.decoration ~= nil then |
303 | setVisibility(light.decoration, false); |
304 | end |
305 | if light.realLight ~= nil then |
306 | setVisibility(light.realLight, false); |
307 | end |
308 | table.insert(self.beaconLights, light); |
309 | end; |
310 | i = i + 1; |
311 | end; |
312 | self.beaconLightsActive = false; |
313 | |
314 | self.lightsTypesMask = 0; |
315 | end; |
361 | function Lights:update(dt) |
362 | if self.beaconLightsActive then |
363 | for _, beaconLight in pairs(self.beaconLights) do |
364 | if beaconLight.rotationNode ~= nil then |
365 | rotate(beaconLight.rotationNode, 0, beaconLight.speed*dt, 0); |
366 | end |
367 | end; |
368 | end; |
369 | |
370 | if self.turnLightState ~= Lights.TURNLIGHT_OFF then |
371 | if self:getUseHighProfile() then |
372 | local alpha = Utils.clamp((math.cos(7*getShaderTimeSec()) + 0.2), 0, 1); |
373 | if self.turnLightState == Lights.TURNLIGHT_LEFT or self.turnLightState == Lights.TURNLIGHT_HAZARD then |
374 | for _, signal in pairs(self.turnLights.left) do |
375 | if signal.realLight ~= nil then |
376 | setLightColor(signal.realLight, signal.defaultColor[1]*alpha, signal.defaultColor[2]*alpha, signal.defaultColor[3]*alpha); |
377 | for i=0, getNumOfChildren(signal.realLight)-1 do |
378 | setLightColor(getChildAt(signal.realLight, i), signal.defaultColor[1]*alpha, signal.defaultColor[2]*alpha, signal.defaultColor[3]*alpha); |
379 | end |
380 | end |
381 | end; |
382 | end |
383 | if self.turnLightState == Lights.TURNLIGHT_RIGHT or self.turnLightState == Lights.TURNLIGHT_HAZARD then |
384 | for _, signal in pairs(self.turnLights.right) do |
385 | if signal.realLight ~= nil then |
386 | setLightColor(signal.realLight, signal.defaultColor[1]*alpha, signal.defaultColor[2]*alpha, signal.defaultColor[3]*alpha); |
387 | for i=0, getNumOfChildren(signal.realLight)-1 do |
388 | setLightColor(getChildAt(signal.realLight, i), signal.defaultColor[1]*alpha, signal.defaultColor[2]*alpha, signal.defaultColor[3]*alpha); |
389 | end |
390 | end |
391 | end; |
392 | end |
393 | end |
394 | end |
395 | end; |
464 | function Lights:setLightsTypesMask(superFunc, lightsTypesMask, force, noEventSend) |
465 | if superFunc ~= nil then |
466 | if not superFunc(self, lightsTypesMask, noEventSend) then |
467 | return false; |
468 | end |
469 | end |
470 | |
471 | if lightsTypesMask ~= self.lightsTypesMask or force then |
472 | if noEventSend == nil or noEventSend == false then |
473 | if g_server ~= nil then |
474 | g_server:broadcastEvent(VehicleSetLightEvent:new(self, lightsTypesMask), nil, nil, self); |
475 | else |
476 | g_client:getServerConnection():sendEvent(VehicleSetLightEvent:new(self, lightsTypesMask)); |
477 | end; |
478 | end; |
479 | |
480 | self.lightsTypesMask = lightsTypesMask; |
481 | |
482 | local activeLightSetup = self.lights.low; |
483 | local inactiveLightSetup = self.lights.high; |
484 | |
485 | if self:getUseHighProfile() then |
486 | activeLightSetup = self.lights.high; |
487 | inactiveLightSetup = self.lights.low; |
488 | end |
489 | |
490 | for _, light in pairs(inactiveLightSetup) do |
491 | if light.decoration ~= nil then |
492 | setVisibility(light.decoration, false); |
493 | end |
494 | if light.realLight ~= nil then |
495 | setVisibility(light.realLight, false); |
496 | end |
497 | end |
498 | |
499 | for _,light in pairs(activeLightSetup) do |
500 | local lightActive = false; |
501 | for _, lightType in pairs(light.lightTypes) do |
502 | if bitAND(lightsTypesMask, 2^lightType) ~= 0 then |
503 | lightActive = true; |
504 | break; |
505 | end |
506 | end |
507 | |
508 | if light.enableDirection ~= nil then |
509 | lightActive = lightActive and light.enableDirection == self.reverserDirection; |
510 | end |
511 | if light.decoration ~= nil then |
512 | setVisibility(light.decoration, lightActive); |
513 | end |
514 | |
515 | if light.realLight ~= nil then |
516 | if lightActive then |
517 | for _, excludedLightType in pairs(light.excludedLightTypes) do |
518 | if bitAND(lightsTypesMask, 2^excludedLightType) ~= 0 then |
519 | lightActive = false; |
520 | break; |
521 | end |
522 | end |
523 | end |
524 | |
525 | if lightActive then |
526 | setVisibility(light.realLight, true) |
527 | else |
528 | local active = false; |
529 | if light.brakeLight ~= nil then |
530 | if light.brakeLight.isActive then |
531 | active = true; |
532 | end |
533 | end |
534 | setVisibility(light.realLight, active) |
535 | end |
536 | end |
537 | light.isActive = lightActive; |
538 | end |
539 | |
540 | |
541 | for _,v in pairs(self.attachedImplements) do |
542 | if v.object ~= nil then |
543 | v.object:setLightsTypesMask(lightsTypesMask, true, true); |
544 | end |
545 | end; |
546 | |
547 | self:onLightsTypesMaskChanged(lightsTypesMask); |
548 | end; |
549 | |
550 | return true; |
551 | end; |
603 | function Lights:setTurnLightState(superFunc, state, force, noEventSend) |
604 | if superFunc ~= nil then |
605 | if not superFunc(self, state, noEventSend) then |
606 | return false; |
607 | end; |
608 | end |
609 | |
610 | if state ~= self.turnLightState or force then |
611 | if noEventSend == nil or noEventSend == false then |
612 | if g_server ~= nil then |
613 | g_server:broadcastEvent(VehicleSetTurnLightEvent:new(self, state), nil, nil, self); |
614 | else |
615 | g_client:getServerConnection():sendEvent(VehicleSetTurnLightEvent:new(self, state)); |
616 | end; |
617 | end; |
618 | |
619 | local useHighProfile = self:getUseHighProfile() |
620 | for _, signal in pairs(self.turnLights.left) do |
621 | if signal.realLight ~= nil then |
622 | if useHighProfile then |
623 | setVisibility(signal.realLight, state == Lights.TURNLIGHT_LEFT or state == Lights.TURNLIGHT_HAZARD); |
624 | end |
625 | end |
626 | if signal.decoration ~= nil then |
627 | setVisibility(signal.decoration, state == Lights.TURNLIGHT_LEFT or state == Lights.TURNLIGHT_HAZARD); |
628 | end |
629 | end; |
630 | for _, signal in pairs(self.turnLights.right) do |
631 | if signal.realLight ~= nil then |
632 | if useHighProfile then |
633 | setVisibility(signal.realLight, state == Lights.TURNLIGHT_RIGHT or state == Lights.TURNLIGHT_HAZARD); |
634 | end |
635 | end |
636 | if signal.decoration ~= nil then |
637 | setVisibility(signal.decoration, state == Lights.TURNLIGHT_RIGHT or state == Lights.TURNLIGHT_HAZARD); |
638 | end |
639 | end; |
640 | |
641 | for _,v in pairs(self.attachedImplements) do |
642 | if v.object ~= nil then |
643 | v.object:setTurnLightState(state, true, true); |
644 | end |
645 | end; |
646 | |
647 | self:onTurnLightStateChanged(state); |
648 | |
649 | self.turnLightState = state; |
650 | end; |
651 | |
652 | return true; |
653 | end; |
659 | function Lights:setBrakeLightsVisibility(superFunc, visibility) |
660 | if superFunc ~= nil then |
661 | if not superFunc(self, visibility) then |
662 | return false; |
663 | end; |
664 | end |
665 | |
666 | if visibility ~= self.brakeLightsVisibility then |
667 | self.brakeLightsVisibility = visibility; |
668 | local useHighProfile = self:getUseHighProfile(); |
669 | for _, brakeLight in pairs(self.brakeLights) do |
670 | if brakeLight.realLight ~= nil then |
671 | if useHighProfile then |
672 | brakeLight.isActive = visibility; |
673 | if visibility then |
674 | if brakeLight.backLight ~= nil then |
675 | local color = brakeLight.backLight.defaultColor; |
676 | setLightColor(brakeLight.realLight, color[1]*2, color[2]*2, color[3]*2); |
677 | for i=0, getNumOfChildren(brakeLight.realLight)-1 do |
678 | setLightColor(getChildAt(brakeLight.realLight, i), color[1]*2, color[2]*2, color[3]*2); |
679 | end |
680 | end |
681 | setVisibility(brakeLight.realLight, true); |
682 | brakeLight.isActive = true; |
683 | else |
684 | local isVisible = false; |
685 | if brakeLight.backLight ~= nil then |
686 | local color = brakeLight.backLight.defaultColor; |
687 | setLightColor(brakeLight.realLight, color[1], color[2], color[3]); |
688 | for i=0, getNumOfChildren(brakeLight.realLight)-1 do |
689 | setLightColor(getChildAt(brakeLight.realLight, i), color[1], color[2], color[3]); |
690 | end |
691 | if brakeLight.backLight.isActive then |
692 | isVisible = true; |
693 | end |
694 | end |
695 | setVisibility(brakeLight.realLight, isVisible); |
696 | end; |
697 | if brakeLight.backLight ~= nil then |
698 | |
699 | end |
700 | end |
701 | end |
702 | if brakeLight.decoration ~= nil then |
703 | setVisibility(brakeLight.decoration, visibility); |
704 | end |
705 | end |
706 | for _,v in pairs(self.attachedImplements) do |
707 | if v.object ~= nil then |
708 | v.object:setBrakeLightsVisibility(visibility); |
709 | end |
710 | end |
711 | |
712 | self:onBrakeLightsVisibilityChanged(visibility); |
713 | end |
714 | |
715 | return true; |
716 | end |