Hallo Zusammen,
ich habe nach langem hin und her überlege, mich dazu entschieden, dieses Script zu veröffentlichen.
Das Script ist nicht das performanteste und bestgeschriebenste Script, denn auch ich lernte immer was dazu. Also es gibt bestimmt schönere Wege, wie man das gleiche Ziel erreichen kann.
Was macht das Script??
Das Script dient dem Einloggen als Zivilist. Das bedeutet, dass es keine weiteren Fraktionen ausser den Zivilisten gibt. Alle Polizisten und Sanitäter müssen sich als Zivilist einloggen, um ihren Dienst zu beginnen.
WICHTIG: Dieses System ist NICHTS für Anfänger! Wer nur Copy/Pasten kann, sollte hier nicht weiterlesen! Dieses Skript bedarf weiterführende Kenntnisse in der Programmierung, deshalb Schwierigkeit 5!!
Erstellt bevor ihr anfangt ein Backup! Ich garantiere nicht zur Lauffähigkeit dieses Scriptes und hafte für keine Fehler!
Dieses System müsst ihr selbst einbauen können! Schwierigkeit 5 bedeutet, dass ihr dies alleine hinbekommen müsst!
Ihr dürft alles bearbeiten wie ihr möchtet!
Ich habe mit der Arma 3 Programmierung aufgehört, sodass ich die Skripte nicht mehr gebrauchen kann, möchte diese aber nicht vorenthalten.
Also viel Spaß damit!
Dann fangen wir doch mal an:
Leider musste ich einige Dateien anhängen, da mir nur 20.000 Zeichen zur Verfügung stehen ...
Datenbank-Teil:
Schritt 1: (ich habe dies über PHPmyAdmin gemacht!)
Spoiler anzeigen
1. Öffnet die Tabelle "players" und klickt auf "Struktur".
2. Sucht die Zeile "coplevel" und bearbeitet diese.
3. Ändert den TYP von "ENUM" auf "INT" mit der Länge "2". Dadurch ist es euch möglich, bis zu 99 Ränge bei der Polizei zu erstellen.
Dies müsste dann so aussehen:
native-servers.com/attachment/13191/
4. Habt ihr weitere Fraktionen (ADAC/Rettungsdienst), müsst ihr dies dort genauso tun!
5. Durch diese Änderung ist es zudem möglich, Ingame die Spieler zu whitelisten.
Missions-Teil:
Schritt 2: Wir erstellen im Ordner "euer Missionsordner/core/" die Datei "fn_einloggen.sqf" mit folgendem Inhalt:
Die Datei ist für euch in den Dateinanhängen hinterlegt.
Schritt 3: Wir erstellen im Ordner "euer Missionsordner/core/" die Datei "fn_ausloggen.sqf" mit folgendem Inhalt:
Die Datei ist für euch in den Dateinanhängen hinterlegt.
Schritt 4: Wir gehen in die mission.sqm und geben folgende Init in einen Gegenstand ein:
this addAction['Polizeidienst beginnen',life_fnc_einloggen,'polizei',0,false,false,'','!life_cop']; " \n "this addAction['Polizeidienst beenden',life_fnc_ausloggen,'polizei',0,false,false,'','life_cop'];
Ihr könnt nach dem Tutorial alle Blufor und Opfor/Widerstand-NPC´s von der Karte entfernen!
Schritt 5: In der configuration.sqf hinterlegen wir nun die hinzugefügten Variablen:
Schritt 6: Ich habe meine fn_loadGear.sqf umgebaut. (/core/functions/)
#include "..\..\script_macros.hpp"
/*
File: fn_loadGear.sqf
Author: Bryan "Tonic" Boardwine
Description:
Loads saved civilian gear, this is limited for a reason and that's balance.
*/
private ["_itemArray","_handle"];
load_side = "";
if(life_cop) then {load_side = "cop";}; //Abfrage ob derzeit im Polizei-Dienst
if(life_retttungsdienst) then {load_side = "san";}; //Abfrage ob derzeit im Rettungsdienst
if(!life_retttungsdienst && !life_cop) then {load_side = "civ";}; //Falls beides nein, dann Zivilist
[getPlayerUID player,load_side,player] remoteExec ["TON_fnc_holeUpdates",RSERV]; //Aufruf zur holeUpdates datei! (ANDERE WEISE DER DATENBESCHAFFUNG!!!)
Alles anzeigen
Schritt 7: Wir erstellen im Ordner "euer Missionsordner/core/functions/" die Datei "fn_loadGear2.sqf" mit folgendem Inhalt:
Die Datei ist für euch in den Dateinanhängen hinterlegt.
Schritt 8: Ich habe meine fn_saveGear.sqf umgebaut. (/core/functions/)
#include "..\..\script_macros.hpp"
/*
File: fn_saveGear.sqf
Author: Bryan "Tonic" Boardwine
Full Gear/Y-Menu Save by Vampire
Edited: Itsyuka
Description:
Saves the players gear for syncing to the database for persistence..
*/
private ["_return","_uItems","_bItems","_vItems","_pItems","_hItems","_yItems","_uMags","_vMags","_bMags","_pMag","_hMag","_uni","_ves","_bag","_handled","_savedVirtualItems"];
_return = [];
_savedVirtualItems = LIFE_SETTINGS(getArray,"saved_virtualItems");
_return pushBack uniform player;
_return pushBack vest player;
_return pushBack backpack player;
_return pushBack goggles player;
_return pushBack headgear player;
_return pushBack assignedITems player;
if (playerSide isEqualTo west || playerSide isEqualTo civilian && {LIFE_SETTINGS(getNumber,"save_civilian_weapons") isEqualTo 1}) then {
_return pushBack primaryWeapon player;
_return pushBack handgunWeapon player;
} else {
_return pushBack [];
_return pushBack [];
};
_uItems = [];
_uMags = [];
_bItems = [];
_bMags = [];
_vItems = [];
_vMags = [];
_pItems = [];
_hItems = [];
_yItems = [];
_uni = [];
_ves = [];
_bag = [];
if (!(uniform player isEqualTo "")) then {
{
if (_x in (magazines player)) then {
_uMags pushBack _x;
} else {
_uItems pushBack _x;
};
} forEach (uniformItems player);
};
if (!(backpack player isEqualTo "")) then {
{
if (_x in (magazines player)) then {
_bMags pushBack _x;
} else {
_bItems pushBack _x;
};
} forEach (backpackItems player);
};
if (!(vest player isEqualTo "")) then {
{
if (_x in (magazines player)) then {
_vMags pushBack _x;
} else {
_vItems pushBack _x;
};
} forEach (vestItems player);
};
if (count (primaryWeaponMagazine player) > 0 && alive player) then {
_pMag = ((primaryWeaponMagazine player) select 0);
if (!(_pMag isEqualTo "")) then {
_uni = player canAddItemToUniform _pMag;
_ves = player canAddItemToVest _pMag;
_bag = player canAddItemToBackpack _pMag;
_handled = false;
if (_ves) then {
_vMags pushBack _pMag;
_handled = true;
};
if (_uni && !_handled) then {
_uMags pushBack _pMag;
_handled = true;
};
if (_bag && !_handled) then {
_bMags pushBack _pMag;
_handled = true;
};
};
};
if (count (handgunMagazine player) > 0 && alive player) then {
_hMag = ((handgunMagazine player) select 0);
if (!(_hMag isEqualTo "")) then {
_uni = player canAddItemToUniform _hMag;
_ves = player canAddItemToVest _hMag;
_bag = player canAddItemToBackpack _hMag;
_handled = false;
if (_ves) then {
_vMags pushBack _hMag;
_handled = true;
};
if (_uni && !_handled) then {
_uMags pushBack _hMag;
_handled = true;
};
if (_bag && !_handled) then {
_bMags pushBack _hMag;
_handled = true;
};
};
};
if (count (primaryWeaponItems player) > 0) then {
{
_pItems pushBack _x;
} forEach (primaryWeaponItems player);
};
if (count (handgunItems player) > 0) then {
{
_hItems pushBack _x;
} forEach (handGunItems player);
};
{
_val = ITEM_VALUE(_x);
if (_val > 0) then {
_yItems pushBack [_x,_val];
};
} forEach _savedVirtualItems;
_savedVirtualItems = [];
_return pushBack _uItems;
_return pushBack _uMags;
_return pushBack _bItems;
_return pushBack _bMags;
_return pushBack _vItems;
_return pushBack _vMags;
_return pushBack _pItems;
_return pushBack _hItems;
if (LIFE_SETTINGS(getNumber,"save_virtualItems") isEqualTo 1) then {
_return pushBack _yItems;
_yItems = [];
} else {
_return pushBack [];
};
life_gear = _return;
if(!life_cop && !life_rettungsdienst) then {life_civ_gear = life_gear;[4] spawn life_fnc_UpdateSpieler;}; //Speichere Zivilisten-Inventar
if(life_cop) then {life_cop_gear = life_gear;[5] spawn life_fnc_UpdateSpieler;}; //Speichere Polizei-Inventar
if(life_rettungsdienst) then {life_med_gear = life_gear;[6] spawn life_fnc_UpdateSpieler;}; //Speichere Rettungsdienst-Inventar
life_gear = [];
_return = [];
Alles anzeigen
Schritt 9: Ich habe meine fn_requestReceived.sqf umgebaut. (/core/session/)
Wichtig! Ihr dürft hier kein Copy/Paste machen! Selbst nachschauen und kontrollieren!!
CONST(life_coplevel,(_this select 7)); müsst ihr zu life_copLevel = parseNumber(_this select 6); umbauen.
Ihr braucht durch dieses Script keine Abfrage der Playerside mehr!!
#include "..\..\script_macros.hpp"
/*
File: fn_requestReceived.sqf
Author: Bryan "Tonic" Boardwine
Description:
Called by the server saying that we have a response so let's
sort through the information, validate it and if all valid
set the client up.
*/
private _count = count _this;
life_session_tries = life_session_tries + 1;
if (life_session_completed) exitWith {}; //Why did this get executed when the client already initialized?
if (life_session_tries > 3) exitWith {cutText[localize "STR_Session_Error","BLACK FADED"]; 0 cutFadeOut 999999999;};
0 cutText [localize "STR_Session_Received","BLACK FADED"];
0 cutFadeOut 9999999;
//Error handling and junk..
if (isNil "_this") exitWith {[] call SOCK_fnc_insertPlayerInfo;};
if (_this isEqualType "") exitWith {[] call SOCK_fnc_insertPlayerInfo;};
if (count _this isEqualTo 0) exitWith {[] call SOCK_fnc_insertPlayerInfo;};
if ((_this select 0) isEqualTo "Error") exitWith {[] call SOCK_fnc_insertPlayerInfo;};
if (!(getPlayerUID player isEqualTo (_this select 0))) exitWith {[] call SOCK_fnc_dataQuery;};
//Parse basic player information.
CASH = parseNumber (_this select 2);
BANK = parseNumber (_this select 3);
life_adminlevel = (_this select 4);
//Loop through licenses
if (count (_this select 8) > 0) then {
{missionNamespace setVariable [(_x select 0),(_x select 1)];} forEach (_this select 8);
};
life_gear_default = _this select 10;
life_default_gear = life_gear_default;
life_is_arrested = _this select 9;
life_copLevel = parseNumber(_this select 6);
life_medicLevel = parseNumber(_this select 5);
life_panlevel = parseNumber(_this select 7);
life_isCop = parseNumber(_this select 15);
life_isMedic = parseNumber(_this select 16);
life_isPan = parseNumber(_this select 17);
life_justizlevel = parseNumber(_this select 18);
if (LIFE_SETTINGS(getNumber,"save_playerStats") isEqualTo 1) then {
life_hunger = ((_this select 11) select 0);
life_thirst = ((_this select 11) select 1);
player setDamage ((_this select 11) select 2);
};
life_houses = _this select (_count - 3);
if (LIFE_SETTINGS(getNumber,"save_civilian_position") isEqualTo 1) then {
life_is_alive = _this select 12;
life_civ_position = _this select 13;
if (life_is_alive) then {
if !(count life_civ_position isEqualTo 3) then {diag_log format ["[requestReceived] Bad position received. Data: %1",life_civ_position];life_is_alive =false;};
if (life_civ_position distance (getMarkerPos "respawn_civilian") < 300) then {life_is_alive = false;};
};
};
{
_house = nearestObject [(call compile format ["%1",(_x select 0)]), "House"];
life_vehicles pushBack _house;
} forEach life_houses;
life_gangData = _this select (_count - 2);
if !(count life_gangData isEqualTo 0) then {
[] spawn life_fnc_initGang;
};
[] spawn life_fnc_initHouses;
if (count (_this select (_count - 1)) > 0) then {
{life_vehicles pushBack _x;} forEach (_this select (_count - 1));
};
life_session_completed = true;
Alles anzeigen
Schritt 10: Ich habe meine fn_updateRequest.sqf umgebaut. (/core/session/)
Wichtig! Ihr dürft hier kein Copy/Paste machen! Selbst nachschauen und kontrollieren!!
#include "..\..\script_macros.hpp"
/*
File: fn_updateRequest.sqf
Author: Tonic
Description:
Passes ALL player information to the server to save player data to the database.
*/
private ["_packet","_array","_flag","_alive","_position"];
_side = "";
if(life_cop) then {_side = "cop";};
if(life_rettungsdienst) then {_side = "san";};
if(!life_rettungsdienst && !life_cop ) then {_side = "civ";};
_packet = [getPlayerUID player,(profileName),_side,CASH,BANK];
_array = [];
_alive = alive player;
_position = getPosATL player;
[] call life_fnc_saveGear;
_flag = switch (playerSide) do {case west: {"cop"}; case civilian: {"civ"}; case independent: {"med"};};
{
_varName = LICENSE_VARNAME(configName _x,_flag);
_array pushBack [_varName,LICENSE_VALUE(configName _x,_flag)];
} forEach (format ["getText(_x >> 'side') isEqualTo '%1'",_flag] configClasses (missionConfigFile >> "Licenses"));
_packet pushBack _array;
if(!life_rettungsdienst && !life_cop) then
{
_packet pushBack life_civ_gear;
};
if(life_cop) then
{
_packet pushBack life_cop_gear;
};
if(life_rettungsdienst) then
{
_packet pushBack life_med_gear;
};
_array = [];
_array pushBack life_hunger;
_array pushBack life_thirst;
_array pushBack (damage player);
_packet pushBack _array;
_packet pushBack life_coplevel;
_packet pushBack life_medicLevel;
_packet pushBack life_is_arrested;
_packet pushBack _alive;
_packet pushBack _position;
if (life_HC_isActive) then {
_packet remoteExecCall ["HC_fnc_updateRequest",HC_Life];
} else {
_packet remoteExecCall ["DB_fnc_updateRequest",RSERV];
};
Alles anzeigen
Schritt 11: Wir erstellen im Ordner "euer Missionsordner/core/" die Datei "fn_paycheck.sqf" mit folgendem Inhalt:
#include "..\script_macros.hpp"
/**
* fn_paycheck.sqf
*
* LICENSE: This file is subject to the terms and conditions defined in
* file "LICENSE.md", which is part of this source code package.
*
* @author ProteusSpectrum
* @copyright 2016 ProteusSpectrum
*/
if(life_gehalt) exitWith {};
life_dienstgehalt = 0;
systemChat format ["Du erhälst deinen Lohn in 15 Minuten."];
life_gehalt = true;
//Polizei
while {life_cop} do
{
sleep 900;
if(!life_cop) exitWith {};
switch (life_coplevel) do
{
case 1: {life_dienstgehalt = 8303;}; //Meisteranwärter
case 2: {life_dienstgehalt = 10303;}; //Polizeimeister
case 3: {life_dienstgehalt = 12303;}; //Polizeiobermeister
case 4: {life_dienstgehalt = 14303;}; //Polizeihauptmeister
case 5: {life_dienstgehalt = 16303;}; //Polizeikommissaranwärter
case 6: {life_dienstgehalt = 18303;}; //Polizeikommissar
case 7: {life_dienstgehalt = 20303;}; //Polizeioberkommissar
case 8: {life_dienstgehalt = 36900;}; //Polizeihauptkommissar
case 9: {life_dienstgehalt = 41000;}; //Polizeipräsident
};
systemChat format["Du hast deinen Lohn in Höhe von $%1 erhalten.",[life_dienstgehalt] call life_fnc_numberText];
BANK = BANK + life_dienstgehalt;
life_gehalt = false;
};
//Sanitäter
while {life_rettungsdienst} do
{
sleep 900;
if(!life_rettungsdienst) exitWith {};
switch (life_medicLevel) do
{
case 1: {life_dienstgehalt = 8303;}; //Ersthelfer
case 2: {life_dienstgehalt = 11070;}; //Rettungsdienst
case 3: {life_dienstgehalt = 14760;}; //Rettungssanitäter
case 4: {life_dienstgehalt = 36900;}; //Notarzt
case 5: {life_dienstgehalt = 41000;}; //Leitender Notarzt
};
systemChat format["Du hast deinen Lohn in Höhe von $%1 erhalten.",[life_dienstgehalt] call life_fnc_numberText];
BANK = BANK + life_dienstgehalt;
life_gehalt = false;
};
Alles anzeigen
Schritt 12: Wir erstellen im Ordner "euer Missionsordner/core/civilian" die Datei "fn_UpdateSpieler.sqf" mit folgendem Inhalt:
Diese Datei sorgt dafür, dass die Anfragen zur Speicherung an die Life_Server-Datei übergeben wird.
Da ich noch weitere Funktionen eingefügt habe, müsst ihr euch diese Datei anpassen. Für dieses Tutoriale wichtige Inhalte habe ich euch markiert.
#include "..\..\script_macros.hpp"
/*
File: fn_updateSpieler.sqf
Author: Tonic
Description:
Passes ALL player information to the server to save player data to the database.
*/
private ["_packet","_array","_flag","_alive","_position"];
_mode = _this select 0;
switch (_mode) do
{
//Kontakte speichern
case 0:
{
_packet = [0, getPlayerUID player, life_kontakte];
_packet remoteExecCall ["TON_fnc_Updates",RSERV];
};
//Kontakte laden
case 1:
{
_packet = [1, getPlayerUID player, player];
_packet remoteExecCall ["TON_fnc_Updates",RSERV];
};
//Kontakte einspeichern
case 2:
{
life_kontakte = _this select 1;
};
//AceActions Lizenzen speichern
case 3:
{
_packet = [2, getPlayerUID player];
_array = [];
_flag = switch (playerSide) do {case west: {"cop"}; case civilian: {"civ"}; case independent: {"med"};};
{
_varName = LICENSE_VARNAME(configName _x,_flag);
_array pushBack [_varName,LICENSE_VALUE(configName _x,_flag)];
} forEach (format ["getText(_x >> 'side') isEqualTo '%1'",_flag] configClasses (missionConfigFile >> "Licenses"));
_packet pushBack _array;
_packet remoteExecCall ["TON_fnc_Updates",RSERV];
};
//Zivilisten Gear
case 4:
{
_packet = [3, getPlayerUID player, player, life_civ_gear];
_packet remoteExecCall ["TON_fnc_Updates",RSERV];
};
//Polizei Gear
case 5:
{
_packet = [4, getPlayerUID player, player, life_cop_gear];
_packet remoteExecCall ["TON_fnc_Updates",RSERV];
};
//Rettungsdienst Gear
case 6:
{
_packet = [5, getPlayerUID player, player, life_med_gear];
_packet remoteExecCall ["TON_fnc_Updates",RSERV];
};
};
Alles anzeigen
Schritt 13: Nun müsst seit ihr dran:
Alle Abfragen von der Playerside (BSP: switch (playerSide) do { ... };) auf folgendes umschreiben:
Bei Polizei: if(life_cop)then {...};
Bei Rettungsdienst: if(life_rettungsdienst)then {...};
Da dies je nach Mission unterschiedlich ist, müsst ihr das erledigen!
Schritt 14: Nun müsst ihr nur noch die neuerstellten Dateien in die functions.h eintragen im entsprechenden Bereich und die RemoteExec Aufruf-Dateien in der CfgRemoteExec.hpp!
Da dieses Tutorial die Stufe 5 vorweist, denke ich, dass ihr das selbst hinbekommen müsst.
Life-Server-Teil:
Schritt 15: Nun geht in die "life_server/init.sqf" und fügt folgendes hinzu (sofern nicht schon vorhanden!)
unter der Zeile "[8,true,24] execFSM "\life_server\FSM\timeModule.fsm";"
life_adminLevel = 0;
life_medicLevel = 0;
life_copLevel = 0;
Schritt 16: Nun geht in die "life_server/functions/MySQL/fn_queryRequest.sqf".
Wichtig: Wer hier Copy/Paste macht, ist selbst Schuld! Dies muss genau an euren Server angepasst sein!
Die Datei ist für euch in den Dateinanhängen hinterlegt.
Schritt 17: Nun geht in die "life_server/functions/MySQL/fn_updateRequest.sqf".
Wichtig! Ihr müsst auch hier selbst nachdenken! Wer keine fortgeschrittenen Kenntnisse hat, sollte von diesem System die Finger weglassen!
Bei mir sind alle Abfragen anders! Die angehängte Datei ist nur ein Beispiel!!!
Die Datei ist für euch in den Dateinanhängen hinterlegt.
Aufgrund der maximalen Statement-Länge habe ich die Lizenzen getrennt von den Variablen gespeichert und in ein eigenes Statement gepackt.
Schritt 18: Wir erstellen im Ordner "life_server/functions/Systems/" die Datei "fn_holeUpdates.sqf" mit folgendem Inhalt:
Diese Datei sorgt dafür, dass alle Spielerinventare auf Anfrage geladen werden!
Die Datei ist für euch in den Dateinanhängen hinterlegt.
Schritt 19: Wir erstellen im Ordner "life_server/functions/Systems/" die Datei "fn_Updates.sqf" mit folgendem Inhalt:
Auch hier hatte ich weitere Update-Statements, die ihr ignorieren könnt.
Die Datei ist für euch in den Dateinanhängen hinterlegt.
Schritt 20: Auch hier müsst ihr alle neu erstellen Dateien in die entsprechenden Dateien eintragen.
Das solltet ihr hinbekommen.
Nun sollte alles wichtige implementiert sein.
Ich wünsche euch viel Spaß mit diesem System!