Ich habe mich gestern aus eigenem Interesse mal ran gesetzt und das "News Broadcast" Script aus der Altis Life v4.4r3 ein wenig umgeschrieben, um den Cops die Möglichkeit zu bieten ebenfalls Nachrichten über dieses Tool zu senden. Und dieses kleine aber feine Script möchte ich nun mit euch teilen.
Script: AAN News Rundnachrichten (Auch bekannt als '7 News Script')
Version: Altis Life 4.0+ (getestet in 4.4 & 4.4r3)
Schiwerigkeitsgrad: Fortgeschrittener (mittel) - ein gewisses Scriptverständnis wird zum Bearbeiten vorausgesetzt!
Funktionen:
~ Möglichkeit für Zivilisten, eine Nachricht im "Fernsehen" zu senden (gegen eine Gebühr)
~ Möglichkeit für Cops, eine Nachricht im "Fernsehen" zu senden (Button im Z-Menü)
Erweiterungen:
HIER geht es zur Erweiterung "Erpresste Rundnachrichten" die es ermöglicht, den Reporter zu "bedrohen" (für Rebellen interessant ^^)
Rechtliche Hinweise (Copyright):
Dieses Script/Tutorial basiert auf Code aus dem offiziellen Arma Life RPG Framework - ich habe diesen lediglich abgeändert!
Ich untersage dennoch die Verbreitung dieser Daten und die des von mir verfassten Tutorials in anderen Foren ohne vorher mein Einverständnis dazu einzuholen.
Nun zum eigentlichen Teil dieses Posts...
Anleitung:
Hinweis:
In der Version 4.4r3 ist dieses Script bereits eingebaut! Falls ihr diese Version nutzt, sind nur die mit * markierten Punkte notwendig! Außerdem müssen in dieser Version die Dateien nur abgeändert und nicht erstellt werden! (Inhalt kann 1:1 übernommen werden)
-
* Öffnet eure Config_Master.hpp und fügt dort folgendes einC
/* Channel 7 News Station Configurations */ news_broadcast_cost = 150000; //Preis für eine Nachricht im Fernsehen news_broadcast_cooldown = 20; //Abklingzeit zwischen zwei Nachrichten. (Default = 20 minutes) news_broadcast_header_length = 60; //Maximallänge der Überschrift. Alles darüber wird abgeschnitten. Hängt von der Schriftart, -größe und anderen Faktoren ab. Vorsicht beim Abändern! cop_news_broadcast_cooldown = 5; //Abklingzeit zwischen zwei Nachrichten der Polizei cop_news_broadcast_minimum_Rank = 5; //Benötigter Rang für Polizisten, um Nachricht zu senden
- Öffnet eure CfgRemoteExec.hpp und fügt unter den Client only Functions folgendes ein
- Öffnet eure Functions.hpp und fügt folgende Einträge ein:
unter class Actions
unter class Functions
-
* Erstellt eine neue Datei fn_newsBroadcast.sqf im Ordner core\actions mit folgendem InhaltC
Alles anzeigen#include "..\..\script_macros.hpp" /* File: fn_newsBroadcast.sqf Author: Jesse "tkcjesse" Schultz edited by: blackfisch Description: Creates the dialog and handles the data in the Channel 7 News Dialog. */ #define Confirm 100104 private ["_msgCost","_msgRank","_rank","_copCooldown","_display","_confirmBtn","_msgCooldown","_broadcastDelay"]; createDialog "life_news_broadcast"; disableSerialization; _display = findDisplay 100100; _confirmBtn = _display displayCtrl Confirm; _confirmBtn ctrlEnable false; _msgCooldown = (60 * LIFE_SETTINGS(getNumber,"news_broadcast_cooldown")); _msgCost = LIFE_SETTINGS(getNumber,"news_broadcast_cost"); _copCooldown = (60 * LIFE_SETTINGS(getNumber,"cop_news_broadcast_cooldown")); _msgRank = LIFE_SETTINGS(getNumber,"cop_news_broadcast_minimum_Rank"); _rank = call life_coplevel; switch (playerside) do { case west: { if (_rank < _msgRank) then { hint format["Du besitzt nicht den benötigten Rang! (benötigter Rang: %1)", _msgRank]; closeDialog 0; } else { _confirmBtn ctrlEnable true; _confirmBtn buttonSetAction "[ctrlText 100101,ctrlText 100102,profilename,""cop""] call life_fnc_postNewsBroadcast; closeDialog 0;"; }; if (isNil "life_copBroadcastTimer" || {(time - life_copBroadcastTimer) > _copCooldown}) then { _broadcastDelay = localize "STR_News_Now"; } else { _broadcastDelay = [(_msgCooldown - (time - life_copBroadcastTimer))] call BIS_fnc_secondsToString; _confirmBtn ctrlEnable false; }; CONTROL(100100,100103) ctrlSetStructuredText parseText format["Benötigter Rang: %1<br/>Nächste Übertragung verfügbar: %2",[_msgRank] call life_fnc_numberText,_broadcastDelay]; }; case civilian: { if (CASH < _msgCost) then { hint format[localize "STR_News_NotEnough",[_msgCost] call life_fnc_numberText]; } else { _confirmBtn ctrlEnable true; _confirmBtn buttonSetAction "[ctrlText 100101,ctrlText 100102,profilename,""civ""] call life_fnc_postNewsBroadcast; closeDialog 0;"; }; if (isNil "life_broadcastTimer" || {(time - life_broadcastTimer) > _msgCooldown}) then { _broadcastDelay = localize "STR_News_Now"; } else { _broadcastDelay = [(_msgCooldown - (time - life_broadcastTimer))] call BIS_fnc_secondsToString; _confirmBtn ctrlEnable false; }; CONTROL(100100,100103) ctrlSetStructuredText parseText format[ localize "STR_News_StructuredText",[_msgCost] call life_fnc_numberText,_broadcastDelay]; }; default {}; };
-
* Erstellt eine Datei fn_postNewsBroadcast.sqf im Ordner core\functions mit folgendem InhaltC
Alles anzeigen#include "..\..\script_macros.hpp" /* File: fn_postNewsBroadcast.sqf Author: Jesse "tkcjesse" Schultz edited by: blackfisch Description: Handles actions after the broadcast button is clicked. */ private ["_broadcastHeader","_broadcastMessage","_length","_badCharacter","_characterByte","_allowed","_allowedLength"]; disableSerialization; _broadcastHeader = ctrlText (CONTROL(100100,100101)); _broadcastMessage = ctrlText (CONTROL(100100,100102)); _length = count (toArray (_broadcastHeader)); _characterByte = toArray (_broadcastHeader); _allowed = toArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.,:/()[]\ÄÖÜäöüß?!=&%$§ '#`´{}<>|-+*@^°"); _allowedLength = LIFE_SETTINGS(getNumber,"news_broadcast_header_length"); _badCharacter = false; _side = _this select 3; if (_length > _allowedLength) exitWith {hint format[localize "STR_News_HeaderLength",_allowedLength];}; { if (!(_x in _allowed)) exitWith {_badCharacter = true;}; } forEach _characterByte; if (_badCharacter) exitWith {hint localize "STR_News_UnsupportedCharacter"}; switch (_side) do { case "cop": { _sender = format["Altis Police Department - Officer %1", profileName]; /* Hinweis: "Altis Police Department - Officer" kann entfernt oder abgeändert werden nach Belieben! '%1' repräsentiert den Namen des Spielers */ [_broadcastHeader,_broadcastMessage,_sender] remoteExec ['life_fnc_AAN',-2]; [0] call SOCK_fnc_updatePartial; life_copBroadcastTimer = time; publicVariable "life_copBroadcastTimer"; }; case "civ": { [_broadcastHeader,_broadcastMessage,profileName] remoteExec ['life_fnc_AAN',-2]; CASH = CASH - LIFE_SETTINGS(getNumber,"news_broadcast_cost"); [0] call SOCK_fnc_updatePartial; life_broadcastTimer = time; publicVariable "life_broadcastTimer"; }; default {}; };
- Ladet euch die fn_AAN.sqf herunter und fügt sie in den core\functions Ordner ein fn_AAN.sqf
- Öffnet eure configuration.sqf (zu finden im core Ordner) und fügt dort unter den Backend Variable folgendes ein:
- Erstellt eine neue Datei newsStation.hpp im Ordner dialog mit folgendem InhaltCSS
Alles anzeigenclass life_news_broadcast { idd = 100100; name= "life_news_broadcast"; movingEnable = 0; enableSimulation = 1; class controlsBackground { class Life_RscTitleBackground: Life_RscText { colorBackground[] = {"(profileNamespace getVariable ['GUI_BCG_RGB_R',0.3843])", "(profileNamespace getVariable ['GUI_BCG_RGB_G',0.7019])", "(profileNamespace getVariable ['GUI_BCG_RGB_B',0.8862])", "(profileNamespace getVariable ['GUI_BCG_RGB_A',0.7])"}; idc = -1; x = 0.1; y = 0.2; w = 0.64; h = (1 / 25); }; class MainBackground: Life_RscText { colorBackground[] = {0, 0, 0, 0.7}; idc = -1; x = 0.1; y = 0.2 + (11 / 250); w = 0.64; h = 0.3 - (5 / 250); }; }; class controls { class Title: Life_RscTitle { colorBackground[] = {0, 0, 0, 0}; idc = -1; text = "$STR_News_DialogTitle"; x = 0.1; y = 0.2; w = 0.6; h = (1 / 25); }; class MsgHeader: Life_RscTitle { colorBackground[] = {0, 0, 0, 0}; idc = -1; text = "$STR_News_MsgHeader"; x = 0.1; y = 0.25; w = 0.6; h = (1 / 25); }; class MsgHeaderEdit: Life_RscEdit { idc = 100101; text = ""; sizeEx = 0.035; x = 0.11; y = 0.3; w = 0.62; h = 0.03; }; class MsgText: Life_RscTitle { colorBackground[] = {0, 0, 0, 0}; idc = -1; text = "$STR_News_MsgContent"; x = 0.1; y = 0.33; w = 0.6; h = (1 /25); }; class MsgContentEdit: Life_RscEdit { idc = 100102; text = ""; sizeEx = 0.035; x = 0.11; y = 0.38; w = 0.62; h = 0.03; }; class MessageInfo: Life_RscStructuredText { colorBackground[] = {0, 0, 0, 0}; idc = 100103; text = ""; x = 0.1; y = 0.43; w = 0.6; h = .275; }; class ConfirmButtonKey: Life_RscButtonMenu { idc = 100104; text = "$STR_News_Broadcast"; x = (6.25 / 40) + (4.2 / 40) + (1 / 250 / (safezoneW / safezoneH)); y = 0.51 + (1 / 50); w = (10.5 / 40); h = (1 / 25); }; class CloseButtonKey: Life_RscButtonMenu { idc = -1; text = "$STR_Global_Close"; onButtonClick = "closeDialog 0;"; x = -0.06 + (6.25 / 40) + (1 / 250 / (safezoneW / safezoneH)); y = 0.51 + (1 / 50); w = (6.25 / 40); h = (1 / 25); }; }; };
- Öffnet eure MasterHandler.hpp (zu finden im dialog Ordner) und fügt folgenden Eintrag ein
-
* Öffnet eure player_inv.hpp (zu finden im dialog Ordner) und fügt unter class ButtonAdminMenu folgendes ein
- Öffnet eure settings.hpp und fügt folgendes ein:
unter class RevealNearestHeader
unter class RevealONOFF
-
* Öffnet eure fn_p_openMenu.sqf (zu finden im Ordner core\pmenu) und fügt sowohl bei case civilian als auch bei case independent folgendes ein (falls nicht vorhanden, cases neu erstellen!)
- Öffnet eure stringtable.xml und fügt folgendes Package ein (wichtig: es muss über oder unter einem anderen Package sein, abber dennoch im Project "Altis Life RPG" - am besten vo das erste Package packen) 4.4 Stringtable Download mit Einträgen: stringtable4.4.txtXML
Alles anzeigen<Package name="News_Strings"> <Key ID="STR_News_AddAction"> <Original>News Station Broadcast</Original> </Key> <Key ID="STR_News_DialogTitle"> <Original>Channel 7 News Station</Original> </Key> <Key ID="STR_News_MsgHeader"> <Original>Message Heading:</Original> </Key> <Key ID="STR_News_MsgContent"> <Original>Message Content:</Original> </Key> <Key ID="STR_News_Broadcast"> <Original>Broadcast Message</Original> </Key> <Key ID="STR_News_StructuredText"> <Original>Broadcast Cost: %1<br />Next Broadcast Available: %2</Original> </Key> <Key ID="STR_News_HeaderLength"> <Original>The header cannot be over %1 characters</Original> </Key> <Key ID="STR_News_UnsupportedCharacter"> <Original>You've entered an unsupported character!</Original> </Key> <Key ID="STR_News_Now"> <Original>Now</Original> </Key> <Key ID="STR_News_NotEnough"> <Original>You need $%1 to send a broadcast!</Original> </Key> <Key ID="STR_News_BroadcastedBy"> <Original><t size='2'>%1</t><br />Broadcasted by: %2</Original> </Key> <Key ID="STR_News_BroadcastRebel"> <Original>Force Broadcast</Original> </Key> <Key ID="STR_News_Forced"> <Original>Ein Studio von AAN News wird von bewaffneten Räubern überfallen!</Original> </Key> </Package>
- Setzt im Editor einen neuen NPC (z.B. einen Reporter) mit folgender initC
this enableSimulation false; this allowDamage false; this addAction[localize"STR_News_AddAction",life_fnc_newsBroadcast,"",1.5,false,false,"",'isNull objectParent player && player distance _target < 4']; this addAction[localize"STR_NOTF_ATM",life_fnc_atmMenu,"",0,false,false,"",' isNull objectParent player && player distance _target < 4 '];
- Sofern ihr Altis Life 4.0 nutzt nun noch eine Datei script_macros.hpp im Hauptverzeichnis der Mission erstellen mit folgendem InhaltCSS
Alles anzeigen/* System Wide Stuff */ #define SYSTEM_TAG "life" #define ITEM_TAG format["%1%2",SYSTEM_TAG,"item_"] #define CASH life_cash #define BANK life_atmbank #define GANG_FUNDS group player getVariable ["gang_bank",0]; //RemoteExec Macros #define RSERV 2 //Only server #define RCLIENT -2 //Except server #define RANY 0 //Global //Scripting Macros #define CONST(var1,var2) var1 = compileFinal (if (var2 isEqualType "") then {var2} else {str(var2)}) #define CONSTVAR(var) var = compileFinal (if (var isEqualType "") then {var} else {str(var)}) #define FETCH_CONST(var) (call var) //Display Macros #define CONTROL(disp,ctrl) ((findDisplay ##disp) displayCtrl ##ctrl) #define CONTROL_DATA(ctrl) (lbData[ctrl,lbCurSel ctrl]) #define CONTROL_DATAI(ctrl,index) ctrl lbData index //System Macros #define LICENSE_VARNAME(varName,flag) format["license_%1_%2",flag,M_CONFIG(getText,"Licenses",varName,"variable")] #define LICENSE_VALUE(varName,flag) missionNamespace getVariable [LICENSE_VARNAME(varName,flag),false] #define ITEM_VARNAME(varName) format["life_inv_%1",M_CONFIG(getText,"VirtualItems",varName,"variable")] #define ITEM_VALUE(varName) missionNamespace getVariable [ITEM_VARNAME(varName),0] #define ITEM_ILLEGAL(varName) M_CONFIG(getNumber,"VirtualItems",varName,"illegal") #define ITEM_SELLPRICE(varName) M_CONFIG(getNumber,"VirtualItems",varName,"sellPrice") #define ITEM_BUYPRICE(varName) M_CONFIG(getNumber,"VirtualItems",varName,"buyPrice") #define ITEM_NAME(varName) M_CONFIG(getText,"VirtualItems",varName,"displayName") //Condition Macros #define KINDOF_ARRAY(a,b) [##a,##b] call {_veh = _this select 0;_types = _this select 1;_res = false; {if (_veh isKindOf _x) exitWith { _res = true };} forEach _types;_res} //Config Macros #define FETCH_CONFIG(TYPE,CFG,SECTION,CLASS,ENTRY) TYPE(configFile >> CFG >> SECTION >> CLASS >> ENTRY) #define FETCH_CONFIG2(TYPE,CFG,CLASS,ENTRY) TYPE(configFile >> CFG >> CLASS >> ENTRY) #define FETCH_CONFIG3(TYPE,CFG,SECTION,CLASS,ENTRY,SUB) TYPE(configFile >> CFG >> SECTION >> CLASS >> ENTRY >> SUB) #define FETCH_CONFIG4(TYPE,CFG,SECTION,CLASS,ENTRY,SUB,SUB2) TYPE(configFile >> CFG >> SECTION >> CLASS >> ENTRY >> SUB >> SUB2) #define M_CONFIG(TYPE,CFG,CLASS,ENTRY) TYPE(missionConfigFile >> CFG >> CLASS >> ENTRY) #define BASE_CONFIG(CFG,CLASS) inheritsFrom(configFile >> CFG >> CLASS) #define LIFE_SETTINGS(TYPE,SETTING) TYPE(missionConfigFile >> "Life_Settings" >> SETTING) //UI Macros #define LIFEdisplay (uiNamespace getVariable ["playerHUD",displayNull]) #define LIFEctrl(ctrl) ((uiNamespace getVariable ["playerHUD",displayNull]) displayCtrl ctrl) //SpyGlass Macros #define SPYGLASS_END \ vehicle player setVelocity[1e10,1e14,1e18]; \ sleep 3; \ preProcessFile "SpyGlass\endoftheline.sqf"; \ sleep 2.5; \ failMission "SpyGlass";
Sieht Ingame dann etwa so aus:
Der Dialog
Die Nachricht
Fertig!
Das war's schon!
Solltet ihr Wünsche, Anregungen oder Verbesserungsvorschläge haben, lasst es mich gerne wissen!
Ich wünsche euch Viel Spaß mit dem Tutorial