Hallo zusammen,
ich stelle euch hier mal ein universelles Blaulichtscript bereit. Kurz erklärt, könnt Ihr hiermit relativ bequem in der Config_Vehicles.hpp die Position der Blaulichter festlegen. Zusätzlich könnt Ihr eine Position für ein ziviles Aufsteckblaulicht oder auch "Frontblitzer", wenn man das so nennt, hinzufügen. Die Entscheidung, welche Blaulichter zu Verfügung stehen ist an den Skin gebunden, dh. ein SUV mit Polizei-Lackierung hat normales Blaulicht und Frontblitzer, ein Kripo-SUV hat nur Frontblitzer fest eingebaut und kann durch ein Aufsteckblaulicht erweitert werden. Für jeden anderen SUV Skin kann nur das Aufsteckblaulicht montiert werden. Letzteres lässt sich für gewisse Fahrzeuge natürlich auch komplett deaktivieren, indem einfach keine Position für ein ziviles Licht definiert wird.
Interessiert? Na dann mal los!
1. Zuerst geht Ihr in euren core/functions Ordner und erstellt eine neue Datei namens fn_blaulicht.sqf
#include "..\..\script_macros.hpp"
/*
Datei: fn_blaulicht.sqf
Funktionen für Blaulicht in einer Datei
*/
private _vehicle = param [0,objNull,[objNull]];
if (isNil "_vehicle" || isNull _vehicle || {!(_vehicle getVariable "lights")} || {!(M_CONFIG(isArray,"LifeCfgVehicles",(typeOf _vehicle),"lights"))}) exitWith {};
private _lights = getArray(missionConfigFile >> "LifeCfgVehicles" >> (typeOf _vehicle) >> "lights");
if (count _lights isEqualTo 0) exitWith {_vehicle setVariable["lights",false,true];};
_lightsMain = [];
_lightsFront = [];
_lightZiviSingle = objNull;
{
_light = "#lightpoint" createVehicleLocal getPos _vehicle;
_light setLightColor [0.1,0.1,20];
_light setLightBrightness 0.0;
_light setLightAmbient [0.1,0.1,3];
_light lightAttachObject [_vehicle, (_x select 1)];
_light setLightAttenuation [0.181, 0, 1000, 130];
_light setLightIntensity 10;
_light setLightFlareSize 0.38;
_light setLightFlareMaxDistance 150;
_light setLightUseFlare true;
_light setLightDayLight true;
_lName = (_x select 0);
if (_lName find "main" != -1) then {_lightsMain pushBack _light};
if (_lName find "front" != -1) then {_lightsFront pushBack _light};
if (_lName find "ziviS" != -1) then {_lightZiviSingle = _light};
} forEach _lights;
private _bconfig = _vehicle getVariable["blaulichtkonfig",0];
if(count _lightsFront isEqualTo 2 && _bconfig > 0) then {
[_lightsFront,_vehicle] spawn {
params [
["_lightsFront", [], [[]]],
["_vehicle", objNull, [objNull]]
];
while {alive _vehicle} do {
if !(_vehicle getVariable "lights") exitWith {};
(_lightsFront select 1) setLightBrightness 20;
(_lightsFront select 0) setLightBrightness 20;
sleep 0.05;
(_lightsFront select 0) setLightBrightness 0.0;
(_lightsFront select 1) setLightBrightness 0.0;
sleep 0.2;
(_lightsFront select 1) setLightBrightness 20;
(_lightsFront select 0) setLightBrightness 20;
sleep 0.05;
(_lightsFront select 0) setLightBrightness 0.0;
(_lightsFront select 1) setLightBrightness 0.0;
sleep 0.4;
};
};
};
if(!isNull _lightZiviSingle && !isNull(_vehicle getVariable["blaulicht",objNull])) then {
[_lightZiviSingle,_vehicle] spawn {
params [
["_lightZiviSingle", objNull, [objNull]],
["_vehicle", objNull, [objNull]]
];
while {alive _vehicle} do {
if !(_vehicle getVariable "lights") exitWith {};
_lightZiviSingle setLightBrightness 20;
sleep 0.2;
_lightZiviSingle setLightBrightness 0;
sleep 0.2;
};
if(!alive _vehicle) then {deleteVehicle (_vehicle getVariable["blaulicht",objNull]);};
};
};
if(count _lightsMain isEqualTo 2 && _bconfig isEqualTo 2) then {
private _switchMain = false;
while {alive _vehicle} do {
if !(_vehicle getVariable "lights") exitWith {};
if(_switchMain) then {
(_lightsMain select 0) setLightBrightness 0.0;
sleep 0.05;
(_lightsMain select 1) setLightBrightness 20;
} else {
(_lightsMain select 1) setLightBrightness 0.0;
sleep 0.05;
(_lightsMain select 0) setLightBrightness 20;
};
_switchMain = !_switchMain;
sleep 0.22;
};
};
if(_bconfig isEqualTo 0 && isNull(_vehicle getVariable["blaulicht",objNull])) then {_vehicle setVariable["lights",false,true];};
waitUntil {sleep 0.1; if(isNull _vehicle) exitWith {true}; !(_vehicle getVariable "lights") || !(alive _vehicle)};
{deleteVehicle _x} forEach _lightsMain;
{deleteVehicle _x} forEach _lightsFront;
if(!isNull _lightZiviSingle) then {deleteVehicle _lightZiviSingle};
Alles anzeigen
2. (Optional) Erstellt eine Datei namens fn_aufsteckblaulicht.sqf unter core/items
#include "..\..\script_macros.hpp"
/*
Datei: fn_aufsteckblaulicht.sqf
Selbsterklärend?
*/
private _vehicle = cursorObject;
if (vehicle player != player) then {_vehicle = vehicle player};
if (isNil "_vehicle" || isNull _vehicle || !(_vehicle isKindof "LandVehicle") || {!(M_CONFIG(isArray,"LifeCfgVehicles",(typeOf _vehicle),"lights"))}) exitWith {};
private _lights = getArray(missionConfigFile >> "LifeCfgVehicles" >> (typeOf _vehicle) >> "lights");
if (count _lights isEqualTo 0) exitWith {hint parseText "<t color='#ff0000'>Hier kann leider kein Blaulicht angebracht werden :/ Rede am besten mit deinem Mechaniker darüber</t>";};
private _light = [];
{
if(_x select 0 isEqualTo "ziviS") exitWith {
_light = _x;
};
} forEach _lights;
if(count _light > 0) then {
if(isNull(_vehicle getVariable["blaulicht",objNull])) then {
private _bconf = _vehicle getVariable["blaulichtkonfig",0];
if(!(_bconf isEqualTo 2)) then {
if([false,"blaulicht",1] call life_fnc_handleInv) then {
private _obj = "Land_Camping_Light_off_F" createVehicle [0,0,0];
private _offset = _light select 1;
_offset set[2,(_offset select 2) - 0.06]; //etwas unterhalb des Lichts
_obj attachTo[_vehicle,_offset];
_vehicle setVariable["blaulicht",_obj,true];
hintSilent parseText "<t color='#00ff00'>Blaulicht angebracht - Das Gaspedal ist rechts, der Rest ist egal!</t>";
} else {hint parseText "<t color='#ff0000'>Du hast kein Blaulicht</t>";};
} else {
hint parseText "<t color='#ffee00'>Dies ist ein Streifenfahrzeug mit fest eingebautem Blaulicht</t>";
};
} else {
if(!(_vehicle getVariable["lights",false])) then {
if([true,"blaulicht",1] call life_fnc_handleInv) then {
deleteVehicle (_vehicle getVariable["blaulicht",objNull]);
hintSilent parseText "<t color='#00ff00'>Blaulicht demontiert</t>";
} else {hint parseText "Dein Inventar ist voll, Blaulicht kann nicht demontiert werden";};
} else {
hint parseText "<t color='#ffee00'>Schalte das Blaulicht vorher aus</t>";
};
};
} else {
hint parseText "<t color='#ff0000'>Hier kann leider kein Blaulicht angebracht werden :/ Rede am besten mit deinem Mechaniker darüber</t>";
};
Alles anzeigen
3. tragt eure Funktionen in die Functions.hpp ein
[...]
class Functions {
file = "core\functions";
[...]
class blaulicht {};
};
[...]
class Items {
file = "core\items";
[...]
class aufsteckblaulicht {};
};
Alles anzeigen
4. Die Funktion life_fnc_blaulicht muss noch in der CfgRemoteExec.hpp mit JIP eingetragen werden
class CfgRemoteExec {
class Functions {
mode = 1;
jip = 0;
/* Client only functions */
JIP(life_fnc_blaulicht, CLIENT)
[...]
};
};
5. Nun kommen wir zur fn_keyHandler.sqf Ihr müsst nun entscheiden, ob auch Zivilisten das Blaulicht einschalten können oder nicht. Wer ein Polizeifahrzeug stehlen würde, kann aufgrund des Skins nämlich auch Shift+L drücken.
//L Key?
case 38: {
//If cop run checks for turning lights on.
if(vehicle player != player && (M_CONFIG(isArray,"LifeCfgVehicles",(typeOf vehicle player),"lights"))) then {
if(_ctrlKey) then {
[] call life_fnc_aufsteckblaulicht;
_handled = true;
};
if(_shift) then {
if(_veh getVariable["blaulichtkonfig",0] isEqualTo 0) exitWith {};
if (!(vehicle player getVariable ["lights",false])) then {
vehicle player setVariable ["lights", true, true];
[vehicle player] remoteExec ["life_fnc_blaulicht",RCLIENT];
} else {
vehicle player setVariable ["lights", false, true];
};
_handled = true;
};
};
if (!_alt && !_ctrlKey && playerSide isEqualTo west) then { [] call life_fnc_radar; };
};
Alles anzeigen
//L Key?
case 38: {
//If cop run checks for turning lights on.
if(playerSide in [west, independent]) then {
if(vehicle player != player && (M_CONFIG(isArray,"LifeCfgVehicles",(typeOf vehicle player),"lights"))) then {
if(_ctrlKey) then {
[] call life_fnc_aufsteckblaulicht;
_handled = true;
};
if(_shift) then {
if(_veh getVariable["blaulichtkonfig",0] isEqualTo 0) exitWith {};
if (!(vehicle player getVariable ["lights",false])) then {
vehicle player setVariable ["lights", true, true];
[vehicle player] remoteExec ["life_fnc_blaulicht",RCLIENT];
} else {
vehicle player setVariable ["lights", false, true];
};
_handled = true;
};
};
};
if (!_alt && !_ctrlKey && playerSide isEqualTo west) then { [] call life_fnc_radar; };
};
Alles anzeigen
(OPTIONAL) wer kein Aufsteckblaulicht benutzen möchte, kann und sollte den Block mit if(_ctrlKey) then { rausnehmen um Fehler zu vermeiden
6. Um nun zu bestimmen welcher Skin welche Blaulichter angebracht hat gehen wir in die core/vehicle/fn_colorVehicle.sqf und fügen folgendes an die Datei an
private _lights = ((M_CONFIG(getArray,"LifeCfgVehicles",_className,"textures") select _index) param [3,0]);
if(_lights isEqualType 0) then {
_vehicle setVariable["blaulichtkonfig",_lights,true];
};
Achtung: Wer bereits seine Config_Vehicles.hpp bearbeitet hat sollte prüfen, ob an den textures-Blöcken etwas verändert wurde und entsprechend den param[4, 0] erhöhen (im Regelfall nicht nötig, bessere Erklärung im nächsten step)
7. Die Konfiguration erfolgt in der Config_Vehicles.hpp unter class LifeCfgVehicles
Oben habe ich eine kurze Dokumentation beigefügt. Jeder texture-Block, welcher kein Blaulicht haben soll muss nicht bearbeitet werden, da 0 der default wert ist. Wenn ein Skin volles Blaulicht haben soll, fügt Ihr nach vor der Texture Condition, welche immer leer "" sein dürfte, eine 2 ein; Frontblitzer only eine 1. Wenn es für das Fahrzeug definierte Frontblitzer gibt, werden diese auch bei 2 immer genutzt.
Zusätzlich ging es ja um die Positionierung der Lichter, hierzu wird ein lights[] array angelegt. Das Blaulichtscript prüft auf die keywords main front und ziviS und kann somit erkennen wie das Licht blinken soll. Das zivile Blaulicht kann und sollte nur einmal verwendet werden, deswegen ziviSingle
/*
[...]
* 1: STRING (Condition)
* Textures config follows { Texture Name, side, {texture(s)path}, Condition, blaulichtkonfig}
* Texture(s)path follows this format:
* INDEX 0: Texture Layer 0
* INDEX 1: Texture Layer 1
* INDEX 2: Texture Layer 2
* etc etc etc
*
* blaulichtkonfig:
* 0/leer: nix
* 1: nur frontblitzer
* 2: festes Blaulicht
*
* zu 0/1 kann zusätzlich Aufsteckblaulicht montiert werden
*
*/
//Beispielkonfiguration
class B_Quadbike_01_F {
vItemSpace = 50;
tank = 10;
conditions = "license_civ_driver || {!(playerSide isEqualTo civilian)}";
price = 3500;
lights[] = {
{"ziviS",{-0.22, 0.62, -0.47}} //Das Quadbike hat theoretisch einen Platz für ein ziviles Licht
};
textures[] = {
{ "Black", "civ", {
"\A3\Soft_F_beta\Quadbike_01\Data\quadbike_01_civ_black_co.paa"
}, "" },
{ "Blue", "civ", {
"\A3\Soft_F_beta\Quadbike_01\Data\quadbike_01_civ_blue_co.paa"
}, "" },
{ "Red", "civ", {
"\A3\Soft_F_beta\Quadbike_01\Data\quadbike_01_civ_red_co.paa"
}, "" },
{ "White", "civ", {
"\A3\Soft_F_beta\Quadbike_01\Data\quadbike_01_civ_white_co.paa"
}, "" },
{ "Digi Green", "reb", {
"\A3\Soft_F_beta\Quadbike_01\Data\quadbike_01_indp_co.paa"
}, "" },
{ "Hunter Camo", "reb", {
"\a3\soft_f_gamma\Quadbike_01\data\quadbike_01_indp_hunter_co.paa"
}, "" }
};
};
class C_SUV_01_F {
vItemSpace = 100;
tank = 50;
conditions = "";
price = 20000;
lights[]= {
{"mainR",{0.37, -1.2, 0.42}}, //Hier haben wir sämtliche Positionen definiert
{"mainL",{-0.37, -1.2, 0.42}},
{"frontR",{0.38,2.3,-0.52}},
{"frontL",{-0.38,2.3,-0.52}},
{"ziviS",{-0.55, -0.1, 0.42}}
};
textures[] = {
{ "Polizei", "cop", {
"textures\polizei\Cop_SUV.paa"
}, 2, "" }, //Skin "Polizei" ist ein offizielles Fahrzeug und bekommt blaulichtkonfig 2
{ "Kripo Schwarz", "cop", {
"\a3\soft_f_gamma\SUV_01\Data\suv_01_ext_02_co.paa"
}, 1, "" }, //Skin "Kripo Schwarz" ist halboffiziell mit Frontblitzern und bekommt blaulichtkonfig 1
{ "Silver", "civ", {
"\a3\soft_f_gamma\SUV_01\Data\suv_01_ext_03_co.paa"
}, "" }, //Skin "Silver" kann von Zivilisten gekauft werden und hat kein Blaulicht montiert
{ "Orange", "civ", { //da es aber eine ziviS Position gibt, ist ein Aufsteckblaulicht trotzdem möglich
"\a3\soft_f_gamma\SUV_01\Data\suv_01_ext_04_co.paa"
}, "" }
};
};
class B_GEN_Offroad_01_gen_F {
vItemSpace = 130;
tank = 45;
conditions = "";
price = 55000;
lights[]= {
{"mainR",{0.37, 0.0, 0.56}}, //Ein weiteres Beispiel
{"mainL",{-0.45, 0.0, 0.56}},
{"frontR",{0.22,2.55,-0.42}},
{"frontL",{-0.27,2.55,-0.42}},
{"ziviS",{-0.5, 0.25, 0.53}}
};
textures[] = {
{ "Polizei", "cop", {
"textures\polizei\Cop_Offroad.paa"
}, 2, "" }
};
};
Alles anzeigen
Ich füge unten meine Sammlung an Positionen an, damit sollten die meisten Fahrzeuge abgedeckt sein
8. (OPTIONAL) In der Config_vItems.hpp müsst Ihr nun das Aufsteckblaulicht Item einfügen und in den Cop-Shop packen (ein Icon habe ich leider nicht)
[...]
class VirtualItems {
//Virtual Items
[...]
//Aufsteckblaulicht
class blaulicht {
variable = "blaulicht";
displayName = "STR_Item_blaulicht";
weight = 3;
buyPrice = 500;
sellPrice = 250;
illegal = true;
edible = -1;
icon = "";
};
};
Alles anzeigen
In der stringtable.xml noch fix einen Knoten unter irgendeinem <Key ID="STR_Item_[...]"> einfügen
[successbox]und fertig ist das Blaulichtscript![/successbox]
EDIT 26.11.2020:
Mir ist tatsächlich jetzt erst im produktiven Betrieb aufgefallen, dass es einen Fehler mit der fn_levelCheck gibt, da diese immer das letzte Element des Skin-Arrays prüft. Ist nun korrigiert, wer das manuell Anpassen möchte, hier die betreffende Stelle in der colorVehicle:
private _lights = ((M_CONFIG(getArray,"LifeCfgVehicles",_className,"textures") select _index) param [3,0]);
if(_lights isEqualType 0) then {
_vehicle setVariable["blaulichtkonfig",_lights,true];
};
Entsprechend dann in der Config_Vehicles die Nummer eins nach vorne schieben (vor die Condition "") wie nun oben zu sehen.