- Offizieller Beitrag
Hallo zusammen!
Folgende Scriptinhalte stammen von Guitoxx, danke dafür.
Was tut dieses Script?
Mithilfe dieses Scripts könnt ihr sowohl eure Fahrzeuge als auch eure Helikopter oder Flugzeuge im Spiel versichern lassen.
Ein versichertes Fahrzeug taucht im Falle seiner Zerstörung wieder in der Garage des Besitzers auf, die Versicherung selbst kann über das Garagen-Menu abgeschlossen werden.
WICHTIG: Beachtet bitte den Schwierigkeitsgrad dieses Tutorials. Erklärungen zu Variablen, Klassen und Querys werden hier nicht beantwortet.
Im Zweifelsfall: SQF Script Guide und Schwierigkeitsgrad für Tutorials
Also fangen wir an.
Öffnet zuerst folgende Datei: dialog\impound.hpp
Fügt dort nun unter "Class controlsBackground" folgende neue Klasse hinzu:
class InsureCar : life_RscButtonMenu
{
idc = 97480;
text = "Assurer";
onButtonClick = "[] call life_fnc_InsureCar;";
x = 0.43 + (6.25 / 40) + (1 / 250 / (safezoneW / safezoneH));
y = 0.9 - (1 / 25);
w = (6.25 / 40);
h = (1 / 25);
};
Anschließend erstellt eine Datei mit dem Namen fn_insureCar.sqf und folgendem Inhalt in diesem Verzeichnis: dialog\function
#include "..\..\script_macros.hpp"
/*
File: fn_insureCar.sqf
Author: Guit0x "Lintox"
Description:
Insure a vehicle from the garage.
*/
private["_vehicle","_vehicleLife","_vid","_pid","_unit","_assurPrice"];
disableSerialization;
if(EQUAL(lbCurSel 2802,-1)) exitWith {hint localize "STR_Global_NoSelection"};
_vehicle = lbData[2802,(lbCurSel 2802)];
_vehicle = (call compile format["%1",_vehicle]) select 0;
_vehicleLife = _vehicle;
_vid = lbValue[2802,(lbCurSel 2802)];
_pid = steamid;
_unit = player;
if(isNil "_vehicle") exitWith {hint localize "STR_Garage_Selection_Error"};
if((time - life_action_delay) < 1.5) exitWith {hint localize "STR_NOTF_ActionDelay";};
if(!isClass (missionConfigFile >> CONFIG_LIFE_VEHICLES >> _vehicleLife)) then {
_vehicleLife = "Default"; //Use Default class if it doesn't exist
diag_log format["%1: LifeCfgVehicles class doesn't exist",_vehicle];
};
_assurPrice = switch(playerSide) do {
case civilian: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_vehicleLife,"assurPrice"),0)};
case west: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_vehicleLife,"assurPrice"),1)};
case independent: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_vehicleLife,"assurPrice"),2)};
case east: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_vehicleLife,"assurPrice"),3)};
};
if(!(EQUAL(typeName _assurPrice,typeName 0)) OR _assurPrice < 1) then {_assurPrice = 1000};
if(BANK < _assurPrice) exitWith {hint format[localize "STR_Garage_CashError",[_assurPrice] call life_fnc_numberText];};
[_vid,_pid,_assurPrice,player,life_garage_type] remoteExecCall ["TON_fnc_insureCar",RSERV];
hint format[localize "STR_Assur_OK"],
SUB(BANK,_assurPrice);
life_action_delay = time;
closeDialog 0;
Alles anzeigen
Natürlich solltet ihr dann die Klasse "class insureCar{};" eurer Function.h unter "Class Dialog_Controls" hinzufügen.
Nun wird Serverseitig in eurer config.cpp folgende Klasse unter "Class TON_System" erstellt: class insureCar{};
Im Anschluss öffnet eure life_server\Functions\Systems\fn_spawnVehicle.sqf, sucht dort den "_query" und ersetzt ihn durch folgendes:
_query = format["SELECT id, side, classname, type, pid, alive, active, plate, color, insure FROM vehicles WHERE id='%1' AND pid='%2'",_vid,_pid];
Ebenfalls in dieser Datei sucht ihr folgende Zeile: _vehicle setVariable["dbInfo",[(_vInfo select 4),_vInfo select 7]];
und fügt dort "_vInfo select 9" hinzu, das ganze sollte dann so aussehen:
_vehicle setVariable["dbInfo",[(_vInfo select 4),_vInfo select 7, _vInfo select 9]];
Ebenfalls innerhalb dieser Datei ersetzt ihr diese Zeile: [1,"Your vehicle is ready!"] remoteExecCall ["life_fnc_broadcast",_unit];
Durch folgendes (Texte natürlich je nach Sprache ändern...):
if((_vInfo select 9) == 1) then {
[1,"Votre véhicule est prêt et assurer!"] remoteExecCall ["life_fnc_broadcast",_unit];
}
else {
[1,"Votre véhicule est prêt!"] remoteExecCall ["life_fnc_broadcast",_unit];
};
Erstellt nun unter life_server\functions\Systems eine Datei mit dem Namen fn_insureCar.sqf und folgendem Inhalt:
/*
File: fn_insureCar.sqf
Author: Guit0x "Lintox"
Description:
Insure a vehicle from the garage.
*/
private["_vid","_pid","_query","_sql", "_unit", "_assurPrice", "_thread"];
_vid = [_this,0,-1,[0]] call BIS_fnc_param;
_pid = [_this,1,"",[""]] call BIS_fnc_param;
_unit = [_this,2,ObjNull,[ObjNull]] call BIS_fnc_param;
_assurPrice = [_this,3,0,[0]] call BIS_fnc_param;
_query = format["UPDATE vehicles SET insure='1' WHERE pid='%1' AND id='%2'",_pid,_vid];
waitUntil {!DB_Async_Active};
_thread = [_query,1] call DB_fnc_asyncCall;
Alles anzeigen
Danach ersetzt ihr den Inhalt folgender Datei in eurer Mission mit folgendem Inhalt: \dialog\function\fn_garageLBChange.sqf
#include "..\..\script_macros.hpp"
/*
File: fn_garageLBChange.sqf
Author: Bryan "Tonic" Boardwine
Description:
Can't be bothered to answer it.. Already deleted it by accident..
*/
disableSerialization;
private["_control","_index","_className","_classNameLife","_dataArr","_vehicleColor","_vehicleInfo","_trunkSpace","_sellPrice","_retrievePrice","_assurPrice","_assur"];
_control = SEL(_this,0);
_index = SEL(_this,1);
//Fetch some information.
_dataArr = CONTROL_DATAI(_control,_index);
_dataArr = call compile format["%1",_dataArr];
_className = SEL(_dataArr,0);
_classNameLife = _className;
_assur = SEL(_dataArr,2);
if(!isClass (missionConfigFile >> CONFIG_LIFE_VEHICLES >> _classNameLife)) then {
_classNameLife = "Default"; //Use Default class if it doesn't exist
diag_log format["%1: LifeCfgVehicles class doesn't exist",_className];
};
_vehicleColor = SEL(SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"textures"),SEL(_dataArr,1)),0);
if(isNil "_vehicleColor") then {_vehicleColor = "Default";};
_vehicleInfo = [_className] call life_fnc_fetchVehInfo;
_trunkSpace = [_className] call life_fnc_vehicleWeightCfg;
_retrievePrice = switch(playerSide) do {
case civilian: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"storageFee"),0)};
case west: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"storageFee"),1)};
case independent: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"storageFee"),2)};
case east: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"storageFee"),3)};
};
_sellPrice = switch(playerSide) do {
case civilian: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"garageSell"),0)};
case west: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"garageSell"),1)};
case independent: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"garageSell"),2)};
case east: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"garageSell"),3)};
};
_assurPrice = switch(playerSide) do {
case civilian: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"assurPrice"),0)};
case west: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"assurPrice"),1)};
case independent: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"assurPrice"),2)};
case east: {SEL(M_CONFIG(getArray,CONFIG_LIFE_VEHICLES,_classNameLife,"assurPrice"),3)};
};
if(!(EQUAL(typeName _sellPrice,typeName 0)) OR _sellPrice < 1) then {_sellPrice = 1000};
if(!(EQUAL(typeName _retrievePrice,typeName 0)) OR _retrievePrice < 1) then {_retrievePrice = 1000};
if(!(EQUAL(typeName _assurPrice,typeName 0)) OR _assurPrice < 1) then {_assurPrice = 10000};
(CONTROL(2800,2803)) ctrlSetStructuredText parseText format[
(localize "STR_Shop_Veh_UI_RetrievalP")+ " <t color='#8cff9b'>$%1</t><br/>
" +(localize "STR_Shop_Veh_UI_SellP")+ " <t color='#8cff9b'>$%2</t><br/>
Prix de l'assurance: <t color='#8cff9b'>$%9</t><br/>
Etat de l'assurance: %10<br/>
" +(localize "STR_Shop_Veh_UI_Color")+ " <t color='#8cff9b'>%8</t><br/>
" +(localize "STR_Shop_Veh_UI_MaxSpeed")+ " <t color='#8cff9b'>%3 km/h</t><br/>
" +(localize "STR_Shop_Veh_UI_HPower")+ " <t color='#8cff9b'>%4</t><br/>
" +(localize "STR_Shop_Veh_UI_PSeats")+ " <t color='#8cff9b'>%5</t><br/>
" +(localize "STR_Shop_Veh_UI_Trunk")+ " <t color='#8cff9b'>%6</t><br/>
" +(localize "STR_Shop_Veh_UI_Fuel")+ " <t color='#8cff9b'>%7</t>
",
[_retrievePrice] call life_fnc_numberText,
[_sellPrice] call life_fnc_numberText,
SEL(_vehicleInfo,8),
SEL(_vehicleInfo,11),
SEL(_vehicleInfo,10),
if(_trunkSpace == -1) then {"None"} else {_trunkSpace},
SEL(_vehicleInfo,12),
_vehicleColor,
[_assurPrice] call life_fnc_numberText,
if(_assur == 1) then {"<t color='#8cff9b'>Assuré</t>"} else {"<t color='#FF0000'>Pas d'assurance</t>"},
SEL(_vehicleInfo,9)
];
if(_assur == 1) then {
ctrlShow [97480,False];
}else{
ctrlShow [97480,True];
};
ctrlShow [2803,true];
ctrlShow [2830,true];
Alles anzeigen
Für Farbänderungen dienen folgende Zeilen:
(localize "STR_Shop_Veh_UI_RetrievalP")+ " <t color='#8cff9b'>$%1</t><br/>
" +(localize "STR_Shop_Veh_UI_SellP")+ " <t color='#8cff9b'>$%2</t><br/>
Prix de l'assurance: <t color='#8cff9b'>$%9</t><br/>
Etat de l'assurance: %10<br/>
" +(localize "STR_Shop_Veh_UI_Color")+ " <t color='#8cff9b'>%8</t><br/>
" +(localize "STR_Shop_Veh_UI_MaxSpeed")+ " <t color='#8cff9b'>%3 km/h</t><br/>
" +(localize "STR_Shop_Veh_UI_HPower")+ " <t color='#8cff9b'>%4</t><br/>
" +(localize "STR_Shop_Veh_UI_PSeats")+ " <t color='#8cff9b'>%5</t><br/>
" +(localize "STR_Shop_Veh_UI_Trunk")+ " <t color='#8cff9b'>%6</t><br/>
" +(localize "STR_Shop_Veh_UI_Fuel")+ " <t color='#8cff9b'>%7</t>
if(_assur == 1) then {"<t color='#8cff9b'>Assuré</t>"} else {"<t color='#FF0000'>Pas d'assurance</t>"},
Alles anzeigen
Unter dialog\function\fn_impoundMenu.sqf sucht ihr nach folgender Zeile: _tmp = [_x select 2,_x select 8];
und fügt dort "_x select 9" hinzu, was so aussehen sollte:
Öffnet nun eure cleanup.fsm unter life_server\FSM\cleanup.fsm und ersetzt den Inhalt durch folgenden:
/*%FSM<COMPILE "D:\Bohemia Interactive\Tools\FSM Editor Personal Edition\scriptedFSM.cfg, Server-Side Cleanup">*/
/*%FSM<HEAD>*/
/*
item0[] = {"init",0,250,-65.004578,-391.651611,24.995417,-341.651672,0.000000,"init"};
item1[] = {"true",8,218,-62.976639,-315.185364,27.023363,-265.185364,0.000000,"true"};
item2[] = {"Share__Work_load",2,250,-64.183350,-224.681931,25.816656,-174.681931,0.000000,"Share " \n "Work-load"};
item3[] = {"true",8,218,-54.709698,75.189262,35.290302,125.189262,0.000000,"true"};
item4[] = {"Time_Check",4,218,-219.425827,-133.310532,-129.425964,-83.310455,0.000000,"Time Check"};
item5[] = {"Delete_Dead_Cars",2,4346,-220.186951,-29.248400,-130.187195,20.751413,0.000000,"Delete" \n "Dead" \n "Cars"};
item6[] = {"",7,210,-312.538239,95.295059,-304.538239,103.295059,0.000000,""};
item7[] = {"",7,210,-311.750000,-203.033707,-303.750000,-195.033707,0.000000,""};
link0[] = {0,1};
link1[] = {1,2};
link2[] = {2,4};
link3[] = {3,6};
link4[] = {4,5};
link5[] = {5,3};
link6[] = {6,7};
link7[] = {7,2};
globals[] = {0.000000,0,0,0,0,640,480,1,46,6316128,1,-629.444153,611.207214,293.309357,-434.050568,1243,885,1};
window[] = {2,-1,-1,-1,-1,985,225,1868,225,3,1261};
*//*%FSM</HEAD>*/
class FSM
{
fsmName = "Server-Side Cleanup";
class States
{
/*%FSM<STATE "init">*/
class init
{
name = "init";
init = /*%FSM<STATEINIT""">*/"private[""_impound"",""_cars"",""_objs"",""_totCars"",""_thread""];" \n
"_impound = time;" \n
"_cars = time;" \n
"_objs = time;"/*%FSM</STATEINIT""">*/;
precondition = /*%FSM<STATEPRECONDITION""">*/""/*%FSM</STATEPRECONDITION""">*/;
class Links
{
/*%FSM<LINK "true">*/
class true
{
priority = 0.000000;
to="Share__Work_load";
precondition = /*%FSM<CONDPRECONDITION""">*/""/*%FSM</CONDPRECONDITION""">*/;
condition=/*%FSM<CONDITION""">*/"true"/*%FSM</CONDITION""">*/;
action=/*%FSM<ACTION""">*/""/*%FSM</ACTION""">*/;
};
/*%FSM</LINK>*/
};
};
/*%FSM</STATE>*/
/*%FSM<STATE "Share__Work_load">*/
class Share__Work_load
{
name = "Share__Work_load";
init = /*%FSM<STATEINIT""">*/""/*%FSM</STATEINIT""">*/;
precondition = /*%FSM<STATEPRECONDITION""">*/""/*%FSM</STATEPRECONDITION""">*/;
class Links
{
/*%FSM<LINK "Time_Check">*/
class Time_Check
{
priority = 0.000000;
to="Delete_Dead_Cars";
precondition = /*%FSM<CONDPRECONDITION""">*/""/*%FSM</CONDPRECONDITION""">*/;
condition=/*%FSM<CONDITION""">*/"((time - _cars) > (3 * 60))"/*%FSM</CONDITION""">*/;
action=/*%FSM<ACTION""">*/""/*%FSM</ACTION""">*/;
};
/*%FSM</LINK>*/
};
};
/*%FSM</STATE>*/
/*%FSM<STATE "Delete_Dead_Cars">*/
class Delete_Dead_Cars
{
name = "Delete_Dead_Cars";
init = /*%FSM<STATEINIT""">*/"{" \n
" if(!alive _x) then {" \n
" _dbInfo = _x getVariable[""dbInfo"",[]];" \n
" if(count _dbInfo > 0) then {" \n
" _uid = _dbInfo select 0;" \n
" _plate = _dbInfo select 1;" \n
" _insureSystem = _dbInfo select 2;" \n
" diag_log "" destroy vehicule !"";" \n
" diag_log format[""insureSystem = %1 "", _insureSystem];" \n
" if(_insureSystem == 1) then " \n
" { " \n
" diag_log "" Assurer !"";" \n
" diag_log format[""insureSystem = %1 "", _insureSystem];" \n
" _query_0 = format[""UPDATE vehicles SET alive='1', insure='0', active='0' WHERE pid='%1' AND plate='%2'"",_uid,_plate]; " \n
" _query_0 spawn " \n
" {" \n
" waitUntil {!DB_Async_Active};" \n
" _thread_0 = [_this,1] spawn DB_fnc_asyncCall;" \n
" };" \n
" } " \n
" else " \n
" { " \n
" diag_log "" Pas Assurer !"";" \n
" diag_log format[""insureSystem = %1 "", _insureSystem];" \n
" _query = format[""UPDATE vehicles SET alive='0' WHERE pid='%1' AND plate='%2'"",_uid,_plate]; " \n
" _query spawn " \n
" {" \n
" waitUntil {!DB_Async_Active};" \n
" _thread = [_this,1] spawn DB_fnc_asyncCall;" \n
" }; " \n
" }; " \n
" };" \n
" if(!isNil ""_x"" && {!isNull _x}) then {" \n
" deleteVehicle _x;" \n
" };" \n
" };" \n
"} foreach allMissionObjects ""LandVehicle"";" \n
"" \n
"{" \n
" if(!alive _x) then {" \n
" _dbInfo = _x getVariable[""dbInfo"",[]];" \n
" if(count _dbInfo > 0) then {" \n
" _uid = _dbInfo select 0;" \n
" _plate = _dbInfo select 1;" \n
" _insureSystem = _dbInfo select 2;" \n
" diag_log "" destroy vehicule !"";" \n
" diag_log format[""insureSystem = %1 "", _insureSystem];" \n
" if(_insureSystem == 1) then " \n
" { " \n
" diag_log "" Assurer !"";" \n
" diag_log format[""insureSystem = %1 "", _insureSystem];" \n
" _query_0 = format[""UPDATE vehicles SET alive='1', insure='0', active='0' WHERE pid='%1' AND plate='%2'"",_uid,_plate]; " \n
" _query_0 spawn " \n
" {" \n
" waitUntil {!DB_Async_Active};" \n
" _thread_0 = [_this,1] spawn DB_fnc_asyncCall;" \n
" };" \n
" } " \n
" else " \n
" { " \n
" diag_log "" Pas Assurer !"";" \n
" diag_log format[""insureSystem = %1 "", _insureSystem];" \n
" _query = format[""UPDATE vehicles SET alive='0' WHERE pid='%1' AND plate='%2'"",_uid,_plate]; " \n
" _query spawn " \n
" {" \n
" waitUntil {!DB_Async_Active};" \n
" _thread = [_this,1] spawn DB_fnc_asyncCall;" \n
" }; " \n
" }; " \n
" };" \n
" if(!isNil ""_x"" && {!isNull _x}) then {" \n
" deleteVehicle _x;" \n
" };" \n
" };" \n
"} foreach allMissionObjects ""Air"";" \n
"" \n
"_cars = time;" \n
"" \n
"//Group cleanup." \n
"{" \n
" if(count units _x == 0 && local _x) then {" \n
" deleteGroup _x;" \n
" };" \n
"} foreach allGroups;"/*%FSM</STATEINIT""">*/;
precondition = /*%FSM<STATEPRECONDITION""">*/""/*%FSM</STATEPRECONDITION""">*/;
class Links
{
/*%FSM<LINK "true">*/
class true
{
priority = 0.000000;
to="Share__Work_load";
precondition = /*%FSM<CONDPRECONDITION""">*/""/*%FSM</CONDPRECONDITION""">*/;
condition=/*%FSM<CONDITION""">*/"true"/*%FSM</CONDITION""">*/;
action=/*%FSM<ACTION""">*/""/*%FSM</ACTION""">*/;
};
/*%FSM</LINK>*/
};
};
/*%FSM</STATE>*/
};
initState="init";
finalStates[] =
{
};
};
/*%FSM</COMPILE>*/
Alles anzeigen
Texte ändert ihr in folgenden Zeilen:
Öffnet nun eure Config_Vehicles.hpp und fügt für alle Fahrzeuge welche ihr versichern wollt unter LifeCfgVehicles folgendes hinzu: assurPrice[] = { 1000, 1000, 1000, 1000 };
Erstellt dann folgenden Eintrag in eurer CfgRemoteExec.hpp: F(TON_fnc_insureCar,SERVER)
Sucht nun unter life_server\functions\Systems\fn_getVehicles.sqf nach eurem "_query" und ersetzt diesen durch folgendes:
_query = format["SELECT id, side, classname, type, pid, alive, active, plate, color, insure FROM vehicles WHERE pid='%1' AND alive='1' AND active='0' AND side='%2' AND type='%3'",_pid,_side,_type];
Nun fügt ihr eurer Datenbanktabelle "vehicles" die Spalte "insure" hinzu, hier die Struktur:
-- ----------------------------
-- Table structure for `vehicles`
-- ----------------------------
DROP TABLE IF EXISTS `vehicles`;
CREATE TABLE `vehicles` (
`id` int(12) NOT NULL AUTO_INCREMENT,
`side` varchar(15) NOT NULL,
`classname` varchar(32) NOT NULL,
`type` varchar(12) NOT NULL,
`pid` varchar(32) NOT NULL,
`alive` tinyint(1) NOT NULL DEFAULT '1',
`active` tinyint(1) NOT NULL DEFAULT '0',
`plate` int(20) NOT NULL,
`color` int(20) NOT NULL,
`inventory` varchar(500) NOT NULL,
`insure` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `side` (`side`),
KEY `pid` (`pid`),
KEY `type` (`type`)
) ENGINE=InnoDB AUTO_INCREMENT=152 DEFAULT CHARSET=latin1;
Alles anzeigen
Zum Schluss öffnet eure life_server\Functions\Systems\fn_vehicleCreate.sqf und fügt unter private "_insureSystem " hinzu. Danach erstellt ihr dort noch folgende Variable am oberen Ende der Datei: _insureSystem = 0;
danach sucht nach folgender Zeile: _vehicle setVariable["dbInfo",[_uid,_plate]];
und fügt dort "_insureSystem" hinzu, das sollte dann so aussehen: _vehicle setVariable["dbInfo",[_uid,_plate,_insureSystem]];
Das soll es gewesen sein. Viel Spaß damit!