2015-01-12 18:22:58 +00:00
// ACE - Common
2015-12-30 07:07:55 +00:00
// #define ENABLE_PERFORMANCE_COUNTERS
2016-01-13 00:18:12 +00:00
// #define DEBUG_MODE_FULL
2015-09-21 15:00:53 +00:00
#include "script_component.hpp"
2015-08-30 20:26:43 +00:00
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// Get Map Data
//////////////////////////////////////////////////
//Find MGRS zone and 100km grid for current map
[] call FUNC(getMGRSdata);
//Prepare variables for FUNC(getMapGridFromPos)/FUNC(getMapPosFromGrid)
[] call FUNC(getMapGridData);
//////////////////////////////////////////////////
// Eventhandlers
//////////////////////////////////////////////////
2016-01-13 00:18:12 +00:00
//Status Effect EHs:
2016-06-03 19:07:49 +00:00
[QGVAR(setStatusEffect), {_this call FUNC(statusEffect_set)}] call CBA_fnc_addEventHandler;
2023-07-22 03:30:40 +00:00
["forceWalk", false, ["ace_advanced_fatigue", "ACE_SwitchUnits", "ACE_Attach", "ace_dragging", "ACE_Explosives", "ACE_Ladder", "ACE_Sandbag", "ACE_refuel", "ACE_rearm", "ACE_Trenches", "ace_medical_fracture"]] call FUNC(statusEffect_addType);
2023-06-28 11:43:10 +00:00
["blockSprint", false, ["ace_advanced_fatigue", "ace_dragging", "ace_medical_fracture"]] call FUNC(statusEffect_addType);
2017-12-06 16:22:07 +00:00
["setCaptive", true, [QEGVAR(captives,Handcuffed), QEGVAR(captives,Surrendered)]] call FUNC(statusEffect_addType);
2017-08-22 18:27:11 +00:00
["blockDamage", false, ["fixCollision", "ACE_cargo"]] call FUNC(statusEffect_addType);
2016-05-03 18:52:43 +00:00
["blockEngine", false, ["ACE_Refuel"]] call FUNC(statusEffect_addType);
2023-07-22 03:30:40 +00:00
["blockThrow", false, ["ACE_Attach", "ACE_concertina_wire", "ace_dragging", "ACE_Explosives", "ACE_Ladder", "ACE_rearm", "ACE_refuel", "ACE_Sandbag", "ACE_Trenches", "ACE_tripod"]] call FUNC(statusEffect_addType);
2017-12-06 16:22:07 +00:00
["setHidden", true, ["ace_unconscious"]] call FUNC(statusEffect_addType);
2021-09-25 16:16:15 +00:00
["blockRadio", false, [QEGVAR(captives,Handcuffed), QEGVAR(captives,Surrendered), "ace_unconscious"]] call FUNC(statusEffect_addType);
2022-05-08 18:20:15 +00:00
["blockSpeaking", false, ["ace_unconscious"]] call FUNC(statusEffect_addType);
2023-11-23 00:16:42 +00:00
["disableWeaponAssembly", false, ["ace_common", "ace_common_lockVehicle", "ace_csw"]] call FUNC(statusEffect_addType);
2024-01-16 15:37:57 +00:00
["lockInventory", true, [], true] call FUNC(statusEffect_addType);
2016-01-13 00:18:12 +00:00
2016-06-03 19:07:49 +00:00
[QGVAR(forceWalk), {
2016-01-13 00:18:12 +00:00
params ["_object", "_set"];
TRACE_2("forceWalk EH",_object,_set);
_object forceWalk (_set > 0);
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2017-12-06 16:22:07 +00:00
2016-06-03 19:07:49 +00:00
[QGVAR(blockSprint), { //Name reversed from `allowSprint` because we want NOR logic
2016-01-16 23:27:42 +00:00
params ["_object", "_set"];
TRACE_2("blockSprint EH",_object,_set);
_object allowSprint (_set == 0);
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2017-12-06 16:22:07 +00:00
2016-09-30 08:38:27 +00:00
[QGVAR(setAnimSpeedCoef), {
params ["_object", "_set"];
_object setAnimSpeedCoef _set;
}] call CBA_fnc_addEventHandler;
2017-12-23 00:47:43 +00:00
2016-06-03 19:07:49 +00:00
[QGVAR(setCaptive), {
2016-01-13 00:18:12 +00:00
params ["_object", "_set"];
2016-01-16 23:27:42 +00:00
TRACE_2("setCaptive EH",_object,_set);
2017-12-06 16:22:07 +00:00
_object setCaptive (_set > 0);
}] call CBA_fnc_addEventHandler;
[QGVAR(setHidden), {
params ["_object", "_set"];
TRACE_2("setHidden EH",_object,_set);
2018-02-21 10:05:17 +00:00
// May report nil. Default to factor 1.
private _vis = [_object getUnitTrait "camouflageCoef"] param [0, 1];
2017-12-06 15:55:01 +00:00
if (_set > 0) then {
2017-12-09 03:39:35 +00:00
if (_vis != 0) then {
_object setVariable [QGVAR(oldVisibility), _vis];
2017-12-06 15:55:01 +00:00
_object setUnitTrait ["camouflageCoef", 0];
2017-12-29 01:48:20 +00:00
{
2018-01-02 15:26:13 +00:00
if (side _x != side group _object) then {
_x forgetTarget _object;
};
2017-12-29 01:48:20 +00:00
} forEach allGroups;
2017-12-06 15:55:01 +00:00
};
} else {
2017-12-09 03:39:35 +00:00
_vis = _object getVariable [QGVAR(oldVisibility), _vis];
_object setUnitTrait ["camouflageCoef", _vis];
2017-12-06 15:55:01 +00:00
};
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2017-12-06 16:22:07 +00:00
2021-09-25 16:16:15 +00:00
[QGVAR(blockRadio), {
params ["_object", "_set"];
TRACE_2("blockRadio EH",_object,_set);
if (_object isEqualTo ACE_Player && {_set > 0}) then {
call FUNC(endRadioTransmission);
};
2022-01-30 17:56:20 +00:00
if (["task_force_radio"] call FUNC(isModLoaded)) then {
2021-09-25 16:16:15 +00:00
_object setVariable ["tf_unable_to_use_radio", _set > 0, true];
};
2022-01-30 17:56:20 +00:00
if (["acre_main"] call FUNC(isModLoaded)) then {
2022-03-08 22:40:48 +00:00
_object setVariable ["acre_sys_core_isDisabledRadio", _set > 0, true];
2021-09-25 16:16:15 +00:00
};
}] call CBA_fnc_addEventHandler;
2022-05-08 18:20:15 +00:00
[QGVAR(blockSpeaking), {
params ["_object", "_set"];
TRACE_2("blockSpeaking EH",_object,_set);
if (["acre_main"] call FUNC(isModLoaded)) then {
_object setVariable ["acre_sys_core_isDisabled", _set > 0, true];
};
if (["task_force_radio"] call FUNC(isModLoaded)) then {
2024-02-04 17:50:24 +00:00
_object setVariable ["tf_voiceVolume", parseNumber (_set == 0), true];
2022-05-08 18:20:15 +00:00
};
}] call CBA_fnc_addEventHandler;
2016-06-03 19:07:49 +00:00
[QGVAR(blockDamage), { //Name reversed from `allowDamage` because we want NOR logic
2016-01-13 00:18:12 +00:00
params ["_object", "_set"];
if ((_object isKindOf "CAManBase") && {(["ace_medical"] call FUNC(isModLoaded))}) then {
TRACE_2("blockDamage EH (using medical)",_object,_set);
2017-12-07 17:26:21 +00:00
_object setVariable [QEGVAR(medical,allowDamage), (_set == 0), true];
2016-01-13 00:18:12 +00:00
} else {
TRACE_2("blockDamage EH (using allowDamage)",_object,_set);
_object allowDamage (_set == 0);
};
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2017-12-06 16:22:07 +00:00
2016-06-03 19:07:49 +00:00
[QGVAR(blockEngine), {
2016-05-03 18:52:43 +00:00
params ["_vehicle", "_set"];
_vehicle setVariable [QGVAR(blockEngine), _set > 0, true];
_vehicle engineOn false;
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2016-01-13 00:18:12 +00:00
2019-03-24 08:26:00 +00:00
[QGVAR(setMass), {
params ["_object", "_mass"];
_object setMass _mass;
}] call CBA_fnc_addEventHandler;
2023-11-23 00:16:42 +00:00
[QGVAR(disableWeaponAssembly), {
params ["_object", "_set"];
_object enableWeaponDisassembly (_set < 1);
}] call CBA_fnc_addEventHandler;
2023-09-22 16:02:09 +00:00
[QGVAR(lockInventory), {
params ["_object", "_set"];
TRACE_2("lockInventory EH",_object,_set);
_object lockInventory (_set > 0);
}] call CBA_fnc_addEventHandler;
2015-12-18 17:08:10 +00:00
//Add a fix for BIS's zeus remoteControl module not reseting variables on DC when RC a unit
//This variable is used for isPlayer checks
if (isServer) then {
addMissionEventHandler ["HandleDisconnect", {
params ["_dcPlayer"];
private _zeusLogic = getAssignedCuratorLogic _dcPlayer;
if ((!isNil "_zeusLogic") && {!isNull _zeusLogic}) then {
{
if ((_x getvariable ["bis_fnc_moduleRemoteControl_owner", objnull]) isEqualTo _dcPlayer) exitWith {
2024-02-05 17:04:24 +00:00
INFO_3("[%1] DC - Was Zeus [%2] while controlling unit [%3] - manually clearing `bis_fnc_moduleRemoteControl_owner`",[_x] call FUNC(getName),_dcPlayer,_x);
2015-12-18 17:08:10 +00:00
_x setVariable ["bis_fnc_moduleRemoteControl_owner", nil, true];
};
2015-12-20 03:17:36 +00:00
nil
2015-12-18 17:08:10 +00:00
} count (curatorEditableObjects _zeusLogic);
};
}];
};
2015-09-21 15:00:53 +00:00
// Event to log Fix Headbug output
2016-06-03 19:38:16 +00:00
[QGVAR(headbugFixUsed), {
2015-09-21 15:00:53 +00:00
params ["_profileName", "_animation"];
2016-10-02 10:55:31 +00:00
INFO_2("Headbug Used: Name: %1, Animation: %2",_profileName,_animation);
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2015-08-02 01:01:35 +00:00
2016-06-04 10:12:56 +00:00
[QGVAR(fixCollision), FUNC(fixCollision)] call CBA_fnc_addEventHandler;
[QGVAR(fixFloating), FUNC(fixFloating)] call CBA_fnc_addEventHandler;
[QGVAR(fixPosition), FUNC(fixPosition)] call CBA_fnc_addEventHandler;
2015-08-02 01:01:35 +00:00
2019-09-05 20:56:53 +00:00
["ace_loadPersonEvent", LINKFUNC(loadPersonLocal)] call CBA_fnc_addEventHandler;
["ace_unloadPersonEvent", LINKFUNC(unloadPersonLocal)] call CBA_fnc_addEventHandler;
2015-06-11 22:56:11 +00:00
2016-06-04 10:12:56 +00:00
[QGVAR(lockVehicle), {
2015-03-18 10:29:58 +00:00
_this setVariable [QGVAR(lockStatus), locked _this];
_this lock 2;
2023-11-23 00:16:42 +00:00
if ([] isNotEqualTo getArray (configOf _this >> "assembleInfo" >> "dissasembleTo")) then {
[_this, "disableWeaponAssembly", QGVAR(lockVehicle), true] call FUNC(statusEffect_set);
};
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2015-03-18 10:29:58 +00:00
2016-06-04 10:12:56 +00:00
[QGVAR(unlockVehicle), {
2015-03-18 10:29:58 +00:00
_this lock (_this getVariable [QGVAR(lockStatus), locked _this]);
2023-11-23 00:16:42 +00:00
if ([] isNotEqualTo getArray (configOf _target >> "assembleInfo" >> "dissasembleTo")) then {
[_this, "disableWeaponAssembly", QGVAR(lockVehicle), false] call FUNC(statusEffect_set);
};
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2016-06-04 10:12:56 +00:00
[QGVAR(setDir), {(_this select 0) setDir (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(setFuel), {(_this select 0) setFuel (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(engineOn), {(_this select 0) engineOn (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(setSpeaker), {(_this select 0) setSpeaker (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(selectLeader), {(_this select 0) selectLeader (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(setVelocity), {(_this select 0) setVelocity (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(playMove), {(_this select 0) playMove (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(playMoveNow), {(_this select 0) playMoveNow (_this select 1)}] call CBA_fnc_addEventHandler;
2016-07-12 14:16:01 +00:00
[QGVAR(playAction), {(_this select 0) playAction (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(playActionNow), {(_this select 0) playActionNow (_this select 1)}] call CBA_fnc_addEventHandler;
2016-06-04 10:12:56 +00:00
[QGVAR(switchMove), {(_this select 0) switchMove (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(setVectorDirAndUp), {(_this select 0) setVectorDirAndUp (_this select 1)}] call CBA_fnc_addEventHandler;
2017-09-21 18:43:35 +00:00
[QGVAR(addWeaponItem), {(_this select 0) addWeaponItem [(_this select 1), (_this select 2)]}] call CBA_fnc_addEventHandler;
2015-03-24 18:07:39 +00:00
2019-05-03 15:03:17 +00:00
[QGVAR(setVanillaHitPointDamage), {
params ["_object", "_hitPointAnddamage"];
2019-05-03 15:09:16 +00:00
private _damageDisabled = !isDamageAllowed _object;
2019-05-03 15:03:17 +00:00
2019-05-03 15:09:16 +00:00
if (_damageDisabled) then {
2019-05-03 15:03:17 +00:00
_object allowDamage true;
};
_object setHitPointDamage _hitPointAnddamage;
2019-05-03 15:09:16 +00:00
if (_damageDisabled) then {
2019-05-03 15:03:17 +00:00
_object allowDamage false;
};
}] call CBA_fnc_addEventHandler;
2016-05-21 17:59:44 +00:00
// Request framework
2016-06-03 00:29:30 +00:00
[QGVAR(requestCallback), FUNC(requestCallback)] call CBA_fnc_addEventHandler;
[QGVAR(receiveRequest), FUNC(receiveRequest)] call CBA_fnc_addEventHandler;
2016-05-21 17:59:44 +00:00
2016-06-03 00:29:30 +00:00
[QGVAR(systemChatGlobal), {systemChat _this}] call CBA_fnc_addEventHandler;
2016-05-21 17:59:44 +00:00
2015-07-03 01:14:58 +00:00
if (isServer) then {
2016-06-03 19:38:16 +00:00
[QGVAR(hideObjectGlobal), {(_this select 0) hideObjectGlobal (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(enableSimulationGlobal), {(_this select 0) enableSimulationGlobal (_this select 1)}] call CBA_fnc_addEventHandler;
2017-04-11 14:59:32 +00:00
[QGVAR(setShotParents), {(_this select 0) setShotParents [_this select 1, _this select 2]}] call CBA_fnc_addEventHandler;
2016-06-03 00:29:30 +00:00
["ace_setOwner", {(_this select 0) setOwner (_this select 1)}] call CBA_fnc_addEventHandler;
[QGVAR(serverLog), FUNC(serverLog)] call CBA_fnc_addEventHandler;
2019-12-07 21:18:50 +00:00
[QGVAR(claimSafe), LINKFUNC(claimSafeServer)] call CBA_fnc_addEventHandler;
2015-07-03 01:14:58 +00:00
};
2015-01-11 16:42:31 +00:00
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// Set up remote execution
//////////////////////////////////////////////////
2015-01-11 16:42:31 +00:00
2015-04-18 02:26:27 +00:00
// Synced ACE events
// Handle JIP scenario
2015-09-21 15:00:53 +00:00
if (!isServer) then {
2016-06-03 19:38:16 +00:00
["ace_playerJIP", {
2016-10-02 10:55:31 +00:00
INFO("JIP event synchronization initialized");
2016-06-04 19:05:26 +00:00
["ACEa", [player]] call CBA_fnc_serverEvent;
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2015-04-18 02:26:27 +00:00
} else {
2016-06-04 19:05:26 +00:00
["ACEa", FUNC(_handleRequestAllSyncedEvents)] call CBA_fnc_addEventHandler;
2015-04-18 02:26:27 +00:00
};
2015-09-21 15:00:53 +00:00
2016-06-04 19:05:26 +00:00
["ACEe", FUNC(_handleSyncedEvent)] call CBA_fnc_addEventHandler;
["ACEs", FUNC(_handleRequestSyncedEvent)] call CBA_fnc_addEventHandler;
2015-09-21 15:00:53 +00:00
2015-08-06 05:28:43 +00:00
if (isServer) then {
[FUNC(syncedEventPFH), 0.5, []] call CBA_fnc_addPerFrameHandler;
};
2015-08-11 18:10:42 +00:00
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// Check files, previous installed version etc.
//////////////////////////////////////////////////
2019-12-18 20:43:40 +00:00
private _currentVersion = getText (configFile >> "CfgPatches" >> QUOTE(ADDON) >> "versionStr");
2015-12-14 12:17:48 +00:00
private _previousVersion = profileNamespace getVariable ["ACE_VersionNumberString", ""];
2015-09-21 15:00:53 +00:00
// check previous version number from profile
if (_currentVersion != _previousVersion) then {
2017-12-10 18:13:17 +00:00
INFO_2("Updating ACE from [%1] to [%2]",_previousVersion,_currentVersion);
[_previousVersion] call FUNC(cbaSettings_transferUserSettings);
2015-09-21 15:00:53 +00:00
profileNamespace setVariable ["ACE_VersionNumberString", _currentVersion];
};
2015-05-09 11:25:19 +00:00
call FUNC(checkFiles);
2015-04-18 02:26:27 +00:00
2015-06-13 03:57:01 +00:00
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
2016-06-03 00:59:18 +00:00
// Set up ace_settingsInitialized eventhandler
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
2021-10-11 20:48:30 +00:00
["CBA_settingsInitialized", {
2015-09-21 15:00:53 +00:00
[
GVAR(checkPBOsAction),
GVAR(checkPBOsCheckAll),
2015-12-03 05:58:41 +00:00
GVAR(checkPBOsWhitelist)
2015-09-21 15:00:53 +00:00
] call FUNC(checkPBOs)
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2015-09-21 15:00:53 +00:00
2015-06-13 03:57:01 +00:00
2015-09-21 15:00:53 +00:00
/***************************************************************************/
/***************************************************************************/
/** everything that only player controlled machines need, goes below this **/
/***************************************************************************/
/***************************************************************************/
2015-04-18 02:26:27 +00:00
2015-01-11 16:42:31 +00:00
if (!hasInterface) exitWith {};
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// Set up mouse wheel eventhandler
//////////////////////////////////////////////////
call FUNC(assignedItemFix);
2015-09-21 16:37:19 +00:00
2015-09-21 15:00:53 +00:00
// @todo remove?
2015-01-11 16:42:31 +00:00
enableCamShake true;
2015-09-21 15:00:53 +00:00
2016-05-31 06:53:28 +00:00
//FUNC(showHud) needs to be refreshed if it was set during mission init
["ace_infoDisplayChanged", {
2021-10-10 16:55:14 +00:00
if (GVAR(showHudHash) isNotEqualTo createHashMap) then {
2016-05-31 06:53:28 +00:00
[] call FUNC(showHud);
};
}] call CBA_fnc_addEventHandler;
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// Eventhandler to set player names
//////////////////////////////////////////////////
2015-01-12 04:02:33 +00:00
// Set the name for the current player
2016-06-22 09:16:55 +00:00
["unit", {
2015-09-21 15:00:53 +00:00
params ["_newPlayer","_oldPlayer"];
2015-04-30 18:49:38 +00:00
2015-01-16 15:14:18 +00:00
if (alive _newPlayer) then {
2017-02-10 19:03:12 +00:00
[FUNC(setName), [_newPlayer]] call CBA_fnc_execNextFrame;
2015-01-12 21:34:01 +00:00
};
2015-09-21 15:00:53 +00:00
2015-01-16 15:14:18 +00:00
if (alive _oldPlayer) then {
2017-02-10 19:03:12 +00:00
[FUNC(setName), [_oldPlayer]] call CBA_fnc_execNextFrame;
2015-01-12 21:34:01 +00:00
};
2020-04-24 21:59:47 +00:00
}, true] call CBA_fnc_addPlayerEventHandler;
2015-01-13 23:27:42 +00:00
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// Set up numerous eventhanders for player controlled units
//////////////////////////////////////////////////
2017-04-11 15:06:29 +00:00
TRACE_1("adding unit playerEH to set ace_player",isNull cba_events_oldUnit);
2016-06-22 00:31:25 +00:00
["unit", {
ACE_player = (_this select 0);
2017-04-11 15:06:29 +00:00
}, true] call CBA_fnc_addPlayerEventHandler;
2016-06-22 00:31:25 +00:00
2018-09-17 19:03:28 +00:00
// Clear uniqueItems cache on loadout change
["loadout", {
GVAR(uniqueItemsCache) = nil;
}] call CBA_fnc_addPlayerEventHandler;
2018-10-12 12:59:40 +00:00
// Backwards compatiblity for old ace event
2015-09-21 15:00:53 +00:00
GVAR(OldIsCamera) = false;
2018-10-12 12:59:40 +00:00
["featureCamera", {
params ["_player", "_cameraName"];
GVAR(OldIsCamera) = _cameraName != "";
["ace_activeCameraChanged", [_player, GVAR(OldIsCamera)]] call CBA_fnc_localEvent;
}, true] call CBA_fnc_addPlayerEventHandler;
2015-04-18 20:06:42 +00:00
2017-08-22 21:07:45 +00:00
// Add event handler for UAV control change
ACE_controlledUAV = [objNull, objNull, [], ""];
addMissionEventHandler ["PlayerViewChanged", {
// On non-server client this command is semi-broken
// arg index 5 should be the controlled UAV, but it will often be objNull (delay from locality switching?)
// On PlayerViewChanged event, start polling for new uav state for a few seconds (should be done within a few frames)
2017-12-29 01:48:20 +00:00
2017-08-22 21:07:45 +00:00
params ["", "", "", "", "_newCameraOn", "_UAV"];
TRACE_2("PlayerViewChanged",_newCameraOn,_UAV);
2017-12-29 01:48:20 +00:00
2017-08-22 21:07:45 +00:00
[{
if (isNull player) exitWith {true};
private _UAV = getConnectedUAV player;
if (!alive player) then {_UAV = objNull;};
2019-09-04 00:05:45 +00:00
private _position = [player] call FUNC(getUavControlPosition);
2017-08-22 21:07:45 +00:00
private _seatAI = objNull;
private _turret = [];
2024-03-07 21:08:13 +00:00
switch (toLowerANSI _position) do {
2017-08-22 21:07:45 +00:00
case (""): {
_UAV = objNull; // set to objNull if not actively controlling
};
case ("driver"): {
_turret = [-1];
_seatAI = driver _UAV;
};
case ("gunner"): {
_turret = [0];
_seatAI = gunner _UAV;
};
};
2017-12-29 01:48:20 +00:00
2017-08-22 21:07:45 +00:00
private _newArray = [_UAV, _seatAI, _turret, _position];
if (_newArray isEqualTo ACE_controlledUAV) exitWith {false}; // no change yet
2017-12-29 01:48:20 +00:00
2017-08-22 21:07:45 +00:00
TRACE_2("Seat Change",_newArray,ACE_controlledUAV);
ACE_controlledUAV = _newArray;
["ACE_controlledUAV", _newArray] call CBA_fnc_localEvent;
2017-12-29 01:48:20 +00:00
2017-08-22 21:07:45 +00:00
// stay in the loop as we might switch from gunner -> driver, and there may be a empty position event in-between
false
}, {}, [], 3, {TRACE_1("timeout",_this);}] call CBA_fnc_waitUntilAndExecute;
}];
2015-04-18 20:06:42 +00:00
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// Eventhandlers for player controlled machines
//////////////////////////////////////////////////
2015-04-18 20:06:42 +00:00
2016-06-04 10:12:56 +00:00
[QGVAR(displayTextStructured), {_this call FUNC(displayTextStructured)}] call CBA_fnc_addEventHandler;
[QGVAR(displayTextPicture), {_this call FUNC(displayTextPicture)}] call CBA_fnc_addEventHandler;
2015-04-18 20:06:42 +00:00
2016-06-04 10:12:56 +00:00
["ace_unconscious", {
2015-09-21 15:00:53 +00:00
params ["_unit", "_isUnconscious"];
2015-04-18 20:06:42 +00:00
2015-09-21 15:00:53 +00:00
if (local _unit && {!_isUnconscious}) then {
[_unit, false, QFUNC(loadPerson), west /* dummy side */] call FUNC(switchToGroupSide);
};
2016-05-22 15:29:05 +00:00
}] call CBA_fnc_addEventHandler;
2015-04-18 20:06:42 +00:00
2016-05-24 13:13:11 +00:00
["ace_useItem", DFUNC(useItem)] call CBA_fnc_addEventHandler;
2016-02-18 01:54:43 +00:00
2015-01-28 20:38:04 +00:00
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// Add various canInteractWith conditions
//////////////////////////////////////////////////
2015-03-15 08:26:16 +00:00
2016-03-12 13:06:45 +00:00
["isNotDead", {
2016-07-07 07:10:14 +00:00
params ["_unit"];
2016-03-12 13:06:45 +00:00
alive _unit
}] call FUNC(addCanInteractWithCondition);
2015-03-15 15:12:37 +00:00
["notOnMap", {!visibleMap}] call FUNC(addCanInteractWithCondition);
2015-09-21 15:00:53 +00:00
2015-03-31 21:06:28 +00:00
["isNotInside", {
2015-09-21 15:00:53 +00:00
params ["_unit", "_target"];
2015-03-31 21:06:28 +00:00
// Players can always interact with himself if not boarded
2023-07-22 06:11:58 +00:00
isNull objectParent _unit ||
2015-03-31 21:06:28 +00:00
// Players can always interact with his vehicle
2023-07-22 06:11:58 +00:00
{objectParent _unit isEqualTo _target} ||
2015-03-31 21:06:28 +00:00
// Players can always interact with passengers of the same vehicle
2023-07-22 06:11:58 +00:00
{_unit isNotEqualTo _target && {!isNull objectParent _target} && {objectParent _unit isEqualTo objectParent _target}} ||
2017-08-22 21:07:45 +00:00
// Players can always interact with connected UAV
{!(isNull (ACE_controlledUAV select 0))}
2015-03-31 21:06:28 +00:00
}] call FUNC(addCanInteractWithCondition);
2015-04-17 23:44:53 +00:00
2015-12-30 07:48:43 +00:00
["isNotInZeus", {isNull curatorCamera}] call FUNC(addCanInteractWithCondition);
2016-07-07 13:47:37 +00:00
2020-02-22 22:07:32 +00:00
["isNotUnconscious", {
params ["_unit"];
2023-07-22 06:11:58 +00:00
lifeState _unit isNotEqualTo "INCAPACITATED"
2020-02-22 22:07:32 +00:00
}] call FUNC(addCanInteractWithCondition);
2016-07-07 13:47:37 +00:00
//////////////////////////////////////////////////
// Set up reload mutex
//////////////////////////////////////////////////
GVAR(isReloading) = false;
2021-03-03 21:31:07 +00:00
GVAR(reloadMutex_lastMagazines) = [];
// When reloading, the new magazine is removed from inventory, an animation plays and then the old magazine is added
// If the animation is interrupted, the new magazine will be lost
["loadout", {
params ["_unit", "_newLoadout"];
private _mags = magazines _unit;
// if our magazine count dropped by 1, we might be reloading
if ((count GVAR(reloadMutex_lastMagazines)) - (count _mags) == 1) then {
private _weapon = currentWeapon _unit;
private _muzzle = currentMuzzle _unit;
if (_weapon == "") exitWith {};
private _wpnMzlConfig = configFile >> "CfgWeapons" >> _weapon;
if (_muzzle != _weapon) then { _wpnMzlConfig = _wpnMzlConfig >> _muzzle; };
private _compatMags = [_wpnMzlConfig] call CBA_fnc_compatibleMagazines;
private _lastCompatMagCount = {_x in _compatMags} count GVAR(reloadMutex_lastMagazines);
private _curCompatMagCount = {_x in _compatMags} count _mags;
TRACE_3("",_wpnMzlConfig,_lastCompatMagCount,_curCompatMagCount);
if (_lastCompatMagCount - _curCompatMagCount != 1) exitWith {}; // check if magazines for our specific muzzle dropped by 1
private _gesture = getText (_wpnMzlConfig >> "reloadAction");
if (_gesture == "") exitWith {}; //Ignore weapons with no reload gesture (binoculars)
private _isLauncher = _weapon isKindOf ["Launcher", configFile >> "CfgWeapons"];
2021-06-28 05:01:32 +00:00
private _duration = 0;
if (_isLauncher) then {
_duration = getNumber (configfile >> "CfgMovesMaleSdr" >> "States" >> _gesture >> "speed");
};
if (_duration == 0) then {
_duration = getNumber (configfile >> "CfgGesturesMale" >> "States" >> _gesture >> "speed");
};
2021-03-03 21:31:07 +00:00
if (_duration != 0) then {
_duration = if (_duration < 0) then { abs _duration } else { 1 / _duration };
} else {
2021-06-28 05:01:32 +00:00
_duration = 6;
2021-03-03 21:31:07 +00:00
};
2016-07-07 13:47:37 +00:00
2021-03-03 21:31:07 +00:00
TRACE_2("Reloading, blocking gestures",_weapon,_duration);
GVAR(reloadingETA) = CBA_missionTime + _duration;
2016-07-08 13:12:47 +00:00
2021-03-03 21:31:07 +00:00
if (!GVAR(isReloading)) then {
GVAR(isReloading) = true;
2016-07-08 13:12:47 +00:00
2021-03-03 21:31:07 +00:00
[{
CBA_missionTime > GVAR(reloadingETA)
},{
GVAR(isReloading) = false;
}] call CBA_fnc_waitUntilAndExecute;
2016-07-07 13:47:37 +00:00
};
};
2021-03-03 21:31:07 +00:00
GVAR(reloadMutex_lastMagazines) = _mags;
}, true] call CBA_fnc_addPlayerEventHandler;
2016-07-07 13:47:37 +00:00
2023-09-02 22:09:19 +00:00
//////////////////////////////////////////////////
// Start the sway loop
//////////////////////////////////////////////////
["CBA_settingsInitialized", {
[{
// frame after settingsInitialized to ensure all other addons have added their factors
if ((GVAR(swayFactorsBaseline) + GVAR(swayFactorsMultiplier)) isNotEqualTo []) then {
call FUNC(swayLoop)
};
// check for pre-3.16 sway factors being added
if (!isNil {missionNamespace getVariable "ACE_setCustomAimCoef"}) then {
WARNING("ACE_setCustomAimCoef no longer supported - use ace_common_fnc_addSwayFactor");
WARNING_1("source: %1",(missionNamespace getVariable "ACE_setCustomAimCoef") apply {_x});
};
}] call CBA_fnc_execNextFrame;
}] call CBA_fnc_addEventHandler;
2015-09-21 16:37:19 +00:00
//////////////////////////////////////////////////
// Set up PlayerJIP eventhandler
//////////////////////////////////////////////////
2015-04-18 02:26:27 +00:00
// Lastly, do JIP events
2015-04-18 01:23:26 +00:00
// JIP Detection and event trigger. Run this at the very end, just in case anything uses it
2015-09-21 16:37:19 +00:00
// Note: usage of player is most likely on purpose
2015-08-27 03:39:27 +00:00
if (didJip) then {
2015-04-18 01:23:26 +00:00
// We are jipping! Get ready and wait, and throw the event
[{
2015-09-21 16:37:19 +00:00
if(!isNull player && GVAR(settingsInitFinished)) then {
2016-06-03 19:38:16 +00:00
["ace_playerJIP", [player]] call CBA_fnc_localEvent;
2015-09-21 16:37:19 +00:00
[_this select 1] call CBA_fnc_removePerFrameHandler;
2015-04-30 18:49:38 +00:00
};
2015-08-04 07:34:31 +00:00
}, 0, []] call CBA_fnc_addPerFrameHandler;
2015-04-18 01:23:26 +00:00
};
2015-05-10 19:59:53 +00:00
2015-09-21 15:00:53 +00:00
//////////////////////////////////////////////////
// CBA key input handling
//////////////////////////////////////////////////
2015-05-10 19:59:53 +00:00
//Device Handler:
GVAR(deviceKeyHandlingArray) = [];
GVAR(deviceKeyCurrentIndex) = -1;
2015-08-07 01:33:38 +00:00
// Register localizations for the Keybinding categories
2019-12-07 21:40:44 +00:00
["ACE3 Equipment", LLSTRING(ACEKeybindCategoryEquipment)] call CBA_fnc_registerKeybindModPrettyName;
["ACE3 Common", LLSTRING(ACEKeybindCategoryCommon)] call CBA_fnc_registerKeybindModPrettyName;
["ACE3 Weapons", LLSTRING(ACEKeybindCategoryWeapons)] call CBA_fnc_registerKeybindModPrettyName;
["ACE3 Movement", LLSTRING(ACEKeybindCategoryMovement)] call CBA_fnc_registerKeybindModPrettyName;
["ACE3 Scope Adjustment", LLSTRING(ACEKeybindCategoryScopeAdjustment)] call CBA_fnc_registerKeybindModPrettyName;
["ACE3 Vehicles", LLSTRING(ACEKeybindCategoryVehicles)] call CBA_fnc_registerKeybindModPrettyName;
["ACE3 Equipment", QGVAR(openDevice), LLSTRING(toggleHandheldDevice), {
2015-05-10 19:59:53 +00:00
[] call FUNC(deviceKeyFindValidIndex);
if (GVAR(deviceKeyCurrentIndex) == -1) exitWith {false};
[] call ((GVAR(deviceKeyHandlingArray) select GVAR(deviceKeyCurrentIndex)) select 3);
2015-05-12 03:48:03 +00:00
true
2015-05-10 19:59:53 +00:00
},
{false},
2015-09-21 15:00:53 +00:00
[0xC7, [false, false, false]], false] call CBA_fnc_addKeybind; //Home Key
2015-05-10 19:59:53 +00:00
2019-12-07 21:40:44 +00:00
["ACE3 Equipment", QGVAR(closeDevice), LLSTRING(closeHandheldDevice), {
2015-05-10 19:59:53 +00:00
[] call FUNC(deviceKeyFindValidIndex);
if (GVAR(deviceKeyCurrentIndex) == -1) exitWith {false};
[] call ((GVAR(deviceKeyHandlingArray) select GVAR(deviceKeyCurrentIndex)) select 4);
2015-05-12 03:48:03 +00:00
true
2015-05-10 19:59:53 +00:00
},
{false},
2015-09-21 15:00:53 +00:00
[0xC7, [false, true, false]], false] call CBA_fnc_addKeybind; //CTRL + Home Key
2015-05-10 19:59:53 +00:00
2019-12-07 21:40:44 +00:00
["ACE3 Equipment", QGVAR(cycleDevice), LLSTRING(cycleHandheldDevices), {
2015-05-10 19:59:53 +00:00
[1] call FUNC(deviceKeyFindValidIndex);
if (GVAR(deviceKeyCurrentIndex) == -1) exitWith {false};
2017-05-14 19:48:05 +00:00
private _displayName = ((GVAR(deviceKeyHandlingArray) select GVAR(deviceKeyCurrentIndex)) select 0);
private _iconImage = ((GVAR(deviceKeyHandlingArray) select GVAR(deviceKeyCurrentIndex)) select 1);
2015-05-10 19:59:53 +00:00
[_displayName, _iconImage] call FUNC(displayTextPicture);
2015-05-12 03:48:03 +00:00
true
2015-05-10 19:59:53 +00:00
},
{false},
2015-09-21 15:00:53 +00:00
[0xC7, [true, false, false]], false] call CBA_fnc_addKeybind; //SHIFT + Home Key
2015-06-05 22:50:04 +00:00
2022-05-18 18:07:47 +00:00
2023-08-26 16:04:31 +00:00
["ACE3 Weapons", QGVAR(unloadWeapon), LSTRING(unloadWeapon), {
private _unit = ACE_player;
2022-05-18 18:07:47 +00:00
2023-08-26 16:04:31 +00:00
// Conditions
if !([_unit, objNull, ["isNotInside"]] call FUNC(canInteractWith)) exitWith {false};
2022-05-18 18:07:47 +00:00
2023-08-26 16:04:31 +00:00
if !(_unit call CBA_fnc_canUseWeapon) exitWith {false};
(weaponState _unit) params ["_weapon", "_muzzle", "", "_magazine", "_ammo"];
// Check if there is any ammo
if (_ammo < 1) exitWith {false};
// Check if the unit has a weapon
if (_weapon == "") exitWith {false};
// Check if the unit has a weapon selected
if !(_weapon in [primaryWeapon _unit, handgunWeapon _unit, secondaryWeapon _unit]) exitWith {false};
// Statement
[_unit, _weapon, _muzzle, _magazine, _ammo, false] call FUNC(unloadUnitWeapon);
2022-05-18 18:07:47 +00:00
true
2023-08-26 16:04:31 +00:00
}, {false}, [19, [false, false, true]], false] call CBA_fnc_addKeybind; // Alt + R
2022-05-18 18:07:47 +00:00
2022-08-25 16:56:54 +00:00
["CBA_loadoutSet", {
params ["_unit", "_loadout"];
_loadout params ["_primaryWeaponArray"];
Arsenal - Add/Fix/Improve/Change numerous aspects (#9040)
* Arsenal update
* Fixes
* Update fnc_onSelChangedLeft.sqf
* Update fnc_updateUniqueItemsList.sqf
* Header fixes
* Fix for defines.hpp
Co-authored-by: Dystopian <sddex@ya.ru>
* Moved fnc_baseWeapon, filtered invalid items
* Update addons/arsenal/functions/fnc_scanConfig.sqf
Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
* Fixes and tweaks
- Sorting is guaranteed to give a fixed order
- Dog tags no longer throw errors when reloading the ACE arsenal mission when you had some saved in your loadout before quitting the last time you played.
* Cleanup, bug fixes and additions
- Added the ability to add items from "CfgMagazines" into the "Misc. items" or custom tabs.
- Added "baseWeapon" class support for weapon attachments. If a weapon attachment has the config property "baseWeapon" defined, it will take that item and show that in the arsenal.
- Added stronger filtering on item scopes (scope > 0 at least for every item)
- Added "descending" (default, as it is now) and "ascending" sort order as a drop down menu,
- Unique backpacks in containers can now be removed with either the "-" or "clear all items" button.
- When sorting by a number, 2 decimal points have been added, so that when you sort by weight it returns the correct order.
* More fixes and tweaks
- Converted the arsenal to partially work with hashmaps instead of arrays (for configItems and virtualItems, currentItems is still an array).
- Because of the above, performance of FUNC(addVirtualItems) and FUNC(removeVirtualItems) has improved immensely.
- Sorting now caches results, reducing repeated sorting times drastically.
- CBA disposable launchers are handled differently now: Within the arsenal, you can change weapon attachments on disposable launchers, but you can't change their magazines (primary or secondary). Item info on the right and the stats show correct information.
- FUNC(addSort) now checks if the new sorting method already exists and doesn't add it if it does.
- FUNC(removeSort) now exists. You can't remove the default sort type (alphabetically) to avoid problems with the arsenal.
- Both FUNC(addStat) and FUNC(compileStats) actually taken priority into account now. Because of that priority on several stats needed to be tweaked.
- FUNC(removeStat) ensures that there are no gaps within the stat array (so if there is an empty spot in the stats page, it's because there is a stat, but the condition for it being shown hasn't been met).
* Update fnc_replaceUniqueItemsLoadout.sqf
* Update fnc_onSelChangedLeft.sqf
* Update fnc_scanConfig.sqf
* Update docs/wiki/framework/arsenal-framework.md
Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
* Minor cleanup
* Baseweapon filtering
* Improvements + better unique items support
* Update fnc_fillRightPanel.sqf
* Update fnc_onSelChangedLeft.sqf
Fixed: Switching between weapons with incompatible primary magazines while a compatible secondary magazine is loaded doesn't equip the new weapon's primary magazine.
* Update addons/common/functions/fnc_uniqueUnitItems.sqf
Co-authored-by: PabstMirror <pabstmirror@gmail.com>
* undefined variable
Co-authored-by: PabstMirror <pabstmirror@gmail.com>
* fix undefined loadout var
* Update fnc_fillLoadoutsList.sqf
---------
Co-authored-by: Dystopian <sddex@ya.ru>
Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
Co-authored-by: PabstMirror <pabstmirror@gmail.com>
2023-07-21 18:25:25 +00:00
2022-08-25 16:56:54 +00:00
if ((_primaryWeaponArray param [0, ""]) == "ACE_FakePrimaryWeapon") then {
TRACE_1("Ignoring fake gun",_primaryWeaponArray);
_loadout set [0, []];
};
}] call CBA_fnc_addEventHandler;
2015-05-14 23:45:53 +00:00
GVAR(commonPostInited) = true;