Merged branch release into master

This commit is contained in:
Glowbal 2016-09-13 21:28:22 +02:00
commit 65cdf200fb
45 changed files with 388 additions and 109 deletions

View File

@ -4,7 +4,7 @@
<p align="center">
<a href="https://github.com/acemod/ACE3/releases/latest">
<img src="https://img.shields.io/badge/Version-3.6.2-blue.svg?style=flat-square" alt="ACE3 Version">
<img src="https://img.shields.io/badge/Version-3.7.0-blue.svg?style=flat-square" alt="ACE3 Version">
</a>
<a href="https://github.com/acemod/ACE3/issues">
<img src="https://img.shields.io/github/issues-raw/acemod/ACE3.svg?style=flat-square&label=Issues" alt="ACE3 Issues">

View File

@ -7,7 +7,7 @@ class CfgPatches {
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_common"};
author = CSTRING(ACETeam);
author = ECSTRING(common,ACETeam);
authors[] = {"BaerMitUmlaut"};
url = ECSTRING(main,URL);
VERSION_CONFIG;

View File

@ -9,7 +9,7 @@
* None
*/
#include "script_component.hpp"
if (isNull ACE_player) exitWith {}; // Map intros
if (!alive ACE_player) exitWith {}; // Dead people don't breath, Will also handle null (Map intros)
private _currentWork = REE;
private _currentSpeed = (vectorMagnitude (velocity ACE_player)) min 6;

View File

@ -58,7 +58,7 @@ class CfgVehicles {
class ACE_Actions {
class GVAR(pickUp) {
displayName = CSTRING(PickUp);
condition = QUOTE(_player call FUNC(canPrepare));
condition = QUOTE([ARR_2(_player,true)] call FUNC(canPrepare));
statement = QUOTE(_this call FUNC(pickUp));
distance = 1.8; // Requires >1.7 to work when standing with weapon on back
icon = "\a3\ui_f\data\igui\cfg\actions\obsolete\ui_action_takemine_ca.paa";

View File

@ -83,6 +83,13 @@ GVAR(ammoMagLookup) = call CBA_fnc_createNamespace;
// Fired XEH
[QGVAR(throwFiredXEH), FUNC(throwFiredXEH)] call CBA_fnc_addEventHandler;
// Set last thrown time on Vanilla Throwing and Advanced Throwing
["ace_firedPlayer", {
if (_weapon == "Throw") then {
_unit setVariable [QGVAR(lastThrownTime), CBA_missionTime];
};
}] call CBA_fnc_addEventHandler;
// Display handlers
["KeyDown", {_this call FUNC(onKeyDown)}] call CBA_fnc_addDisplayHandler;

View File

@ -4,6 +4,7 @@
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Ignore Last Thrown Time <BOOL> (default: false)
*
* Return Value:
* Can Prepare <BOOL>
@ -15,14 +16,19 @@
*/
#include "script_component.hpp"
params ["_unit"];
params ["_unit", ["_ignoreLastThrownTime", false]];
// Don't delay when picking up
if (_ignoreLastThrownTime) then {
_unit setVariable [QGVAR(lastThrownTime), -1];
};
GVAR(enabled) &&
#ifndef DEBUG_MODE_FULL
{_unit getVariable [QGVAR(lastThrownTime), CBA_missionTime - 3] < CBA_missionTime - 2} && // Prevent throwing in quick succession
#else
#ifdef ALLOW_QUICK_THROW
{true} &&
#else
{_unit getVariable [QGVAR(lastThrownTime), CBA_missionTime - 3] < CBA_missionTime - 2} && // Prevent throwing in quick succession
#endif
{!(call EFUNC(common,isFeatureCameraActive))} &&

View File

@ -15,7 +15,7 @@
*/
#include "script_component.hpp"
if (dialog || {!(ACE_player getVariable [QGVAR(inHand), false])} || {!([ACE_player] call FUNC(canPrepare))}) exitWith {
if (dialog || {!(ACE_player getVariable [QGVAR(inHand), false])} || {!([ACE_player, true] call FUNC(canPrepare))}) exitWith {
[ACE_player, "In dialog or no throwable in hand or cannot prepare throwable"] call FUNC(exitThrowMode);
};
@ -63,7 +63,7 @@ private _power = linearConversion [0, 180, _phi - 30, 1, 0.3, true];
ACE_player setVariable [QGVAR(throwSpeed), _throwSpeed * _power];
#ifdef DEBUG_MODE_FULL
hintSilent format ["Heading: %1\nPower: %2\nSpeed: %3\nThrowMag: %4", _phi, _power, _throwSpeed * _power, _throwableMag];
hintSilent format ["Heading: %1\nPower: %2\nSpeed: %3\nThrowMag: %4\nMuzzle: %5", _phi, _power, _throwSpeed * _power, _throwableMag, ACE_player getVariable [QGVAR(activeMuzzle), ""]];
#endif
private _throwableType = getText (configFile >> "CfgMagazines" >> _throwableMag >> "ammo");
@ -71,16 +71,25 @@ private _throwableType = getText (configFile >> "CfgMagazines" >> _throwableMag
if (!([ACE_player] call FUNC(canThrow)) && {!_primed}) exitWith {
if (!isNull _activeThrowable) then {
deleteVehicle _activeThrowable;
// Restore muzzle ammo (setAmmo 1 has no impact if no appliccable throwable in inventory)
ACE_player setAmmo [ACE_player getVariable [QGVAR(activeMuzzle), ""], 1];
};
};
if (isNull _activeThrowable || {(_throwableType != typeOf _activeThrowable) && {!_primed}}) then {
if (!isNull _activeThrowable) then {
deleteVehicle _activeThrowable;
// Restore muzzle ammo (setAmmo 1 has no impact if no appliccable throwable in inventory)
ACE_player setAmmo [ACE_player getVariable [QGVAR(activeMuzzle), ""], 1];
};
_activeThrowable = _throwableType createVehicleLocal [0, 0, 0];
_activeThrowable enableSimulation false;
ACE_player setVariable [QGVAR(activeThrowable), _activeThrowable];
// Set muzzle ammo to 0 to block vanilla throwing (can only be 0 or 1)
private _muzzle = _throwableMag call FUNC(getMuzzle);
ACE_player setAmmo [_muzzle, 0];
ACE_player setVariable [QGVAR(activeMuzzle), _muzzle];
};
// Exit in case of explosion in hand

View File

@ -25,13 +25,22 @@ if !(_unit getVariable [QGVAR(inHand), false]) exitWith {};
systemChat format ["Exit Throw Mode: %1", _reason];
#endif
private _activeThrowable = _unit getVariable [QGVAR(activeThrowable), objNull];
if !(_unit getVariable [QGVAR(primed), false]) then {
deleteVehicle (_unit getVariable [QGVAR(activeThrowable), objNull]);
deleteVehicle _activeThrowable;
} else {
_unit setVariable [QGVAR(lastThrownTime), CBA_missionTime];
// Fix floating for throwables without proper physics (eg. IR Grenade)
_activeThrowable setVelocity [0, 0, -0.1];
};
// Restore muzzle ammo (setAmmo 1 has no impact if no appliccable throwable in inventory)
_unit setAmmo [_unit getVariable [QGVAR(activeMuzzle), ""], 1];
_unit setVariable [QGVAR(inHand), false];
_unit setVariable [QGVAR(primed), false];
_unit setVariable [QGVAR(activeThrowable), objNull];
_unit setVariable [QGVAR(activeMuzzle), ""];
_unit setVariable [QGVAR(throwType), THROW_TYPE_DEFAULT];
_unit setVariable [QGVAR(throwSpeed), THROW_SPEED_DEFAULT];
_unit setVariable [QGVAR(dropMode), false];

View File

@ -23,12 +23,15 @@ if (_unit getVariable [QGVAR(inHand), false]) exitWith {
TRACE_1("inHand",_unit);
if (!(_unit getVariable [QGVAR(primed), false])) then {
TRACE_1("not primed",_unit);
// Restore muzzle ammo (setAmmo 1 has no impact if no appliccable throwable in inventory)
// selectNextGrenade relies on muzzles array (setAmmo 0 removes the muzzle from the array and current can't be found, cycles between 0 and 1 muzzles)
ACE_player setAmmo [ACE_player getVariable [QGVAR(activeMuzzle), ""], 1];
[_unit] call EFUNC(weaponselect,selectNextGrenade);
};
};
// Try selecting next throwable if none currently selected
if ((isNull (_unit getVariable [QGVAR(activeThrowable), objNull])) && {(currentThrowable _unit) isEqualTo []} && {!([_unit] call EFUNC(weaponselect,selectNextGrenade))}) exitWith {
if (isNull (_unit getVariable [QGVAR(activeThrowable), objNull]) && {(currentThrowable _unit) isEqualTo []} && {!([_unit] call EFUNC(weaponselect,selectNextGrenade))}) exitWith {
TRACE_1("no throwables",_unit);
};

View File

@ -26,7 +26,10 @@ private _throwableMag = (currentThrowable _unit) select 0;
_unit removeItem _throwableMag;
private _throwableType = getText (configFile >> "CfgMagazines" >> _throwableMag >> "ammo");
private _muzzle = _throwableMag call FUNC(getMuzzle);
private _muzzle = _unit getVariable [QGVAR(activeMuzzle), ""];
// Set muzzle ammo to 0 to block vanilla throwing (can only be 0 or 1), removeItem above resets it
_unit setAmmo [_muzzle, 0];
// Create actual throwable globally
private _activeThrowableOld = _unit getVariable [QGVAR(activeThrowable), objNull];

View File

@ -22,15 +22,19 @@
// isNull is necessarry to prevent rare error when ending mission with interact key down
if (EGVAR(interact_menu,keyDown) && {!isNull ACE_player}) then {
// Rescan when player moved >5 meters from last pos, nearObjects is costly
// Rescan when player moved >5 meters from last pos, nearObjects can be costly with a lot of objects around
if ((getPosASL ACE_player) distance _setPosition > 5) then {
// IR throwbles inherit from GrenadeCore, others from GrenadeHand, IR Chemlights are special snowflakes
// Grenades inherit from GrenadeHand, IR throwbles from IRStrobeBase, IR Chemlights are special snowflakes
// nearEntities does not see throwables
_nearThrowables = ACE_player nearObjects ["GrenadeHand", PICK_UP_DISTANCE];
_nearThrowables append (ACE_player nearObjects ["GrenadeCore", PICK_UP_DISTANCE]);
_nearThrowables append (ACE_player nearObjects ["IRStrobeBase", PICK_UP_DISTANCE]);
_nearThrowables append (ACE_player nearObjects ["ACE_Chemlight_IR_Dummy", PICK_UP_DISTANCE]);
{
if (!(_x in _throwablesHelped) && {GVAR(enablePickUpAttached) || {!GVAR(enablePickUpAttached) && {isNull (attachedTo _x)}}}) then {
if (!(_x in _throwablesHelped) &&
{!(_x isKindOf "SmokeShellArty")} && {!(_x isKindOf "G_40mm_Smoke")} && // All smokes inherit from "GrenadeHand" >> "SmokeShell"
{GVAR(enablePickUpAttached) || {!GVAR(enablePickUpAttached) && {isNull (attachedTo _x)}}}
) then {
TRACE_2("Making PickUp Helper",_x,typeOf _x);
private _pickUpHelper = QGVAR(pickUpHelper) createVehicleLocal [0, 0, 0];

View File

@ -54,8 +54,6 @@ if (!(_unit getVariable [QGVAR(primed), false])) then {
_activeThrowable setVelocity _newVelocity;
};
_unit setVariable [QGVAR(lastThrownTime), CBA_missionTime];
// Invoke listenable event
["ace_throwableThrown", [_unit, _activeThrowable]] call CBA_fnc_localEvent;
}, [

View File

@ -3,6 +3,7 @@
#include "\z\ace\addons\main\script_mod.hpp"
// #define DRAW_THROW_PATH
// #define ALLOW_QUICK_THROW
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define CBA_DEBUG_SYNCHRONOUS

View File

@ -127,6 +127,33 @@ class CfgWeapons {
/* Katiba */
class arifle_katiba_Base_F: Rifle_Base_F {};
/* SPAR */
class arifle_SPAR_01_base_F: Rifle_Base_F {
magazines[] = {
"30Rnd_556x45_Stanag",
"30Rnd_556x45_Stanag_green",
"30Rnd_556x45_Stanag_red",
"30Rnd_556x45_Stanag_Tracer_Red",
"30Rnd_556x45_Stanag_Tracer_Green",
"30Rnd_556x45_Stanag_Tracer_Yellow",
"ACE_30Rnd_556x45_Stanag_M995_AP_mag",
"ACE_30Rnd_556x45_Stanag_Mk262_mag",
"ACE_30Rnd_556x45_Stanag_Mk318_mag",
"ACE_30Rnd_556x45_Stanag_Tracer_Dim"
};
};
class arifle_SPAR_03_base_F: Rifle_Base_F {
magazines[] = {
"20Rnd_762x51_Mag",
"ACE_20Rnd_762x51_Mag_Tracer",
"ACE_20Rnd_762x51_Mag_Tracer_Dim",
"ACE_20Rnd_762x51_Mk316_Mod_0_Mag",
"ACE_20Rnd_762x51_M118LR_Mag",
"ACE_20Rnd_762x51_Mk319_Mod_0_Mag",
"ACE_20Rnd_762x51_M993_AP_Mag",
"ACE_20Rnd_762x51_Mag_SD"
};
};
/* Other */
class LMG_Mk200_F: Rifle_Long_Base_F {

View File

@ -31,7 +31,7 @@ private _cargoSpace = [_vehicle] call FUNC(getCargoSpaceLeft);
private _itemSize = [_item] call FUNC(getSizeItem);
_vehicle setVariable [QGVAR(space), (_cargoSpace + _itemSize), true];
(boundingBoxReal q2) params ["_bb1", "_bb2"];
(boundingBoxReal _vehicle) params ["_bb1", "_bb2"];
private _distBehind = ((_bb1 select 1) min (_bb2 select 1)) - 3; // 3 meters behind max bounding box
TRACE_1("",_distBehind);
private _posBehindVehicleAGL = _vehicle modelToWorld [0, _distBehind, -1];

View File

@ -27,8 +27,8 @@ if (isNull _projectile) then {
if (local _unit) then {
if ([_ammo] call FUNC(isIRClass)) then {
// Handle advancedThrowing:
if ((ace_player getVariable [QEGVAR(advancedThrowing,activeThrowable), objNull]) == _projectile) then {
// Handle Advanced Throwing
if ((ACE_player getVariable [QEGVAR(advanced_throwing,activeThrowable), objNull]) == _projectile) then {
[_projectile, _ammo, true] call FUNC(throwIR); // direct call if we are priming with adv throw
} else {
[{_this call FUNC(throwIR)}, [_projectile, _ammo]] call CBA_fnc_execNextFrame;

View File

@ -32,5 +32,5 @@ _dummy setPosATL _pos;
_dummy setVelocity _velocity;
if (_replaceAdvThrowable) then {
ace_player setVariable [QEGVAR(advancedThrowing,activeThrowable), _dummy];
ACE_player setVariable [QEGVAR(advanced_throwing,activeThrowable), _dummy];
};

View File

@ -14,6 +14,9 @@ if (!hasInterface) exitWith {};
};
private _code = compile format [QUOTE('%1' call FUNC(playSignal)), _signalName];
if (_currentName == "Stop") then {
_code = compile format [QUOTE('%1' call FUNC(playSignal)), "BIgestureFreeze"];
};
TRACE_4("Adding KeyBind",_currentName,_signalName,_code,_key);

View File

@ -15,6 +15,8 @@ GVAR(flashbangPPEffectCC) ppEffectForceInNVG true;
if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false};
// Conditions: specific
if (!([ACE_player] call CBA_fnc_canUseWeapon)) exitWith {false};
// Don't change mode or show hint if advanced throwing is active
if (ACE_player getVariable [QEGVAR(advanced_throwing,inHand), false]) exitWith {false};
// Statement
[] call FUNC(nextMode);

View File

@ -61,6 +61,7 @@ if (getNumber (_config >> QGVAR(incendiary)) == 1) then {
// handle throw modes
if (_unit != ACE_player) exitWith {};
if (_unit getVariable [QEGVAR(advanced_throwing,primed), false]) exitWith {LOG("advanced_throwing throw");};
private _mode = missionNamespace getVariable [QGVAR(currentThrowMode), 0];

View File

@ -4,16 +4,16 @@
#define PREFIX ace
#define MAJOR 3
#define MINOR 6
#define PATCHLVL 2
#define BUILD 0
#define MINOR 7
#define PATCHLVL 0
#define BUILD 6
#define VERSION MAJOR.MINOR.PATCHLVL.BUILD
#define VERSION_AR MAJOR,MINOR,PATCHLVL,BUILD
// MINIMAL required version for the Mod. Components can specify others..
#define REQUIRED_VERSION 1.62
#define REQUIRED_CBA_VERSION {2,4,1}
#define REQUIRED_CBA_VERSION {3,0,0}
#ifdef COMPONENT_BEAUTIFIED
#define COMPONENT_NAME QUOTE(ACE3 - COMPONENT_BEAUTIFIED)

View File

@ -57,7 +57,7 @@ private _debugCode = {
[{diag_frameno > (_this select 0)}, _debugCode, [_checkAtFrame, _unit, _startDmg, _damageToAdd, _partNumber]] call CBA_fnc_waitUntilAndExecute;
#endif
private _return = [_unit, _selection, (_currentDamage + _damageToAdd), _unit, _typeOfDamage, _hitpointIndex] call FUNC(handleDamage);
private _return = [_unit, _selection, (_currentDamage + _damageToAdd), _unit, _typeOfDamage, _hitpointIndex, objNull] call FUNC(handleDamage);
TRACE_1("handleDamage called",_return);
_return

View File

@ -9,6 +9,7 @@
* 3: Shooter <OBJECT>
* 4: Projectile <OBJECT/STRING>
* 5: HitPointIndex (-1 for structural) <NUMBER>
* 6: Shooter <OBJECT>
*
* Return Value:
* Damage To Be Inflicted <NUMBER>

View File

@ -38,7 +38,7 @@ call compile _extensionOutput;
{
_x params ["", "_compareId", "_comparyBodyPartN"];
// Check if we have an id of the given class on the given bodypart already
if (_compareId == _toAddClassID && {_comparyBodyPartN2 == _bodyPartNToAdd}) exitWith {
if (_compareId == _toAddClassID && {_comparyBodyPartN == _bodyPartNToAdd}) exitWith {
_foundIndex = _forEachIndex;
};
} forEach _openWounds;

View File

@ -13,7 +13,7 @@
#include "script_component.hpp"
// Player will have to do this manually of course
if (isPlayer _this) exitWith {};
if ([_this] call EFUNC(common,isPlayer)) exitWith {};
// Can't heal self when unconscious
if (_this getVariable ["ACE_isUnconscious", false]) exitWith {};
// Check if we're still treating

View File

@ -46,12 +46,11 @@ if (_target getVariable [QEGVAR(medical,hasPain), false]) then {
};
_totalIvVolume = 0;
private _bloodBags = _target getVariable [QEGVAR(medical,ivBags), []];
{
private _value = _target getVariable _x;
if (!isNil "_value") then {
_totalIvVolume = _totalIvVolume + (_target getVariable [_x, 0]);
};
} count EGVAR(medical,IVBags);
_x params ["_bagVolumeRemaining"];
_totalIvVolume = _totalIvVolume + _bagVolumeRemaining;
} foreach _bloodBags;
if (_totalIvVolume >= 1) then {
_genericMessages pushBack [format [localize ELSTRING(medical,receivingIvVolume), floor _totalIvVolume], [1, 1, 1, 1]];

View File

@ -31,13 +31,6 @@
exceptions[] = {"isNotInside"}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
class GVAR(Connect) { \
displayName = CSTRING(Connect); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canConnectNozzle)); \
statement = QUOTE([ARR_2(_player,_target)] call DFUNC(connectNozzle)); \
exceptions[] = {"isNotInside"}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
class GVAR(Return) { \
displayName = CSTRING(Return); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canReturnNozzle)); \
@ -77,7 +70,7 @@
class GVAR(PickUpNozzle) { \
displayName = CSTRING(TakeNozzle); \
condition = QUOTE([ARR_2(_player,_target)] call FUNC(canTakeNozzle)); \
statement = QUOTE([ARR_3(_player,objNull,_target)] call FUNC(TakeNozzle)); \
statement = QUOTE([ARR_3(_player,objNull,_target)] call FUNC(takeNozzle)); \
exceptions[] = {"isNotInside"}; \
icon = QPATHTOF(ui\icon_refuel_interact.paa); \
}; \
@ -322,7 +315,7 @@ class CfgVehicles {
class I_G_Van_01_fuel_F: Van_01_fuel_base_F {
transportFuel = 0; //1k
};
class Tank_F: Tank {
GVAR(fuelCapacity) = 1200;
};

View File

@ -28,4 +28,4 @@ if (_target isKindOf "AllVehicles") then {
!(isNull _nozzle ||
{_engine} ||
{(_target distance _unit) > REFUEL_ACTION_DISTANCE} ||
{!isNull (_target getVariable [QGVAR(nozzle), objNull])}) // TODO verify cant connect multiple fuel lines
{!isNull (_target getVariable [QGVAR(nozzle), objNull])})

View File

@ -22,6 +22,7 @@ if (isNull _unit ||
{isNull _nozzle} ||
{!(_unit isKindOf "CAManBase")} ||
{!local _unit} ||
{!isNull (_unit getVariable [QGVAR(nozzle), objNull])} ||
{(_nozzle distance _unit) > REFUEL_ACTION_DISTANCE}) exitWith {false};
private _sink = _nozzle getVariable [QGVAR(sink), objNull];

View File

@ -18,6 +18,8 @@
params [["_unit", objNull, [objNull]], ["_target", objNull, [objNull]]];
private _nozzle = _unit getVariable QGVAR(nozzle);
private _nozzle = _unit getVariable [QGVAR(nozzle), objNull];
(_this call FUNC(canConnectNozzle)) && {_target == (_nozzle getVariable [QGVAR(source), objNull])}
(!isNull _nozzle) &&
{_target distance _unit < REFUEL_ACTION_DISTANCE} &&
{_target == (_nozzle getVariable [QGVAR(source), objNull])}

View File

@ -22,6 +22,7 @@ if (isNull _unit ||
{!(_unit isKindOf "CAManBase")} ||
{!local _unit} ||
{!alive _target} ||
{!isNull (_unit getVariable [QGVAR(nozzle), objNull])} ||
{(_target distance _unit) > REFUEL_ACTION_DISTANCE}) exitWith {false};
!(_target getVariable [QGVAR(isConnected), false]) && {!(_unit getVariable [QGVAR(isRefueling), false])}

View File

@ -72,6 +72,8 @@ if (!hasInterface) exitWith {};
["ACE3 Weapons", QGVAR(SelectGrenadeFrag), localize LSTRING(SelectGrenadeFrag), {
// Conditions: canInteract
if !([ACE_player, ACE_player, ["isNotInside", "isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false};
// Don't change mode or show hint if advanced throwing is active
if (ACE_player getVariable [QEGVAR(advanced_throwing,inHand), false]) exitWith {false};
// Statement
[ACE_player, 1] call FUNC(selectNextGrenade);
@ -83,6 +85,8 @@ if (!hasInterface) exitWith {};
["ACE3 Weapons", QGVAR(SelectGrenadeOther), localize LSTRING(SelectGrenadeOther), {
// Conditions: canInteract
if !([ACE_player, ACE_player, ["isNotInside", "isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false};
// Don't change mode or show hint if advanced throwing is active
if (ACE_player getVariable [QEGVAR(advanced_throwing,inHand), false]) exitWith {false};
// Statement
[ACE_player, 2] call FUNC(selectNextGrenade);

View File

@ -4,7 +4,7 @@
<p align="center">
<a href="https://github.com/acemod/ACE3/releases">
<img src="https://img.shields.io/badge/Version-3.6.2-blue.svg?style=flat-square" alt="ACE3 Version">
<img src="https://img.shields.io/badge/Version-3.7.0-blue.svg?style=flat-square" alt="ACE3 Version">
</a>
<a href="https://github.com/acemod/ACE3/issues">
<img src="https://img.shields.io/github/issues-raw/acemod/ACE3.svg?style=flat-square&label=Issues" alt="ACE3 Fehlermeldungen">

View File

@ -3,7 +3,7 @@
</p>
<p align="center">
<a href="https://github.com/acemod/ACE3/releases">
<img src="https://img.shields.io/badge/Wersja-3.6.2-blue.svg?style=flat-square" alt="ACE3 Wersja">
<img src="https://img.shields.io/badge/Wersja-3.7.0-blue.svg?style=flat-square" alt="ACE3 Wersja">
</a>
<a href="https://github.com/acemod/ACE3/issues">
<img src="https://img.shields.io/github/issues-raw/acemod/ACE3.svg?label=Zagadnienia&style=flat-square" alt="ACE3 Zagadnienia">

View File

@ -1,8 +1,8 @@
name = "Advanced Combat Environment 3.6.2";
name = "Advanced Combat Environment 3.7.0";
picture = "logo_ace3_ca.paa";
actionName = "GitHub";
action = "https://github.com/acemod/ACE3";
description = "ACE3 - Version 3.6.2";
description = "ACE3 - Version 3.7.0";
logo = "logo_ace3_ca.paa";
logoOver = "logo_ace3_ca.paa";
tooltip = "ACE3";

View File

@ -134,20 +134,24 @@ Author:
#define DEBUG_MODE_MINIMAL
#endif
#ifdef THIS_FILE
#define THIS_FILE_ 'THIS_FILE'
#define LOG_SYS_FORMAT(LEVEL,MESSAGE) format ['[%1] (%2) %3: %4', toUpper 'PREFIX', 'COMPONENT', LEVEL, MESSAGE]
#ifdef DEBUG_SYNCHRONOUS
#define LOG_SYS(LEVEL,MESSAGE) diag_log text LOG_SYS_FORMAT(LEVEL,MESSAGE)
#else
#define THIS_FILE_ __FILE__
#define LOG_SYS(LEVEL,MESSAGE) LOG_SYS_FORMAT(LEVEL,MESSAGE) call CBA_fnc_log
#endif
#define LOG_SYS_FILELINENUMBERS(LEVEL,MESSAGE) LOG_SYS(LEVEL,format [ARR_4('%1 File: %2 Line: %3',MESSAGE,__FILE__,__LINE__ + 1)])
/* -------------------------------------------
Macro: LOG()
Log a timestamped message into the RPT log.
Log a debug message into the RPT log.
Only run if <DEBUG_MODE_FULL> or higher is defined.
Only run if <DEBUG_MODE_FULL> is defined.
Parameters:
MESSAGE - Message to record [String]
MESSAGE - Message to record <STRING>
Example:
(begin example)
@ -158,19 +162,64 @@ Author:
Spooner
------------------------------------------- */
#ifdef DEBUG_MODE_FULL
#define LOG(MESSAGE) [THIS_FILE_, __LINE__, MESSAGE] call CBA_fnc_log
#define LOG(MESSAGE) LOG_SYS_FILELINENUMBERS('LOG',MESSAGE)
#define LOG_1(MESSAGE,ARG1) LOG(FORMAT_1(MESSAGE,ARG1))
#define LOG_2(MESSAGE,ARG1,ARG2) LOG(FORMAT_2(MESSAGE,ARG1,ARG2))
#define LOG_3(MESSAGE,ARG1,ARG2,ARG3) LOG(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
#define LOG_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) LOG(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
#define LOG_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) LOG(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
#define LOG_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) LOG(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
#define LOG_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) LOG(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
#define LOG_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) LOG(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
#else
#define LOG(MESSAGE) /* disabled */
#define LOG_1(MESSAGE,ARG1) /* disabled */
#define LOG_2(MESSAGE,ARG1,ARG2) /* disabled */
#define LOG_3(MESSAGE,ARG1,ARG2,ARG3) /* disabled */
#define LOG_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) /* disabled */
#define LOG_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) /* disabled */
#define LOG_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) /* disabled */
#define LOG_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) /* disabled */
#define LOG_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) /* disabled */
#endif
/* -------------------------------------------
Macro: INFO()
Record a message without file and line number in the RPT log.
Parameters:
MESSAGE - Message to record <STRING>
Example:
(begin example)
INFO("Mod X is loaded, do Y");
(end)
Author:
commy2
------------------------------------------- */
#define INFO(MESSAGE) LOG_SYS('INFO',MESSAGE)
#define INFO_1(MESSAGE,ARG1) INFO(FORMAT_1(MESSAGE,ARG1))
#define INFO_2(MESSAGE,ARG1,ARG2) INFO(FORMAT_2(MESSAGE,ARG1,ARG2))
#define INFO_3(MESSAGE,ARG1,ARG2,ARG3) INFO(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
#define INFO_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) INFO(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
#define INFO_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) INFO(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
#define INFO_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) INFO(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
#define INFO_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) INFO(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
#define INFO_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) INFO(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
/* -------------------------------------------
Macro: WARNING()
Record a timestamped, non-critical error in the RPT log.
Record a non-critical error in the RPT log.
Only run if <DEBUG_MODE_NORMAL> or higher is defined.
Parameters:
MESSAGE - Message to record [String]
MESSAGE - Message to record <STRING>
Example:
(begin example)
@ -181,21 +230,37 @@ Author:
Spooner
------------------------------------------- */
#ifdef DEBUG_MODE_NORMAL
#define WARNING(MESSAGE) [THIS_FILE_, __LINE__, ('WARNING: ' + MESSAGE)] call CBA_fnc_log
#define WARNING(MESSAGE) LOG_SYS_FILELINENUMBERS('WARNING',MESSAGE)
#define WARNING_1(MESSAGE,ARG1) WARNING(FORMAT_1(MESSAGE,ARG1))
#define WARNING_2(MESSAGE,ARG1,ARG2) WARNING(FORMAT_2(MESSAGE,ARG1,ARG2))
#define WARNING_3(MESSAGE,ARG1,ARG2,ARG3) WARNING(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
#define WARNING_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) WARNING(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
#define WARNING_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) WARNING(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
#define WARNING_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) WARNING(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
#define WARNING_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) WARNING(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
#define WARNING_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) WARNING(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
#else
#define WARNING(MESSAGE) /* disabled */
#define WARNING_1(MESSAGE,ARG1) /* disabled */
#define WARNING_2(MESSAGE,ARG1,ARG2) /* disabled */
#define WARNING_3(MESSAGE,ARG1,ARG2,ARG3) /* disabled */
#define WARNING_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) /* disabled */
#define WARNING_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) /* disabled */
#define WARNING_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) /* disabled */
#define WARNING_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) /* disabled */
#define WARNING_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) /* disabled */
#endif
/* -------------------------------------------
Macro: ERROR()
Record a timestamped, critical error in the RPT log.
The heading is "ERROR" (use <ERROR_WITH_TITLE()> for a specific title).
TODO: Popup an error dialog & throw an exception.
Record a critical error in the RPT log.
Parameters:
MESSAGE - Message to record [String]
MESSAGE - Message to record <STRING>
Example:
(begin example)
@ -205,12 +270,19 @@ Example:
Author:
Spooner
------------------------------------------- */
#define ERROR(MESSAGE) \
[THIS_FILE_, __LINE__, "ERROR", MESSAGE] call CBA_fnc_error;
#define ERROR(MESSAGE) ['PREFIX', 'COMPONENT', MESSAGE, nil, __FILE__, __LINE__ + 1] call CBA_fnc_error
#define ERROR_1(MESSAGE,ARG1) ERROR(FORMAT_1(MESSAGE,ARG1))
#define ERROR_2(MESSAGE,ARG1,ARG2) ERROR(FORMAT_2(MESSAGE,ARG1,ARG2))
#define ERROR_3(MESSAGE,ARG1,ARG2,ARG3) ERROR(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
#define ERROR_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) ERROR(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
#define ERROR_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) ERROR(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
#define ERROR_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ERROR(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
#define ERROR_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ERROR(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
#define ERROR_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ERROR(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
/* -------------------------------------------
Macro: ERROR_WITH_TITLE()
Record a timestamped, critical error in the RPT log.
Record a critical error in the RPT log.
The title can be specified (in <ERROR()> the heading is always just "ERROR")
Newlines (\n) in the MESSAGE will be put on separate lines.
@ -218,8 +290,8 @@ Macro: ERROR_WITH_TITLE()
TODO: Popup an error dialog & throw an exception.
Parameters:
TITLE - Title of error message [String]
MESSAGE - Body of error message [String]
TITLE - Title of error message <STRING>
MESSAGE - Body of error message <STRING>
Example:
(begin example)
@ -229,16 +301,15 @@ Example:
Author:
Spooner
------------------------------------------- */
#define ERROR_WITH_TITLE(TITLE,MESSAGE) \
[THIS_FILE_, __LINE__, TITLE, MESSAGE] call CBA_fnc_error;
#define ERROR_WITH_TITLE(TITLE,MESSAGE) ['PREFIX', 'COMPONENT', TITLE, MESSAGE, __FILE__, __LINE__ + 1] call CBA_fnc_error
/* -------------------------------------------
Macro: MESSAGE_WITH_TITLE()
Record a single line, timestamped log entry in the RPT log.
Record a single line in the RPT log.
Parameters:
TITLE - Title of log message [String]
MESSAGE - Body of message [String]
TITLE - Title of log message <STRING>
MESSAGE - Body of message <STRING>
Example:
(begin example)
@ -248,8 +319,7 @@ Example:
Author:
Killswitch
------------------------------------------- */
#define MESSAGE_WITH_TITLE(TITLE,MESSAGE) \
[THIS_FILE_, __LINE__, TITLE + ': ' + (MESSAGE)] call CBA_fnc_log;
#define MESSAGE_WITH_TITLE(TITLE,MESSAGE) LOG_SYS_FILELINENUMBERS(TITLE,MESSAGE)
/* -------------------------------------------
Macro: RETNIL()
@ -327,35 +397,16 @@ Author:
#ifdef DEBUG_MODE_FULL
#define TRACE_1(MESSAGE,A) \
[THIS_FILE_, __LINE__, PFORMAT_1(MESSAGE,A)] call CBA_fnc_log
#define TRACE_2(MESSAGE,A,B) \
[THIS_FILE_, __LINE__, PFORMAT_2(MESSAGE,A,B)] call CBA_fnc_log
#define TRACE_3(MESSAGE,A,B,C) \
[THIS_FILE_, __LINE__, PFORMAT_3(MESSAGE,A,B,C)] call CBA_fnc_log
#define TRACE_4(MESSAGE,A,B,C,D) \
[THIS_FILE_, __LINE__, PFORMAT_4(MESSAGE,A,B,C,D)] call CBA_fnc_log
#define TRACE_5(MESSAGE,A,B,C,D,E) \
[THIS_FILE_, __LINE__, PFORMAT_5(MESSAGE,A,B,C,D,E)] call CBA_fnc_log
#define TRACE_6(MESSAGE,A,B,C,D,E,F) \
[THIS_FILE_, __LINE__, PFORMAT_6(MESSAGE,A,B,C,D,E,F)] call CBA_fnc_log
#define TRACE_7(MESSAGE,A,B,C,D,E,F,G) \
[THIS_FILE_, __LINE__, PFORMAT_7(MESSAGE,A,B,C,D,E,F,G)] call CBA_fnc_log
#define TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) \
[THIS_FILE_, __LINE__, PFORMAT_8(MESSAGE,A,B,C,D,E,F,G,H)] call CBA_fnc_log
#define TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) \
[THIS_FILE_, __LINE__, PFORMAT_9(MESSAGE,A,B,C,D,E,F,G,H,I)] call CBA_fnc_log
#define TRACE_1(MESSAGE,A) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_1(str diag_frameNo + ' ' + (MESSAGE),A))
#define TRACE_2(MESSAGE,A,B) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_2(str diag_frameNo + ' ' + (MESSAGE),A,B))
#define TRACE_3(MESSAGE,A,B,C) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_3(str diag_frameNo + ' ' + (MESSAGE),A,B,C))
#define TRACE_4(MESSAGE,A,B,C,D) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_4(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D))
#define TRACE_5(MESSAGE,A,B,C,D,E) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_5(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E))
#define TRACE_6(MESSAGE,A,B,C,D,E,F) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_6(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F))
#define TRACE_7(MESSAGE,A,B,C,D,E,F,G) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_7(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G))
#define TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_8(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G,H))
#define TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_9(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G,H,I))
#else
#define TRACE_1(MESSAGE,A) /* disabled */
#define TRACE_2(MESSAGE,A,B) /* disabled */
#define TRACE_3(MESSAGE,A,B,C) /* disabled */
@ -365,7 +416,6 @@ Author:
#define TRACE_7(MESSAGE,A,B,C,D,E,F,G) /* disabled */
#define TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) /* disabled */
#define TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) /* disabled */
#endif
/* -------------------------------------------
@ -528,6 +578,81 @@ Author:
------------------------------------------- */
#define PUSH(var1,var2) (var1) pushBack (var2)
/* -------------------------------------------
Macro: MAP()
Description:
Applies given code to each element of the array, then assigns the
resulting array to the original
Parameters:
ARRAY - Array to be modified
CODE - Code that'll be applied to each element of the array.
Example:
(begin example)
_array = [1, 2, 3, 4, 3, 8];
MAP(_array,_x + 1);
// _array is now [2, 3, 4, 5, 4, 9];
(end)
Author:
654wak654
------------------------------------------- */
#define MAP(ARR,CODE) ARR = ARR apply {CODE}
/* -------------------------------------------
Macro: FILTER()
Description:
Filters an array based on given code, then assigns the resulting array
to the original
Parameters:
ARRAY - Array to be filtered
CODE - Condition to pick elements
Example:
(begin example)
_array = [1, 2, 3, 4, 3, 8];
FILTER(_array,_x % 2 == 0)
// _array is now [2, 4, 8];
(end)
Author:
Commy2
------------------------------------------- */
#define FILTER(ARR,CODE) ARR = ARR select {CODE}
/* -------------------------------------------
Macro: UNIQUE()
Description:
Removes duplicate values in given array
Parameters:
ARRAY - The array to be modified
Example:
(begin example)
_someArray = [4, 4, 5, 5, 5, 2];
UNIQUE(_someArray);
// _someArray is now [4, 5, 2]
(end)
Author:
Commy2
------------------------------------------- */
#define UNIQUE(ARR) ARR = ARR arrayIntersect ARR
/* -------------------------------------------
Macro: INTERSECTION()
Description:
Finds unique common elements between two arrays and assigns them
to the first array
Parameters:
ARRAY0 - The array to be modified
ARRAY1 - The array to find intersections with
Example:
(begin example)
_someArray = [1, 2, 3, 4, 5, 5];
_anotherArray = [4, 5, 6, 7];
INTERSECTION(_someArray,_anotherArray);
// _someArray is now [4, 5]
(end)
Author:
654wak654
------------------------------------------- */
#define INTERSECTION(ARG0,ARG1) ARG0 = ARG0 arrayIntersect (ARG1)
/* -------------------------------------------
Macro: ISNILS()
@ -721,6 +846,47 @@ Author:
#define PREPMAIN(var1) ['PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))', 'TRIPLES(PREFIX,fnc,var1)'] call SLX_XEH_COMPILE_NEW
#endif
#ifdef RECOMPILE
#undef RECOMPILE
#define RECOMPILE recompile = 1
#else
#define RECOMPILE recompile = 0
#endif
/* -------------------------------------------
Macro: PATHTO_FNC()
Description:
Defines a function inside CfgFunctions.
Full file path in addons:
'\MAINPREFIX\PREFIX\SUBPREFIX\COMPONENT\fnc_<FNC>.sqf'
Define 'RECOMPILE' to enable recompiling.
Parameters:
FUNCTION NAME - Name of the function, unquoted <STRING>
Examples:
(begin example)
// file name: fnc_addPerFrameHandler.sqf
class CfgFunctions {
class CBA {
class Misc {
PATHTO_FNC(addPerFrameHandler);
};
};
};
// -> CBA_fnc_addPerFrameHandler
(end)
Author:
dixon13, commy2
------------------------------------------- */
#define PATHTO_FNC(func) class func {\
file = QPATHTOF(DOUBLES(fnc,func).sqf);\
RECOMPILE;\
}
#define FUNC(var1) TRIPLES(ADDON,fnc,var1)
#define FUNCMAIN(var1) TRIPLES(PREFIX,fnc,var1)
#define FUNC_INNER(var1,var2) TRIPLES(DOUBLES(PREFIX,var1),fnc,var2)
@ -1453,6 +1619,7 @@ Author:
// XEH Specific
#define XEH_CLASS CBA_Extended_EventHandlers
#define XEH_CLASS_BASE DOUBLES(XEH_CLASS,base)
#define XEH_DISABLED class EventHandlers { class XEH_CLASS {}; }; SLX_XEH_DISABLED = 1
#define XEH_ENABLED class EventHandlers { class XEH_CLASS { EXTENDED_EVENTHANDLERS }; }; SLX_XEH_DISABLED = 0
@ -1465,4 +1632,42 @@ Author:
#define XEH_POST_CINIT QUOTE(call COMPILE_FILE(XEH_PostClientInit_Once))
#define XEH_POST_SINIT QUOTE(call COMPILE_FILE(XEH_PostServerInit_Once))
#define IS_LINUX (productVersion select 2 <= 154)
/* -------------------------------------------
Macro: IS_ADMIN
Check if the local machine is an admin in the multiplayer environment.
Reports 'true' for logged and voted in admins.
Parameters:
None
Example:
(begin example)
// print "true" if player is admin
systemChat str IS_ADMIN;
(end)
Author:
commy2
------------------------------------------- */
#define IS_ADMIN serverCommandAvailable "#kick"
/* -------------------------------------------
Macro: IS_ADMIN_LOGGED
Check if the local machine is a logged in admin in the multiplayer environment.
Reports 'false' if the player was voted to be the admin.
Parameters:
None
Example:
(begin example)
// print "true" if player is admin and entered in the server password
systemChat str IS_ADMIN_LOGGED;
(end)
Author:
commy2
------------------------------------------- */
#define IS_ADMIN_LOGGED serverCommandAvailable "#shutdown"