diff --git a/README.md b/README.md deleted file mode 100644 index 9a2b580..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -OCAP-addon diff --git a/addons/@ocap/addons/ocap/config.cpp b/addons/@ocap/addons/ocap/config.cpp deleted file mode 100644 index 740304c..0000000 --- a/addons/@ocap/addons/ocap/config.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//////////////////////////////////////////////////////////////////// -//DeRap: ocap\config.bin -//Produced from mikero's Dos Tools Dll version 8.02 -//https://mikero.bytex.digital/Downloads -//'now' is Sun Apr 25 20:52:44 2021 : 'file' last modified on Tue Mar 16 12:25:11 2021 -//////////////////////////////////////////////////////////////////// - -#define _ARMA_ - -class CfgPatches -{ - class OCAP - { - - name = "OCAP2"; - author = "Dell, Zealot, Kurt, IndigoFox, Fank"; - authors[] = {"Dell", "Zealot", "Kurt", "IndigoFox", "Fank"}; - url = "https://github.com/OCAP2/OCAP"; - version = 1.1; - versionStr = "1.2.0-alpha"; - versionAr[] = {1, 1, 0}; - requiredAddons[] = {"A3_Functions_F","cba_main"}; - requiredVersion = 2.04; - units[] = {}; - weapons[] = {}; - }; -}; - -class CfgFunctions -{ - class OCAP - { - class null - { - file = "ocap\functions"; - class autostart { - preInit = 1; - }; - class init{}; - class addEventHandlers{}; - class addEventMission{}; - class eh_connected{}; - class eh_disconnected{}; - class eh_fired{}; - class eh_hit{}; - class eh_killed{}; - class exportData{}; - class extension{}; - class getDelay{}; - class getInstigator{}; - class getEventWeaponText{}; - class getUnitType{}; - class handleMarkers{}; - class handleCustomEvent{}; - class startCaptureLoop{}; - class trackAceExplLife{}; - class trackAceExplPlace{}; - class trackAceRemoteDet{}; - class trackAceThrowing{}; - class updateTime{}; - }; - }; -}; - -class CfgRemoteExec -{ - class Functions - { - class handleMarkers - { - allowedTargets = 2; - }; - class handleCustomEvent - { - allowedTargets = 2; - }; - class trackAceThrowing - { - allowedTargets = 0; - }; - }; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_addEventHandlers.sqf b/addons/@ocap/addons/ocap/functions/fn_addEventHandlers.sqf deleted file mode 100644 index 2ad7878..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_addEventHandlers.sqf +++ /dev/null @@ -1,41 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_addEventHandlers - -Description: - Used for applying unit-specific event handlers to units during initialization. These event handlers will trigger on the server. - - Applied during initialization of a unit in . - -Parameters: - _entity - Object to apply event handlers to. [Object] - _respawn - Determines if unit is initialized for the first time, or has respawned and does not need certain handlers reapplied. [Boolean, defaults to false] - -Returns: - Nothing - -Examples: - --- Code - [_unit] spawn ocap_fnc_addEventHandlers; - --- - -Public: - No - -Author: - IndigoFox, Fank ----------------------------------------------------------------------------- */ - -params ["_entity", ["_respawn", false]]; - -if ((_entity call BIS_fnc_objectType) # 0 == "Soldier") then { - _entity addEventHandler ["FiredMan", { _this spawn ocap_fnc_eh_fired; }]; -}; -_entity addMPEventHandler ["MPHit", { _this spawn ocap_fnc_eh_hit; }]; - -if ( - !_respawn && - (_entity call BIS_fnc_objectType) # 0 == "Soldier" && - isClass (configFile >> "CfgPatches" >> "ace_advanced_throwing") -) then { - ocap_fnc_trackAceThrowing remoteExec ["call", _entity]; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_addEventMission.sqf b/addons/@ocap/addons/ocap/functions/fn_addEventMission.sqf deleted file mode 100644 index 6c6fb26..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_addEventMission.sqf +++ /dev/null @@ -1,73 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_addEventMission - -Description: - Used for applying mission event handlers. - - * Applied during initialization of OCAP2 in . - -Parameters: - None - -Returns: - Nothing - -Examples: - --- Code - call ocap_fnc_addEventMission; - --- - -Public: - No - -Author: - IndigoFox, Dell ----------------------------------------------------------------------------- */ - -addMissionEventHandler["HandleDisconnect", { - _this call ocap_fnc_eh_disconnected; -}]; - -addMissionEventHandler["PlayerConnected", { - _this call ocap_fnc_eh_connected; -}]; - -addMissionEventHandler ["EntityKilled", { - _this call ocap_fnc_eh_killed; -}]; - -addMissionEventHandler ["EntityRespawned", { - params ["_entity", "_corpse"]; - - // Reset unit back to normal - _entity setvariable ["ocapIsKilled", false]; - - // Stop tracking old unit - if (_corpse getVariable ["ocap_isInitialised", false]) then { - _corpse setVariable ["ocap_exclude", true]; - - [_entity, true] spawn ocap_fnc_addEventHandlers; - }; -}]; - -if (isClass (configFile >> "CfgPatches" >> "ace_explosives")) then { - call ocap_fnc_trackAceExplPlace; -}; - -if (ocap_saveMissionEnded) then { - addMissionEventHandler ["MPEnded", { - ["Mission ended automatically"] call ocap_fnc_exportData; - }]; -}; - -// Custom event handler -ocap_customEvent_handle = ["ocap_handleCustomEvent", { - _this call ocap_fnc_handleCustomEvent; -}] call CBA_fnc_addEventHandler; - -// Add event saving markers -call ocap_fnc_handleMarkers; - -["WMT_fnc_EndMission", { - _this call ocap_fnc_exportData; -}] call CBA_fnc_addEventHandler; diff --git a/addons/@ocap/addons/ocap/functions/fn_autoStart.sqf b/addons/@ocap/addons/ocap/functions/fn_autoStart.sqf deleted file mode 100644 index 1ab2be6..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_autoStart.sqf +++ /dev/null @@ -1,27 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_autoStart - -Description: - Run during preInit to check for auto or manual start. Calls ocap_fnc_init. - -Parameters: - None - -Returns: - Nothing - -Examples: - call ocap_fnc_autoStart; - -Public: - Yes - -Author: - TyroneMF ----------------------------------------------------------------------------- */ - -#include "\userconfig\ocap\config.hpp" - -if (ocap_autoStart) then { - [] call ocap_fnc_init; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_eh_connected.sqf b/addons/@ocap/addons/ocap/functions/fn_eh_connected.sqf deleted file mode 100644 index 6a6f47a..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_eh_connected.sqf +++ /dev/null @@ -1,3 +0,0 @@ -[":EVENT:", - [ocap_captureFrameNo, "connected", _this select 2] -] call ocap_fnc_extension; diff --git a/addons/@ocap/addons/ocap/functions/fn_eh_disconnected.sqf b/addons/@ocap/addons/ocap/functions/fn_eh_disconnected.sqf deleted file mode 100644 index 137bf0c..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_eh_disconnected.sqf +++ /dev/null @@ -1,9 +0,0 @@ -params ["_unit", "_id", "_uid", "_name"]; - -[":EVENT:", - [ocap_captureFrameNo, "disconnected", _name] -] call ocap_fnc_extension; - -if (_unit getVariable ["ocap_isInitialised", false]) then { - _unit setVariable ["ocap_exclude", true]; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_eh_fired.sqf b/addons/@ocap/addons/ocap/functions/fn_eh_fired.sqf deleted file mode 100644 index f38aade..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_eh_fired.sqf +++ /dev/null @@ -1,179 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_eh_fired - -Description: - Tracks bullet and non-bullet projectiles. This is the code triggered when a unit firing is detected by the "FiredMan" Event Handler applied to units during . - -Parameters: - _firer - Unit the event handler is assigned to (the instigator) [Object] - _weapon - Fired weapon [String] - _muzzle - Muzzle that was used [String] - _mode - Current mode of the fired weapon [String] - _ammo - Ammo used [String] - _magazine - Magazine name which was used [String] - _projectile - Object of the projectile that was shot out [Object] - _vehicle - if weapon is vehicle weapon, otherwise objNull [Object] - -Returns: - Nothing - -Examples: - --- Code - --- - -Public: - No - -Author: - IndigoFox, Dell ----------------------------------------------------------------------------- */ - -params ["_firer", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle"]; - -_frame = ocap_captureFrameNo; - -// if (!isServer) exitWith {}; - -_ammoSimType = getText(configFile >> "CfgAmmo" >> _ammo >> "simulation"); - -// bullet handling, cut short -if (_ammoSimType isEqualTo "shotBullet") then { - [_projectile, _firer, _frame, _ammoSimType, _ammo] spawn { - params["_projectile", "_firer", "_frame", "_ammoSimType", "_ammo"]; - if (isNull _projectile) then { - _projectile = nearestObject [_firer, _ammo]; - }; - private _lastPos = []; - waitUntil { - _pos = getPosASL _projectile; - if (((_pos select 0) isEqualTo 0) || isNull _projectile) exitWith { - true - }; - _lastPos = _pos; - false; - }; - - if !((count _lastPos) isEqualTo 0) then { - [":FIRED:", [ - (_firer getVariable "ocap_id"), - _frame, - _lastPos - ]] call ocap_fnc_extension; - }; - }; - -} else { - - // simulation == "ShotSmokeX"; // M18 Smoke - // "ShotGrenade" // M67 - // "ShotRocket" // S-8 - // "ShotMissile" // R-27 - // "ShotShell" // VOG-17M, HE40mm - // "ShotIlluminating" // 40mm_green Flare - // "ShotMine" // Satchel remote - - _int = random 2000; - _muzzleDisp = getText(configFile >> "CfgWeapons" >> _weapon >> _muzzle >> "displayName"); - if (_muzzleDisp == "") then {_muzzleDisp = getText(configFile >> "CfgWeapons" >> _weapon >> "displayNameShort")}; - if (_muzzleDisp == "") then {_muzzleDisp = getText(configFile >> "CfgWeapons" >> _weapon >> "displayName")}; - _magDisp = getText(configFile >> "CfgMagazines" >> _magazine >> "displayNameShort"); - if (_magDisp == "") then {_magDisp = getText(configFile >> "CfgMagazines" >> _magazine >> "displayName")}; - if (_magDisp == "") then {_magDisp = getText(configFile >> "CfgAmmo" >> _ammo >> "displayNameShort")}; - if (_magDisp == "") then {_magDisp = getText(configFile >> "CfgAmmo" >> _ammo >> "displayName")}; - - // non-bullet handling - private ["_markTextLocal"]; - if (!isNull _vehicle) then { - _markTextLocal = format["[%3] %1 - %2", _muzzleDisp, _magDisp, ([configOf _vehicle] call BIS_fnc_displayName)]; - } else { - if (_ammoSimType isEqualTo "shotGrenade") then { - _markTextLocal = format["%1", _magDisp]; - } else { - _markTextLocal = format["%1 - %2", _muzzleDisp, _magDisp]; - }; - }; - - _markName = format["Projectile#%1", _int]; - _markColor = "ColorRed"; - _markerType = ""; - _magPic = (getText(configfile >> "CfgMagazines" >> _magazine >> "picture")); - if (_magPic == "") then { - _markerType = "mil_triangle"; - } else { - _magPicSplit = _magPic splitString "\"; - _magPic = _magPicSplit # ((count _magPicSplit) -1); - _markerType = format["magIcons/%1", _magPic]; - _markColor = "ColorWhite"; - }; - - - // _markStr = format["|%1|%2|%3|%4|%5|%6|%7|%8|%9|%10", - // _markName, - // getPos _firer, - // "mil_triangle", - // "ICON", - // [1, 1], - // 0, - // "Solid", - // "ColorRed", - // 1, - // _markTextLocal - // ]; - - // _markStr call BIS_fnc_stringToMarkerLocal; - - // diag_log text format["detected grenade, created marker %1", _markStr]; - - // _markStr = str _mark; - // _mark = createMarkerLocal [format["Projectile%1", _int],_projectile]; - // _mark setMarkerColorLocal "ColorRed"; - // _mark setMarkerTypeLocal "selector_selectable"; - // _mark setMarkerShapeLocal "ICON"; - // _mark setMarkerTextLocal format["%1 - %2", _firer, _markTextLocal]; - - _firerPos = getPosASL _firer; - ["ocap_handleMarker", ["CREATED", _markName, _firer, _firerPos, _markerType, "ICON", [1,1], getDirVisual _firer, "Solid", _markColor, 1, _markTextLocal, true]] call CBA_fnc_localEvent; - - if (_ammoSimType isEqualTo "shotSubmunitions") then { - private _subTypes = ((configFile >> "CfgAmmo" >> _ammo >> "submunitionAmmo") call BIS_fnc_getCfgDataArray) select {_x isEqualType ""}; - if (count _subTypes > 1) then { - waitUntil {isNull _projectile}; - }; - while {isNull _projectile} do { - { - _projSearch = nearestObject [_firer, _x]; - if !(isNull _projSearch) exitWith {_projectile = _projSearch}; - } forEach _subTypes; - }; - } else { - if (isNull _projectile) then { - _projectile = nearestObject [_firer, _ammo]; - }; - }; - - private _lastPos = []; - private _lastDir = 0; - waitUntil { - _pos = getPosASL _projectile; - _dir = getDirVisual _projectile; - if (((_pos select 0) isEqualTo 0) || isNull _projectile) exitWith { - true - }; - _lastPos = _pos; - _lastDir = _dir; - // params["_eventType", "_mrk_name", "_mrk_owner", "_pos", "_type", "_shape", "_size", "_dir", "_brush", "_color", "_alpha", "_text", "_forceGlobal"]; - ["ocap_handleMarker", ["UPDATED", _markName, _firer, _pos, "", "", "", _dir, "", "", 1]] call CBA_fnc_localEvent; - sleep 0.3; - false; - }; - - if !((count _lastPos) isEqualTo 0) then { - // if (count _lastPos == 3) then { - // params["_eventType", "_mrk_name", "_mrk_owner", "_pos", "_type", "_shape", "_size", "_dir", "_brush", "_color", "_alpha", "_text", "_forceGlobal"]; - ["ocap_handleMarker", ["UPDATED", _markName, _firer, _lastPos, "", "", "", _lastDir, "", "", 1]] call CBA_fnc_localEvent; - }; - sleep 10; - // deleteMarkerLocal _markName; - // }; - ["ocap_handleMarker", ["DELETED", _markName]] call CBA_fnc_localEvent; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_eh_hit.sqf b/addons/@ocap/addons/ocap/functions/fn_eh_hit.sqf deleted file mode 100644 index 9881a7d..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_eh_hit.sqf +++ /dev/null @@ -1,76 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_eh_hit - -Description: - Tracks when a unit is hit/takes damage. This is the code triggered by the "MPHit" Event Handler applied to units during . - -Parameters: - _unit - Object the event handler is assigned to. [Object] - _causedBy - Object that caused the damage. Contains the unit itself in case of collisions. [Object] - _damage - Level of damage caused by the hit. [Number] - _instigator - Object - Person who pulled the trigger. [Object] - -Returns: - Nothing - -Examples: - --- Code - --- - -Public: - No - -Author: - IndigoFox, Fank ----------------------------------------------------------------------------- */ - -#include "script_macros.hpp"; -params ["_unit", "_causedBy", "_damage", "_instigator"]; - -[_unit, _causedBy, _instigator] spawn { - params ["_unit", "_causedBy", "_instigator"]; - - if (isNull _instigator) then { - _instigator = [_unit, _causedBy] call ocap_fnc_getInstigator; - }; - - _unitID = _unit getVariable ["ocap_id", -1]; - if (_unitID == -1) exitWith {}; - private _eventData = [ocap_captureFrameNo, "hit", _unitID, ["null"], -1]; - - if (!isNull _instigator) then { - _causedById = _causedBy getVariable ["ocap_id", -1]; - _instigatorId = _instigator getVariable ["ocap_id", -1]; - - private _causedByInfo = []; - private _distanceInfo = 0; - if (_causedBy isKindOf "CAManBase" && _causedById > -1) then { - _causedByInfo = [ - _causedById, - ([_causedBy] call ocap_fnc_getEventWeaponText) - ]; - _distanceInfo = round (_unit distance _causedBy); - } else { - if (!isNull _instigator && _causedBy != _instigator && _instigator isKindOf "CAManBase" && _instigatorId > -1) then { - _causedByInfo = [ - _instigatorId, - ([_instigator] call ocap_fnc_getEventWeaponText) - ]; - _distanceInfo = round (_unit distance _instigator); - } else { - _causedByInfo = [_causedById]; - _distanceInfo = round (_unit distance _causedBy); - }; - }; - _eventData = [ - ocap_captureFrameNo, - "hit", - _unitID, - _causedByInfo, - _distanceInfo - ]; - }; - - DEBUG(_eventData); - [":EVENT:", _eventData] call ocap_fnc_extension; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_eh_killed.sqf b/addons/@ocap/addons/ocap/functions/fn_eh_killed.sqf deleted file mode 100644 index a6d9fb0..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_eh_killed.sqf +++ /dev/null @@ -1,80 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_eh_killed - -Description: - Tracks when a unit is killed. This is the code triggered by the "MPKilled" Event Handler applied to units during . - -Parameters: - _unit - Object the event handler is assigned to. [Object] - _killer - Object that killed the unit. [Object] - _instigator - Person who pulled the trigger. [Object] - _useEffects - same as useEffects in setDamage alt syntax. [Boolean] - -Returns: - Nothing - -Examples: - --- Code - --- - -Public: - No - -Author: - Dell, IndigoFox, Fank ----------------------------------------------------------------------------- */ - -#include "script_macros.hpp"; -params ["_victim", "_killer", "_instigator"]; -if !(_victim getvariable ["ocapIsKilled",false]) then { - _victim setvariable ["ocapIsKilled",true]; - - [_victim, _killer, _instigator] spawn { - params ["_victim", "_killer", "_instigator"]; - if (_killer == _victim) then { - private _time = diag_tickTime; - [_victim, { - _this setVariable ["ace_medical_lastDamageSource", (_this getVariable "ace_medical_lastDamageSource"), 2]; - }] remoteExec ["call", _victim]; - waitUntil {diag_tickTime - _time > 10 || !(isNil {_victim getVariable "ace_medical_lastDamageSource"})}; - _killer = _victim getVariable ["ace_medical_lastDamageSource", _killer]; - } else { - _killer - }; - - if (isNull _instigator) then { - _instigator = [_victim, _killer] call ocap_fnc_getInstigator; - }; - - // [ocap_captureFrameNo, "killed", _victimId, ["null"], -1]; - private _victimId = _victim getVariable ["ocap_id", -1]; - if (_victimId == -1) exitWith {}; - private _eventData = [ocap_captureFrameNo, "killed", _victimId, ["null"], -1]; - - if (!isNull _instigator) then { - _killerId = _instigator getVariable ["ocap_id", -1]; - if (_killerId == -1) exitWith {}; - - private _killerInfo = []; - if (_instigator isKindOf "CAManBase") then { - _killerInfo = [ - _killerId, - ([_instigator] call ocap_fnc_getEventWeaponText) - ]; - } else { - _killerInfo = [_killerId]; - }; - - _eventData = [ - ocap_captureFrameNo, - "killed", - _victimId, - _killerInfo, - round(_instigator distance _victim) - ]; - }; - - DEBUG(_eventData); - [":EVENT:", _eventData] call ocap_fnc_extension; - }; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_exportData.sqf b/addons/@ocap/addons/ocap/functions/fn_exportData.sqf deleted file mode 100644 index aadd168..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_exportData.sqf +++ /dev/null @@ -1,113 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_exportData - -Description: - This function facilitates the actual endMission and save events in the extension, prompting it to pack the mission and upload it to the web component. - - This function MUST be called in order to save a mission recording. A boolean true in the correct option of userconfig.hpp will automatically execute this function when the "MPEnded" Event Handler triggers. - -Parameters: - _side - The winning side [optional, Side] - _message - A custom description of how the victory was achieved [optional, String] - _tag - A custom tag to override that which is defined in userconfig.hpp that will make it filterable in web [optional, String] - -Returns: - Nothing - -Examples: - --- Code - // "Mission ended" - [] call ocap_fnc_exportData; - - // "BLUFOR Win." - [west] call ocap_fnc_exportData; - - // "OPFOR Win. OPFOR controlled all sectors! - [east, "OPFOR controlled all sectors!"] call ocap_fnc_exportData; - - // "Independent Win. INDFOR stole the intel!" - // Mission is saved under filterable "SnatchAndGrab" tag on web - [independent, "INDFOR stole the intel!", "SnatchAndGrab"] call ocap_fnc_exportData; - --- - -Public: - Yes - -Author: - Dell, Zealot, IndigoFox, TyroneMF ----------------------------------------------------------------------------- */ - -#include "script_macros.hpp" -if (!ocap_capture) exitWith {LOG(["fnc_exportData.sqf called, but recording hasn't started."]);}; - -[] spawn { - _realyTime = time - ocap_startTime; - _ocapTime = ocap_frameCaptureDelay * ocap_captureFrameNo; - LOG(ARR6("fnc_exportData.sqf: RealyTime =", _realyTime," OcapTime =", _ocapTime," delta =", _realyTime - _OcapTime)); -}; - -ocap_capture = false; -ocap_endFrameNo = ocap_captureFrameNo; - -publicVariable "ocap_endFrameNo"; - -params ["_side", "_message", "_tag"]; -switch (count _this) do { - case 0: { - [":EVENT:", [ocap_endFrameNo, "endMission", ["", "Mission ended"]]] call ocap_fnc_extension; - }; - case 1: { - [":EVENT:", [ocap_endFrameNo, "endMission", ["", _side]]] call ocap_fnc_extension; - }; - default { - private _sideString = str(_side); - if (_side == sideUnknown) then { _sideString = "" }; - [":EVENT:", [ocap_endFrameNo, "endMission", [_sideString, _message]]] call ocap_fnc_extension; - }; -}; - -if (ocap_needToSave) then { - if (!isNil "_tag") then { - [":SAVE:", [worldName, ocap_missionName, getMissionConfigValue ["author", ""], ocap_frameCaptureDelay, ocap_endFrameNo, _tag]] call ocap_fnc_extension; - LOG(ARR4("Saved recording of mission", ocap_missionName, "with tag", _tag)); - } else { - [":SAVE:", [worldName, ocap_missionName, getMissionConfigValue ["author", ""], ocap_frameCaptureDelay, ocap_endFrameNo]] call ocap_fnc_extension; - LOG(ARR3("Saved recording of mission", ocap_missionName, "with default tag")); - }; - - // briefingName is used here, no need for publicVariable for a simple confirmation log. - { - player createDiaryRecord [ - "OCAP2Info", - [ - "Status", - ( - "OCAP2 capture of " + briefingName + " has been exported with " + str(ocap_endFrameNo) + " frames saved." + - "

" + - "Upload results have been logged." - ) - ] - ]; - player setDiarySubjectPicture [ - "OCAP2Info", - "\A3\ui_f\data\igui\cfg\simpleTasks\types\upload_ca.paa" - ]; - } remoteExec ["call", 0, false]; -} else { - LOG(["ocap_needToSave is set to false. Not saving"]); - { - player createDiaryRecord [ - "OCAP2Info", - [ - "Status", - ( - "OCAP2 capture of " + briefingName + " has not been saved, as the configured criteria have not been met." - ) - ] - ]; - player setDiarySubjectPicture [ - "OCAP2Info", - "\A3\ui_f\data\igui\cfg\simpleTasks\types\danger_ca.paa" - ]; - } remoteExec ["call", 0, false]; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_getDelay.sqf b/addons/@ocap/addons/ocap/functions/fn_getDelay.sqf deleted file mode 100644 index b7f7768..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_getDelay.sqf +++ /dev/null @@ -1,40 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_exportData - -Description: - Determines the the appropriate interval at which to loop the function. - - Устанавливает точную задержку между кадрами - -Parameters: - None - -Returns: - Sleep duration [Number] - -Examples: - --- Code - call ocap_fnc_getDelay; - --- - -Public: - No - -Author: - Dell ----------------------------------------------------------------------------- */ - -#include "script_macros.hpp" -private "_sleep"; -isNil { - _relativelyTime = time - ocap_startTime; - _sleep = (ocap_captureFrameNo + 1) * ocap_frameCaptureDelay - _relativelyTime; - if ((ocap_captureFrameNo % 10) isEqualTo 0) then { - LOG(ARR4("DEBUG: Frame", ocap_captureFrameNo, "is created in ~", ocap_frameCaptureDelay - _sleep)); - }; - if (_sleep < 0) then { - LOG(ARR3("ERROR: Frame delay is negative", ocap_captureFrameNo, _sleep)); - _sleep = 0; - }; -}; -_sleep diff --git a/addons/@ocap/addons/ocap/functions/fn_getEventWeaponText.sqf b/addons/@ocap/addons/ocap/functions/fn_getEventWeaponText.sqf deleted file mode 100644 index 0ba8122..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_getEventWeaponText.sqf +++ /dev/null @@ -1,66 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_getEventWeaponText - -Description: - Used to identify the current weapon a unit is using that has injured or killed another. Will determine the handheld weapon or vehicle weapon they're using. - - Called during and . - -Parameters: - _instigator - The unit to evaluate [Object] - -Returns: - The description of weapon or vehicle > weapon. [String] - -Examples: - --- Code - [_instigator] call ocap_fnc_getEventWeaponText - --- - -Public: - No - -Author: - IndigoFox ----------------------------------------------------------------------------- */ - -params ["_instigator"]; - -if (vehicle _instigator isEqualTo _instigator) exitWith { - getText (configFile >> "CfgWeapons" >> currentWeapon _instigator >> "displayName"); -}; - -// pilot/driver doesn't return a value, so check for this -private _turPath = []; -if (count (assignedVehicleRole _instigator) > 1) then { - _turPath = assignedVehicleRole _instigator select 1; -} else { - _turPath = [-1]; -}; - -private _curVic = getText(configFile >> "CfgVehicles" >> (typeOf vehicle _instigator) >> "displayName"); -(weaponstate [vehicle _instigator, _turPath]) params ["_curWep", "_curMuzzle", "_curFiremode", "_curMag"]; -private _curWepDisplayName = getText(configFile >> "CfgWeapons" >> _curWep >> "displayName"); -private _curMagDisplayName = getText(configFile >> "CfgMagazines" >> _curMag >> "displayName"); -private _text = _curVic; -if (count _curMagDisplayName < 22) then { - if !(_curWepDisplayName isEqualTo "") then { - _text = _text + " [" + _curWepDisplayName; - if !(_curMagDisplayName isEqualTo "") then { - _text = _text + " / " + _curMagDisplayName + "]"; - } else { - _text = _text + "]" - }; - }; -} else { - if !(_curWepDisplayName isEqualTo "") then { - _text = _text + " [" + _curWepDisplayName; - if (_curWep != _curMuzzle && !(_curMuzzle isEqualTo "")) then { - _text = _text + " / " + _curMuzzle + "]"; - } else { - _text = _text + "]"; - }; - }; -}; - -_text; diff --git a/addons/@ocap/addons/ocap/functions/fn_getInstigator.sqf b/addons/@ocap/addons/ocap/functions/fn_getInstigator.sqf deleted file mode 100644 index 0ec5392..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_getInstigator.sqf +++ /dev/null @@ -1,47 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_getInstigator - -Description: - Attempts to identify who truly pulled the trigger on a kill event. - -Parameters: - _victim - Who was killed. [Object] - _killer - What caused the damage. [Object, default objNull] - _instigator - Who pulled the trigger, as reported by Arma. [Object, default objNull] - -Returns: - The true killer. [Object] - -Examples: - --- Code - [_victim, _killer] call ocap_fnc_getInstigator; - --- - -Public: - No - -Author: - Dell ----------------------------------------------------------------------------- */ - -params ["_victim", ["_killer", objNull], ["_instigator", objNull]]; - -if (isNull _instigator) then { - _instigator = UAVControl vehicle _killer select 0; -}; -if ((isNull _instigator) || (_instigator == _victim)) then { - _instigator = _killer; -}; -if (_instigator isKindOf "AllVehicles") then { - _instigator = call { - if(alive(gunner _instigator))exitWith{gunner _instigator}; - if(alive(commander _instigator))exitWith{commander _instigator}; - if(alive(driver _instigator))exitWith{driver _instigator}; - effectiveCommander _instigator - }; -}; -if (isNull _instigator) then { - _instigator = _killer; -}; - -_instigator; diff --git a/addons/@ocap/addons/ocap/functions/fn_getUnitType.sqf b/addons/@ocap/addons/ocap/functions/fn_getUnitType.sqf deleted file mode 100644 index 421bb6e..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_getUnitType.sqf +++ /dev/null @@ -1,76 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_getUnitType - -Description: - Identifies the role of a unit using similar methodology to Arma 3's. Used in . - -Parameters: - _unitToCheck - Unit to evaluate. [Object] - -Returns: - The role text. [String] - -Examples: - --- Code - [_x] call ocap_fnc_getUnitType; - --- - -Public: - No - -Author: - IndigoFox ----------------------------------------------------------------------------- */ - -params ["_unitToCheck"]; - -private _role = "Man"; -private _typePic = getText (configOf _unitToCheck >> "icon"); - - -switch (true) do { - case ( - ["Officer", _typePic] call BIS_fnc_inString - ): {_role = "Officer"}; - case ( - _unitToCheck == leader group _unitToCheck - ): {_role = "Leader"}; -}; - -if (_role == "Man") then { - switch (true) do { - case (_unitToCheck getUnitTrait 'medic'): { - _role = 'Medic'; - }; - case (_unitToCheck getUnitTrait 'engineer'): { - _role = 'Engineer'; - }; - case (_unitToCheck getUnitTrait 'explosiveSpecialist'): { - _role = 'ExplosiveSpecialist'; - }; - }; -}; - -if (_role == "Man") then { - private _weaponPicture = toLower getText (configFile >> "CfgWeapons" >> secondaryWeapon _unitToCheck >> "UiPicture"); - switch (true) do { - case ("_mg_" in _weaponPicture): {_role = "MG"}; - case ("_gl_" in _weaponPicture): {_role = "GL"}; - case ("_at_" in _weaponPicture): {_role = "AT"}; - case ("_sniper_" in _weaponPicture):{_role = "Sniper"}; - case ("_aa_" in _weaponPicture): {_role = "AA"}; - }; -}; - -if (_role == "Man") then { - private _weaponPicture = toLower getText (configFile >> "CfgWeapons" >> primaryWeapon _unitToCheck >> "UiPicture"); - switch (true) do { - case ("_mg_" in _weaponPicture): {_role = "MG"}; - case ("_gl_" in _weaponPicture): {_role = "GL"}; - case ("_at_" in _weaponPicture): {_role = "AT"}; - case ("_sniper_" in _weaponPicture):{_role = "Sniper"}; - case ("_aa_" in _weaponPicture): {_role = "AA"}; - }; -}; - -_role diff --git a/addons/@ocap/addons/ocap/functions/fn_handleCustomEvent.sqf b/addons/@ocap/addons/ocap/functions/fn_handleCustomEvent.sqf deleted file mode 100644 index 8d9a2db..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_handleCustomEvent.sqf +++ /dev/null @@ -1,53 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_handleCustomEvent - -Description: - Used for applying global event handlers. - - * Applied during initialization of OCAP2 in . - -Parameters: - _type - objective type that will define the text & icon [String, one of: "flag"] - _unit - name of the unit that performed the action [String] - _unitColor - color for the unit's name shown in Events list and for the pulse on the map [String, Hex RGB, defaults "" and will show as white] - _objectiveColor - color representing the icon in Events list [String, Hex RGB, defaults "" and will show as white] - _position - the location to pulse on the map [optional, PositionATL, default nil] - -Returns: - Nothing - -Examples: - --- Code - ["ocap_handleCustomEvent", ["eventType", "eventMessage"]] call CBA_fnc_serverEvent; - - // indicates a flag has been captured - ["ocap_handleCustomEvent", ["captured", [ - "flag", - name _unit, - str side group _unit, - "#FF0000", - getPosAtl _flag - ]]] call call CBA_fnc_serverEvent; - - - // Not yet implemented - ["ocap_handleCustomEvent", ["captured", [ - "sector", - name _unit, - str side group _unit, - "#FF0000", - getPosAtl _sectorObject - ]]] call call CBA_fnc_serverEvent; - --- - -Public: - Yes - -Author: - Fank, Zealot ----------------------------------------------------------------------------- */ - -params ["_eventName", "_eventMessage"]; -[":EVENT:", - [ocap_captureFrameNo, _eventName, _eventMessage] -] call ocap_fnc_extension; diff --git a/addons/@ocap/addons/ocap/functions/fn_handleMarkers.sqf b/addons/@ocap/addons/ocap/functions/fn_handleMarkers.sqf deleted file mode 100644 index ed0c753..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_handleMarkers.sqf +++ /dev/null @@ -1,292 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_handleMarkers - -Description: - Used for tracking all markers in the vanilla Arma 3 system. - - This function creates a server-side CBA listener as well as local Event Handlers on the server and all clients. It facilitates marker creation, modification, and deletion that occurs across any machine or on the server. - - Delays are integrated into the system to allow for multi-line scripted marker creations during a mission to reflect correctly in the created marker during playback. These delays are accounted for so that playback reflects the true creation time. - - Due to the nature of locality and single-view playback, markers of the same name which exist in different states on different clients may display odd behavior during playback. - - Marker exclusion as configured in userconfig.hpp is handled client-side for performance reasons. - - * Applied during mission event handler application in . - -Parameters: - None - -Returns: - Nothing - -Examples: - --- Code - call ocap_fnc_handleMarkers; - --- - -Public: - Yes - -Author: - IndigoFox, Fank ----------------------------------------------------------------------------- */ - -#include "\userconfig\ocap\config.hpp" -#include "script_macros.hpp" - -// array: ocap_markers_tracked -// Persistent global variable on server that defines unique marker names currently being tracked. -// Entries are added at marker create events and removed at marker delete events to avoid duplicate processing. -ocap_markers_tracked = []; // Markers which we saves into replay - -// On the dedicated server, the color of the markers is blue -{ - _x params ["_name", "_color"]; - profilenamespace setVariable [_name, _color]; -} forEach [ - ["map_blufor_r", 0], - ["map_blufor_g", 0.3], - ["map_blufor_b", 0.6], - ["map_independent_r", 0], - ["map_independent_g", 0.5], - ["map_independent_b", 0], - ["map_civilian_r", 0.4], - ["map_civilian_g", 0], - ["map_civilian_b", 0.5], - ["map_unknown_r", 0.7], - ["map_unknown_g", 0.6], - ["map_unknown_b", 0], - ["map_opfor_r", 0.5], - ["map_opfor_g", 0], - ["map_opfor_b", 0] -]; - -// create CBA event handler to be called on server -ocap_markers_handle = ["ocap_handleMarker", { - params["_eventType", "_mrk_name", "_mrk_owner", "_pos", "_type", "_shape", "_size", "_dir", "_brush", "_color", "_alpha", "_text", ["_forceGlobal", false], ["_creationTime", 0]]; - - switch (_eventType) do { - - case "CREATED":{ - DEBUG(ARR2("MARKER:CREATE: Processing marker data -- ", _this)); - - if (_mrk_name in ocap_markers_tracked) exitWith { - DEBUG(ARR3("MARKER:CREATE: Marker", _mrk_name, "already tracked, exiting")); - }; - - DEBUG(ARR4("MARKER:CREATE: Valid CREATED process of marker from", _mrk_owner, "for", _mrk_name)); - - if (_type isEqualTo "") then {_type = "mil_dot"}; - ocap_markers_tracked pushBackUnique _mrk_name; - - private _mrk_color = ""; - if (_color == "Default") then { - _mrk_color = (configfile >> "CfgMarkers" >> _type >> "color") call BIS_fnc_colorConfigToRGBA call bis_fnc_colorRGBtoHTML; - } else { - _mrk_color = (configfile >> "CfgMarkerColors" >> _color >> "color") call BIS_fnc_colorConfigToRGBA call bis_fnc_colorRGBtoHTML; - }; - - private ["_sideOfMarker"]; - if (_mrk_owner isEqualTo objNull) then { - _forceGlobal = true; - _mrk_owner = -1; - _sideOfMarker = -1; - } else { - _sideOfMarker = (side _mrk_owner) call BIS_fnc_sideID; - _mrk_owner = _mrk_owner getVariable["ocap_id", 0]; - }; - - if (_sideOfMarker isEqualTo 4 || - (["Projectile#", _mrk_name] call BIS_fnc_inString) || - (["Detonation#", _mrk_name] call BIS_fnc_inString) || - (["Mine#", _mrk_name] call BIS_fnc_inString) || - (["ObjectMarker", _mrk_name] call BIS_fnc_inString) || - (["moduleCoverMap", _mrk_name] call BIS_fnc_inString) || - _forceGlobal) then {_sideOfMarker = -1}; - - private ["_polylinePos"]; - if (count _pos > 3) then { - _polylinePos = []; - for [{_i = 0}, {_i < ((count _pos) - 1)}, {_i = _i + 1}] do { - _polylinePos pushBack [_pos # (_i), _pos # (_i + 1)]; - _i = _i + 1; - }; - _pos = _polylinePos; - }; - - if (isNil "_dir") then { - _dir = 0; - } else {if (_dir isEqualTo "") then {_dir = 0}}; - - private _captureFrameNo = ocap_captureFrameNo; - if (_creationTime > 0) then { - private _delta = time - _creationTime; - private _lastFrameTime = (ocap_captureFrameNo * ocap_frameCaptureDelay) + ocap_startTime; - if (_delta > (time - _lastFrameTime)) then { // marker was initially created in some frame(s) before - _captureFrameNo = ceil _lastFrameTime - (_delta / ocap_frameCaptureDelay); - private _logParams = (str [ocap_captureFrameNo, time, _creationTime, _delta, _lastFrameTime, _captureFrameNo]); - DEBUG(ARR2("CREATE:MARKER: adjust frame ", _logParams)); - }; - }; - - private _logParams = (str [_mrk_name, _dir, _type, _text, _captureFrameNo, -1, _mrk_owner, _mrk_color, _size, _sideOfMarker, _pos, _shape, _alpha, _brush]); - DEBUG(ARR4("CREATE:MARKER: Valid CREATED process of", _mrk_name, ", sending to extension -- ", _logParams)); - - [":MARKER:CREATE:", [_mrk_name, _dir, _type, _text, _captureFrameNo, -1, _mrk_owner, _mrk_color, _size, _sideOfMarker, _pos, _shape, _alpha, _brush]] call ocap_fnc_extension; - }; - - case "UPDATED":{ - - if (_mrk_name in ocap_markers_tracked) then { - if (isNil "_dir") then {_dir = 0}; - - if (ocap_isDebug) then { - private _logParams = str [_mrk_name, ocap_captureFrameNo, _pos, _dir, _alpha]; - DEBUG(ARR4("MARKER:MOVE: Valid UPDATED process of", _mrk_name, ", sending to extension -- ", _logParams)); - }; - - [":MARKER:MOVE:", [_mrk_name, ocap_captureFrameNo, _pos, _dir, _alpha]] call ocap_fnc_extension; - }; - }; - - case "DELETED":{ - - if (_mrk_name in ocap_markers_tracked) then { - DEBUG(ARR3("MARKER:DELETE: Marker", _mrk_name, "deleted")); - [":MARKER:DELETE:", [_mrk_name, ocap_captureFrameNo]] call ocap_fnc_extension; - ocap_markers_tracked = ocap_markers_tracked - [_mrk_name]; - }; - }; - }; -}] call CBA_fnc_addEventHandler; - - - - - -// handle created markers -{ - addMissionEventHandler["MarkerCreated", { - params["_marker", "_channelNumber", "_owner", "_local"]; - - if (!_local) exitWith {}; - - // check for excluded values in marker name. if name contains at least one value, skip sending traffic to server - // if value is undefined, then skip - private _isExcluded = false; - if (!isNil "ocap_excludeMarkerFromRecord") then { - { - if ((str _marker) find _x >= 0) exitWith { - _isExcluded = true; - }; - } forEach ocap_excludeMarkerFromRecord; - }; - if (_isExcluded) exitWith {}; - - private _event = _this; - _event pushBack time; - - [{ - params["_marker", "_channelNumber", "_owner", "_local", "_creationTime"]; - _pos = ATLToASL (markerPos [_marker, true]); - _type = markerType _marker; - _shape = markerShape _marker; - _size = markerSize _marker; - _dir = markerDir _marker; - _brush = markerBrush _marker; - _color = markerColor _marker; - _text = markerText _marker; - _alpha = markerAlpha _marker; - _polyline = markerPolyline _marker; - if (count _polyline != 0) then { - _pos = _polyline; - }; - - ["ocap_handleMarker", ["CREATED", _marker, _owner, _pos, _type, _shape, _size, _dir, _brush, _color, _alpha, _text, false, _creationTime]] call CBA_fnc_serverEvent; - }, _event, 2] call CBA_fnc_waitAndExecute; - }]; - - // handle marker moves/updates - addMissionEventHandler["MarkerUpdated", { - params["_marker", "_local"]; - - if (!_local) exitWith {}; - - // check for excluded values in marker name. if name contains at least one value, skip sending traffic to server - // if value is undefined, then skip - private _isExcluded = false; - if (!isNil "ocap_excludeMarkerFromRecord") then { - { - if ((str _marker) find _x >= 0) exitWith { - _isExcluded = true; - }; - } forEach ocap_excludeMarkerFromRecord; - }; - if (_isExcluded) exitWith {}; - - private _pos = ATLToASL (markerPos [_marker, true]); - - ["ocap_handleMarker", ["UPDATED", _marker, player, _pos, "", "", "", markerDir _marker, "", "", markerAlpha _marker]] call CBA_fnc_serverEvent; - }]; - - // handle marker deletions - addMissionEventHandler["MarkerDeleted", { - params["_marker", "_local"]; - - if (!_local) exitWith {}; - - // check for excluded values in marker name. if name contains at least one value, skip sending traffic to server - // if value is undefined, then skip - private _isExcluded = false; - if (!isNil "ocap_excludeMarkerFromRecord") then { - { - if ((str _marker) find _x > 0) exitWith { - _isExcluded = true; - }; - } forEach ocap_excludeMarkerFromRecord; - }; - if (_isExcluded) exitWith {}; - - ["ocap_handleMarker", ["DELETED", _marker, player]] call CBA_fnc_serverEvent; - }]; -} remoteExec["call", 0, true]; - - - -// collect all initial markers & add event handlers to clients -[ - {count allPlayers > 0}, - { - { - private _marker = _x; - // "Started polling starting markers" remoteExec ["hint", 0]; - // get intro object markers - _pos = ATLToASL (markerPos [_marker, true]); - _type = markerType _marker; - _shape = markerShape _marker; - _size = markerSize _marker; - _dir = markerDir _marker; - _brush = markerBrush _marker; - _color = markerColor _marker; - _text = markerText _marker; - _alpha = markerAlpha _marker; - _polyline = markerPolyline _marker; - if (count _polyline != 0) then { - _pos = _polyline; - }; - - if (isNil "_dir") then { - _dir = 0; - } else {if (_dir isEqualTo "") then {_dir = 0}}; - - _forceGlobal = true; - - // "_eventType", "_mrk_name", "_mrk_owner","_pos", "_type", "_shape", "_size", "_dir", "_brush", "_color", "_alpha", "_text", "_forceGlobal" - ["ocap_handleMarker", ["CREATED", _marker, objNull, _pos, _type, _shape, _size, _dir, _brush, _color, _alpha, _text, _forceGlobal]] call CBA_fnc_localEvent; - - } forEach (allMapMarkers); - - LOG(["GETINITIALMARKERS: Successfully parsed init-scripted and editor-placed markers"]); - } -] call CBA_fnc_waitUntilAndExecute; diff --git a/addons/@ocap/addons/ocap/functions/fn_init.sqf b/addons/@ocap/addons/ocap/functions/fn_init.sqf deleted file mode 100644 index 282c3d9..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_init.sqf +++ /dev/null @@ -1,107 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_init - -Description: - Automatic Start: Called from ocap_fnc_autoStart. - Manual Start: Server execution to begin. - -Parameters: - None - -Returns: - Nothing - -Examples: - --- Code - call ocap_fnc_init; - --- - -Public: - No - -Author: - Dell, Zealot, IndigoFox ----------------------------------------------------------------------------- */ - -#include "\userconfig\ocap\config.hpp" -#include "script_macros.hpp" - -// bool: ocap_capture -ocap_capture = false; -// int: ocap_captureFrameNo -ocap_captureFrameNo = 0; -// bool: ocap_needToSave -ocap_needToSave = [false, true] select (ocap_minMissionTime < 10); - -if (ocap_excludeMarkerFromRecord isEqualType []) then { - publicVariable "ocap_excludeMarkerFromRecord"; -} else { - LOG(["excludeMarkerFromRecord in config is not an array, skipping exclusions"]); -}; - -// macro: OCAP_ADDON_VERSION -ocap_addon_ver = OCAP_ADDON_VERSION; -publicVariable "ocap_addon_ver"; - -ocap_extension_ver = ([":VERSION:", []] call ocap_fnc_extension); -publicVariable "ocap_extension_ver"; - - -{ - [{!isNil "ocap_addon_ver" && !isNil "ocap_extension_ver"}, { - player createDiarySubject ["OCAP2Info", "OCAP2 AAR", "\A3\ui_f\data\igui\cfg\simpleTasks\types\whiteboard_ca.paa"]; - - ocap_fnc_copyGitHubToClipboard = {copyToClipboard "https://github.com/OCAP2/OCAP"; systemChat "OCAP2 GitHub link copied to clipboard";}; - ocap_diaryAbout = player createDiaryRecord [ - "OCAP2Info", - [ - "About", - ( - "OCAP2
" + - "Addon version: " + ocap_addon_ver + - "
" + - "Extension version: " + (ocap_extension_ver # 0) + " (built " + (ocap_extension_ver # 1) + ")" + - "
" + - "https://github.com/OCAP2/OCAP" + - "

" + - "OCAP2 is a server-side Arma 3 recording suite that provides web-based playback of all units, vehicles, markers, and projectiles present, placed, and fired during a mission." + - "

" + - "Recording status can be found in the Status section." + - "

" + - "DISCLAIMER: This mission may be recorded and made publicly available at the discretion of the server administrators. Please be aware that your actions during this mission will be tracked and attributed to your in-game username." - ) - ] - ]; - - ocap_diaryStatus = player createDiaryRecord [ - "OCAP2Info", - [ - "Status", - "OCAP2 initialized. Awaiting configured capture conditions." - ] - ]; - }] call CBA_fnc_waitUntilAndExecute; -} remoteExecCall ["call", 0, true]; - -// Support both methods of setting mission name. -ocap_missionName = getMissionConfigValue ["onLoadName", ""]; -if (ocap_missionName == "") then { - ocap_missionName = briefingName; -}; - -// Add event missions -call ocap_fnc_addEventMission; -[":START:", [worldName, ocap_missionName, getMissionConfigValue ["author", ""], ocap_frameCaptureDelay]] call ocap_fnc_extension; -0 spawn ocap_fnc_startCaptureLoop; - -[":SET:VERSION:", [OCAP_ADDON_VERSION]] call ocap_fnc_extension; - -0 spawn { - if (ocap_needToSave) exitWith {}; - LOG(["Waiting freeze end!"]); - waitUntil {sleep 1.4; missionNamespace getVariable["WMT_pub_frzState", 3] >= 3}; - LOG(["Waiting until ocap_minMissionTime ends"]); - sleep ocap_minMissionTime; - LOG(["ocap_needToSave is set to true"]); - ocap_needToSave = true; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_startCaptureLoop.sqf b/addons/@ocap/addons/ocap/functions/fn_startCaptureLoop.sqf deleted file mode 100644 index ddee340..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_startCaptureLoop.sqf +++ /dev/null @@ -1,212 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_startCaptureLoop - -Description: - Iterates through units, declares they exist, and conditional records their state at an interval defined in userconfig.hpp. - - This is the core processing loop that determines when new units enter the world, all the details about them, classifies which to exclude, and determines their health/life status. It has both unit and vehicle tracking. - - This is spawned during . - -Parameters: - None - -Returns: - Nothing - -Examples: - --- Code - 0 spawn ocap_fnc_startCaptureLoop; - --- - -Public: - No - -Author: - Dell, Zealot, IndigoFox, Fank ----------------------------------------------------------------------------- */ - -#include "\userconfig\ocap\config.hpp" -#include "script_macros.hpp" - -// Function: _isKindOfApc -// Determines whether the vehicle is an APC by checking class inheritance -private _isKindOfApc = { - _bool = false; - { - if (_this isKindOf _x) exitWith {_bool = true;};false - } count ["Wheeled_APC_F","Tracked_APC","APC_Wheeled_01_base_F","APC_Wheeled_02_base_F", - "APC_Wheeled_03_base_F","APC_Tracked_01_base_F","APC_Tracked_02_base_F","APC_Tracked_03_base_F"]; - _bool -}; - -// Function: _getClass -// Gets generalized 'class' of vehicle to determine what icon to assign during playback -private _getClass = { - if (_this isKindOf "Truck_F") exitWith {"truck"}; // Should be higher than Car - if (_this call _isKindOfApc) exitWith {"apc"}; - if (_this isKindOf "Car") exitWith {"car"}; - if (_this isKindOf "Tank") exitWith {"tank"}; - if (_this isKindOf "StaticMortar") exitWith {"static-mortar"}; - if (_this isKindOf "StaticWeapon") exitWith {"static-weapon"}; - if (_this isKindOf "ParachuteBase") exitWith {"parachute"}; - if (_this isKindOf "Helicopter") exitWith {"heli"}; - if (_this isKindOf "Plane") exitWith {"plane"}; - if (_this isKindOf "Air") exitWith {"plane"}; - if (_this isKindOf "Ship") exitWith {"sea"}; - "unknown" -}; - - - - -waitUntil{(count(allPlayers) >= ocap_minPlayerCount)}; - -// bool: ocap_capture -ocap_capture = true; -ocap_startTime = time; -LOG(ARR3(__FILE__, "ocap_capture start, time:", ocap_startTime)); - -{ - [{!isNull player}, { - player createDiaryRecord [ - "OCAP2Info", - [ - "Status", - "OCAP2 recording conditions met -- beginning capture." - ], taskNull, "", false - ]; - player setDiarySubjectPicture [ - "OCAP2Info", - "\A3\ui_f\data\igui\cfg\simpleTasks\types\use_ca.paa" - ]; - }] call CBA_fnc_waitUntilAndExecute; -} remoteExecCall ["call", 0, true]; - - -[] call ocap_fnc_updateTime; - -private _id = 0; -while {ocap_capture} do { - isNil { - if (ocap_captureFrameNo == 10 || (ocap_captureFrameNo > 10 && ocap_trackTimes && ocap_captureFrameNo % ocap_trackTimeInterval == 0)) then { - [] call ocap_fnc_updateTime; - }; - - if (ocap_captureFrameNo % (60 / ocap_frameCaptureDelay) == 0) then { - publicVariable "ocap_captureFrameNo"; - { - player createDiaryRecord [ - "OCAP2Info", - [ - "Status", - ("Capture frame: " + str(ocap_captureFrameNo) + "") - ] - ]; - } remoteExecCall ["call", 0, false]; - }; - - { - if !(_x getVariable ["ocap_isInitialised", false]) then { - if (_x isKindOf "Logic") exitWith { - _x setVariable ["ocap_exclude", true]; - _x setVariable ["ocap_isInitialised", true]; - }; - _x setVariable ["ocap_id", _id]; - [":NEW:UNIT:", [ - ocap_captureFrameNo, //1 - _id, //2 - name _x, //3 - groupID (group _x), //4 - str side group _x, //5 - BOOL(isPlayer _x), //6 - roleDescription _x // 7 - ]] call ocap_fnc_extension; - [_x] spawn ocap_fnc_addEventHandlers; - _id = _id + 1; - _x setVariable ["ocap_isInitialised", true]; - }; - if !(_x getVariable ["ocap_exclude", false]) then { - private _unitRole = _x getVariable ["ocap_unitType", ""]; - if (ocap_captureFrameNo % 10 == 0 || _unitRole == "") then { - _unitRole = [_x] call ocap_fnc_getUnitType; - _x setVariable ["ocap_unitType", _unitRole]; - }; - - private _lifeState = 0; - if (alive _x) then { - if (ocap_preferACEUnconscious && !isNil "ace_common_fnc_isAwake") then { - _lifeState = if ([_x] call ace_common_fnc_isAwake) then {1} else {2}; - } else { - _lifeState = if (lifeState _x isEqualTo "INCAPACITATED") then {2} else {1}; - }; - }; - - _pos = getPosASL _x; - [":UPDATE:UNIT:", [ - (_x getVariable "ocap_id"), //1 - _pos, //2 - round getDir _x, //3 - _lifeState, //4 - BOOL(!((vehicle _x) isEqualTo _x)), //5 - if (alive _x) then {name _x} else {""}, //6 - BOOL(isPlayer _x), //7 - _unitRole //8 - ]] call ocap_fnc_extension; - }; - false - } count (allUnits + allDeadMen); - - { - if !(_x getVariable ["ocap_isInitialised", false]) then { - _vehType = typeOf _x; - _class = _vehType call _getClass; - _toExcludeKind = false; - if (count ocap_excludeKindFromRecord > 0) then { - private _vic = _x; - { - if (_vic isKindOf _x) exitWith { - _toExcludeKind = true; - }; - } forEach ocap_excludeKindFromRecord; - }; - if ((_class isEqualTo "unknown") || (_vehType in ocap_excludeClassFromRecord) || _toExcludeKind) exitWith { - LOG(ARR2("WARNING: vehicle is defined as 'unknown' or exclude:", _vehType)); - _x setVariable ["ocap_isInitialised", true]; - _x setVariable ["ocap_exclude", true]; - }; - - _x setVariable ["ocap_id", _id]; - [":NEW:VEH:", [ - ocap_captureFrameNo, //1 - _id, //2 - _class, //3 - getText (configFile >> "CfgVehicles" >> _vehType >> "displayName") //4 - ]] call ocap_fnc_extension; - [_x] spawn ocap_fnc_addEventHandlers; - _id = _id + 1; - _x setVariable ["ocap_isInitialised", true]; - }; - if !(_x getVariable ["ocap_exclude", false]) then { - private _crew = []; - { - if (_x getVariable ["ocap_isInitialised", false]) then { - _crew pushBack (_x getVariable "ocap_id"); - }; false - } count (crew _x); - _pos = getPosASL _x; - [":UPDATE:VEH:", [ - (_x getVariable "ocap_id"), //1 - _pos, //2 - round getDir _x, //3 - BOOL(alive _x), //4 - _crew, //5 - ocap_captureFrameNo // 6 - ]] call ocap_fnc_extension; - }; - false - } count vehicles; - }; - sleep (call ocap_fnc_getDelay); - ocap_captureFrameNo = ocap_captureFrameNo + 1; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_trackAceExplLife.sqf b/addons/@ocap/addons/ocap/functions/fn_trackAceExplLife.sqf deleted file mode 100644 index 53f1b32..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_trackAceExplLife.sqf +++ /dev/null @@ -1,71 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_trackAceExplLife - -Description: - Triggered in and monitors the status of a mine to ensure markers during playback reflect arm/disarm/detonation of mines. - -Parameters: - _unarmedPlacement - The CfgMagazines item that was placed. [Object] - _placedPos - The position it was placed at. [PositionAGLS] - -Returns: - Nothing - -Examples: - --- Code - [(_this # 0), _placedPos] spawn ocap_fnc_trackAceExplLife; - --- - -Public: - No - -Author: - IndigoFox ----------------------------------------------------------------------------- */ - -waitUntil {isNull (_this # 0)}; -sleep 1; -params ["_unarmedPlacement", "_placedPos"]; - -_nearMines = []; -_nearMines append (_placedPos nearObjects ["TimeBombCore", 5]); -_nearMines append (_placedPos nearObjects ["APERSMine_Range_Ammo", 5]); -_nearMines append (_placedPos nearObjects ["ATMine_Range_Ammo", 5]); - -if (_nearMines isEqualTo []) then { - exit; -} else { - _armedMine = _nearMines # 0; - - _int = random 2000; - - _explType = typeOf _armedMine; - _explosiveMag = getText(configFile >> "CfgAmmo" >> _explType >> "defaultMagazine"); - _explosiveDisp = getText(configFile >> "CfgMagazines" >> _explosiveMag >> "displayName"); - - _placedPos = getPosASL _armedMine; - _placer = _placedPos nearestObject "Man"; - _placer addOwnedMine _armedMine; - - _markTextLocal = format["%1", _explosiveDisp]; - _markName = format["Mine#%1/%2", _int, _placedPos]; - _markColor = "ColorRed"; - _markerType = "Minefield"; - - ["ocap_handleMarker", ["CREATED", _markName, _placer, _placedPos, _markerType, "ICON", [1,1], 0, "Solid", "ColorRed", 1, _markTextLocal, true]] call CBA_fnc_localEvent; - - waitUntil {isNull _armedMine}; - - ["ocap_handleMarker", ["DELETED", _markName]] call CBA_fnc_localEvent; - - _markerType = "waypoint"; - _markName = format["Detonation#%1", _int]; - - ["ocap_handleMarker", ["CREATED", _markName, _placer, _placedPos, _markerType, "ICON", [1,1], 0, "Solid", _markColor, 1, _markTextLocal, true]] call CBA_fnc_localEvent; - - [_markName] spawn { - params ["_markName"]; - sleep 10; - ["ocap_handleMarker", ["DELETED", _markName]] call CBA_fnc_localEvent; - }; -}; diff --git a/addons/@ocap/addons/ocap/functions/fn_trackAceExplPlace.sqf b/addons/@ocap/addons/ocap/functions/fn_trackAceExplPlace.sqf deleted file mode 100644 index 2a99ed6..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_trackAceExplPlace.sqf +++ /dev/null @@ -1,34 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_trackAceExplPlace - -Description: - Adds Init code for any ACE_Explosives_Place object that is created, i.e. when a unit uses ACE self-interaction to place down an explosive. - - The Init code will spawn an instance of . - -Parameters: - None - -Returns: - Nothing - -Examples: - --- Code - call ocap_fnc_trackAceExplPlace; - --- - -Public: - No - -Author: - IndigoFox ----------------------------------------------------------------------------- */ - -// on any ACE explosive or mine *placement* via interaction menu, will execute the code here -["ACE_Explosives_Place", "init", { - - if (!isServer) exitWith {}; - _placedPos = getPosASL (_this # 0); - [(_this # 0), _placedPos] spawn ocap_fnc_trackAceExplLife; - -}] call CBA_fnc_addClassEventHandler; diff --git a/addons/@ocap/addons/ocap/functions/fn_trackAceRemoteDet.sqf b/addons/@ocap/addons/ocap/functions/fn_trackAceRemoteDet.sqf deleted file mode 100644 index b9aaa75..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_trackAceRemoteDet.sqf +++ /dev/null @@ -1,30 +0,0 @@ -// LOG ACE REMOTE DET EVENTS -[{ - params ["_unit", "_range", "_explosive", "_fuzeTime", "_triggerItem"]; - - _int = random 2000; - - // expl is ammo, need to find mag, and display name of mag - _explosiveMag = getText(configFile >> "CfgAmmo" >> (typeOf _explosive) >> "defaultMagazine"); - _explosiveDisp = getText(configFile >> "CfgMagazines" >> _explosiveMag >> "displayName"); - _triggerItemDisp = getText(configFile >> "CfgWeapons" >> _triggerItem >> "displayName"); - - _markTextLocal = format["%1", _explosiveDisp]; - _markName = format["Detonation#%1", _int]; - _markColor = "ColorRed"; - _markerType = "waypoint"; - _pos = getPosASL _explosive; - - ["ocap_handleMarker", ["CREATED", _markName, _unit, _pos, _markerType, "ICON", [1,1], 0, "Solid", "ColorRed", 1, _markTextLocal, true]] call CBA_fnc_serverEvent; - - [_markName] spawn { - params ["_markName"]; - - sleep 10; - // [format['["ocap_handleMarker", ["DELETED", %1]] call CBA_fnc_serverEvent;', _markName]] remoteExec ["hint", 0]; - // systemChat format['["ocap_handleMarker", ["DELETED", %1]] call CBA_fnc_serverEvent;', _markName]; - ["ocap_handleMarker", ["DELETED", _markName]] call CBA_fnc_serverEvent; - }; - true; - -}] call ace_explosives_fnc_addDetonateHandler; diff --git a/addons/@ocap/addons/ocap/functions/fn_trackAceThrowing.sqf b/addons/@ocap/addons/ocap/functions/fn_trackAceThrowing.sqf deleted file mode 100644 index c61c350..0000000 --- a/addons/@ocap/addons/ocap/functions/fn_trackAceThrowing.sqf +++ /dev/null @@ -1,142 +0,0 @@ -/* ---------------------------------------------------------------------------- -Script: ocap_fnc_trackAceThrowing - -Description: - Adds a local CBA event listener on units that will trigger when a projectile is thrown using ACE Advanced Throwing and add markers to playback that trace its path. Added to units in . - -Parameters: - None - -Returns: - Nothing - -Examples: - --- Code - ocap_fnc_trackAceThrowing remoteExec ["call", _entity]; - --- - -Public: - No - -Author: - IndigoFox ----------------------------------------------------------------------------- */ - -trackThrows = ["ace_throwableThrown", { - _this spawn { - - params["_unit", "_projectile"]; - - if (isNull _projectile) then { - _projectile = nearestObject [_unit, "CA_Magazine"]; - }; - - // systemChat str _this; - - // note that thrown objects outside of ACE explosives do not include a "default magazine" property in their config. - // this script will attempt to find a matching classname in CfgMagazines, as some chemlights and smokes are built this way. - // if not found, a default magazine value will be assigned (m67 frag, white smoke, green chemlight) - - _projType = typeOf _projectile; - _projConfig = configOf _projectile; - _projName = getText(configFile >> "CfgAmmo" >> _projType >> "displayName"); - - // systemChat format["Config name: %1", configOf _projectile]; - - _ammoSimType = getText(configFile >> "CfgAmmo" >> _projType >> "simulation"); - // systemChat format["Projectile type: %1", _ammoSimType]; - - _markerType = ""; - _markColor = ""; - _magDisp = ""; - _magPic = ""; - - _magType = getText(_projConfig >> "defaultMagazine"); - if (_magType == "") then { - _magType = configName(configfile >> "CfgMagazines" >> _projType) - }; - - if (!(_magType isEqualTo "")) then { - // systemChat format["Mag type: %1", _magType]; - - _magDisp = getText(configFile >> "CfgMagazines" >> _magType >> "displayNameShort"); - if (_magDisp == "") then { - _magDisp = getText(configFile >> "CfgMagazines" >> _magType >> "displayName") - }; - if (_magDisp == "") then { - _magDisp = _projName; - }; - - _magPic = (getText(configfile >> "CfgMagazines" >> _magType >> "picture")); - // hint parseText format["Projectile fired:
", _magPic]; - if (_magPic == "") then { - _markerType = "mil_triangle"; - _markColor = "ColorRed"; - } else { - _magPicSplit = _magPic splitString "\"; - _magPic = _magPicSplit#((count _magPicSplit) - 1); - _markerType = format["magIcons/%1", _magPic]; - _markColor = "ColorWhite"; - }; - } else { - _markerType = "mil_triangle"; - _markColor = "ColorRed"; - // set defaults based on ammo sim type, if no magazine could be matched - switch (_ammoSimType) do { - case "shotGrenade":{ - _magPic = "\A3\Weapons_F\Data\UI\gear_M67_CA.paa"; - _magDisp = "Frag"; - }; - case "shotSmokeX":{ - _magPic = "\A3\Weapons_f\data\ui\gear_smokegrenade_white_ca.paa"; - _magDisp = "Smoke"; - }; - case "shotIlluminating":{ - _magPic = "\A3\Weapons_F\Data\UI\gear_flare_white_ca.paa"; - _magDisp = "Flare"; - }; - default { - _magPic = "\A3\Weapons_F\Data\UI\gear_M67_CA.paa"; - _magDisp = "Frag"; - }; - }; - // hint parseText format["Projectile fired:
", _magPic]; - _magPicSplit = _magPic splitString "\"; - _magPic = _magPicSplit#((count _magPicSplit) - 1); - _markerType = format["magIcons/%1", _magPic]; - _markColor = "ColorWhite"; - }; - - if (!(_ammoSimType isEqualTo "shotBullet")) then { - - _int = random 2000; - - _markTextLocal = format["%1", _magDisp]; - _markName = format["Projectile#%1", _int]; - - _throwerPos = getPosASL _unit; - - ["ocap_handleMarker", ["CREATED", _markName, _unit, _throwerPos, _markerType, "ICON", [1,1], 0, "Solid", _markColor, 1, _markTextLocal, true]] call CBA_fnc_serverEvent; - - private _lastPos = []; - waitUntil { - _pos = getPosASL _projectile; - if (((_pos select 0) isEqualTo 0) || isNull _projectile) exitWith { - true - }; - _lastPos = _pos; - ["ocap_handleMarker", ["UPDATED", _markName, _unit, _pos, "", "", "", 0, "", "", 1]] call CBA_fnc_serverEvent; - sleep 0.1; - false; - }; - - if !((count _lastPos) isEqualTo 0) then { - // if (count _lastPos == 3) then { - ["ocap_handleMarker", ["UPDATED", _markName, _unit, _lastPos, "", "", "", 0, "", "", 1]] call CBA_fnc_serverEvent; - }; - - sleep 10; - ["ocap_handleMarker", ["DELETED", _markName]] call CBA_fnc_serverEvent; - }; - }; -}] call CBA_fnc_addEventHandler; diff --git a/addons/@ocap/addons/ocap/functions/markerTestingChecklist.txt b/addons/@ocap/addons/ocap/functions/markerTestingChecklist.txt deleted file mode 100644 index 73c4c97..0000000 --- a/addons/@ocap/addons/ocap/functions/markerTestingChecklist.txt +++ /dev/null @@ -1,19 +0,0 @@ -Testing Checklist: - -1. Mission should have ellipse and rectangle markers scripted or placed in editor. - - some rotated - - some straight -2. Players should create ON MAP SCREEN: - - 1 icon with text, straight - - 1 icon without text, straight - - 1 icon with text, rotated - - 1 icon without text, rotated - - 1 icon of type "Infantry", "Armor", etc, rotated - - at least one drawn line (CTRL+Click/Drag) -3. Players should create ONCE LOADED IN: - - 1 icon with text, straight - - 1 icon without text, straight - - 1 icon with text, rotated - - 1 icon without text, rotated - - 1 icon of type "Infantry", "Armor", etc, rotated - - at least one drawn line (CTRL+Click/Drag) diff --git a/addons/@ocap/addons/ocap/functions/script_macros.hpp b/addons/@ocap/addons/ocap/functions/script_macros.hpp deleted file mode 100644 index d1f39d9..0000000 --- a/addons/@ocap/addons/ocap/functions/script_macros.hpp +++ /dev/null @@ -1 +0,0 @@ -#include "\ocap\script_macros.hpp" diff --git a/addons/@ocap/addons/ocap/script_macros.hpp b/addons/@ocap/addons/ocap/script_macros.hpp deleted file mode 100644 index f8a91f6..0000000 --- a/addons/@ocap/addons/ocap/script_macros.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Header: script_macros.hpp -// Defines macros imported to other functions - -#include "\userconfig\ocap\config.hpp" - -// define: REQUIRED_VERSION -// The version of Arma required to run this mod correctly. -#define REQUIRED_VERSION 2.04 -// define: OCAP_ADDON_VERSION -// The current version of OCAP2. -#define OCAP_ADDON_VERSION "1.2.0-alpha" -// define: LOG -// Used for logging messages via the extension. -#define LOG(_args) [":LOG:", _args] call ocap_fnc_extension - -// define: DEBUG -// Conditional, used for logging debug messages when is true. -#if ocap_isDebug - #define DEBUG(_args) [":LOG:", _args] call ocap_fnc_extension -#else - #define DEBUG(_args) /* disabled */ -#endif - -// define: BOOL -// Forces a true/false return of input. -#define BOOL(_cond) ([0,1] select (_cond)) - -// define: ARR2 -// Resolves to array, used for entry to that requires array input. -#define ARR2(_arg1, _arg2) [_arg1, _arg2] -#define ARR3(_arg1, _arg2, _arg3) [_arg1, _arg2, _arg3] -#define ARR4(_arg1, _arg2, _arg3, _arg4) [_arg1, _arg2, _arg3, _arg4] -#define ARR5(_arg1, _arg2, _arg3, _arg4, _arg5) [_arg1, _arg2, _arg3, _arg4, _arg5] -#define ARR6(_arg1, _arg2, _arg3, _arg4, _arg5, _arg6) [_arg1, _arg2, _arg3, _arg4, _arg5, _arg6] diff --git a/docs/files/extension/fnc_sendData-sqf.html b/docs/files/extension/fnc_sendData-sqf.html new file mode 100644 index 0000000..9e29049 --- /dev/null +++ b/docs/files/extension/fnc_sendData-sqf.html @@ -0,0 +1,43 @@ + + +fnc_sendData.sqf - OCAP2 + + + + + + + + + +

fnc_sendData.sqf

Summary
fnc_sendData.sqf
Functions
OCAP_extension_fnc_sendDataManages raw extension calls and returns values / logs errors where relevant.
+ +

Functions

+ +

OCAP_extension_fnc_sendData

Description

Manages raw extension calls and returns values / logs errors where relevant.

Parameters

_commandThe extension command to call [String]
_argsThe arguments to send [Array]

Returns

Depends

Examples

[":VERSION", []] call EFUNC(extension,sendData);

Public

No

Author

Dell, Zealot

+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/files/extension/script_component-hpp.html b/docs/files/extension/script_component-hpp.html new file mode 100644 index 0000000..64c3cb7 --- /dev/null +++ b/docs/files/extension/script_component-hpp.html @@ -0,0 +1,45 @@ + + +script_component.hpp - OCAP2 + + + + + + + + + +
+ +

Macros

+ +

COMPONENT

#define COMPONENT extension
+ +

COMPONENT_BEAUTIFIED

#define COMPONENT_BEAUTIFIED Extension
+ +
+ + + + + + + + + + +
#define COMPONENT extension
#define COMPONENT_BEAUTIFIED Extension
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/main/XEH_preInit-sqf.html b/docs/files/main/XEH_preInit-sqf.html new file mode 100644 index 0000000..a51415b --- /dev/null +++ b/docs/files/main/XEH_preInit-sqf.html @@ -0,0 +1,49 @@ + + +CBA Settings - OCAP2 + + + + + + + + + +

CBA Settings

Summary
CBA Settings
Core
CBA Settings
OCAP_enabledTurns on or off most recording functionality.
OCAP_isDebugEnables increased logging of addon actions.
OCAP_administratorListAn array or server-visible variable referencing one that is a list of playerUIDs.
+ +

Core

Summary
CBA Settings
OCAP_enabledTurns on or off most recording functionality.
OCAP_isDebugEnables increased logging of addon actions.
OCAP_administratorListAn array or server-visible variable referencing one that is a list of playerUIDs.
+ +

CBA Settings

+ +

OCAP_enabled

Description

Turns on or off most recording functionality.  Will not reset anything from existing session, will just stop recording most new data.  Note: For record/pause switching, use the CBA events!  Default: true

Setting Name

Recording Enabled

Value Type

Boolean

+ +

OCAP_isDebug

Description

Enables increased logging of addon actions.  Default: false

Setting Name

Debug Mode

Value Type

Boolean

+ +

OCAP_administratorList

Description

An array or server-visible variable referencing one that is a list of playerUIDs.  Additional briefing diary or UI elements may be available for more accessible control over OCAP’s features.  Takes effect on player server connection.  Format: [] OR myAdminPUIDs | Default: []

Setting Name

Administrators

Value Type

Stringified Array

Example

"['76561198000000000', '76561198000000001']"
+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/files/main/script_component-hpp.html b/docs/files/main/script_component-hpp.html new file mode 100644 index 0000000..2cec9fc --- /dev/null +++ b/docs/files/main/script_component-hpp.html @@ -0,0 +1,45 @@ + + +script_component.hpp - OCAP2 + + + + + + + + + +
+ +

Macros

+ +

COMPONENT

#define COMPONENT main
+ +

COMPONENT_BEAUTIFIED

#define COMPONENT_BEAUTIFIED Main
+ +
+ + + + + + + + + + +
#define COMPONENT main
#define COMPONENT_BEAUTIFIED Main
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/main/script_macros-hpp.html b/docs/files/main/script_macros-hpp.html new file mode 100644 index 0000000..3eecaa0 --- /dev/null +++ b/docs/files/main/script_macros-hpp.html @@ -0,0 +1,65 @@ + + +script_macros.hpp - OCAP2 + + + + + + + + + +

script_macros.hpp

Defines macros imported to other functions

Summary
script_macros.hppDefines macros imported to other functions
Macros
PREFIX
COMPONENT_NAME
ADDONPREFIX_COMPONENT
VERSION
VERSION_STR
VERSION_AR
VERSION_REQUIRED
LOGUsed for logging messages to the extension (ocap-ext log file).
SYSCHATUsed for debug purposes to send a string to all clients with interfaces.
SHOULDSAVEEVENTSUsed to determine if events should currently be saved based on OCAP_recorder_recording and <OCAP_recorder_startTime>.
BOOLForces a true/false return of input.
ARR2Resolves arguments to array, used for entries to LOG that requires array input.
+ +

Macros

+ +

PREFIX

#define PREFIX OCAP
+ +

COMPONENT_NAME

#define COMPONENT_NAME QUOTE(PREFIX COMPONENT_BEAUTIFIED)
+ + + +

VERSION

#define VERSION 2.0
+ +

VERSION_STR

#define VERSION_STR 2.0.0
+ +

VERSION_AR

#define VERSION_AR 2,0,0
+ +

VERSION_REQUIRED

#define VERSION_REQUIRED 2.10
+ +

LOG

#define OCAPEXTLOG(_args) [":LOG:", _args] call EFUNC(extension,sendData)

Used for logging messages to the extension (ocap-ext log file).

+ +

SYSCHAT

#define SYSCHAT remoteExec ["systemChat", [0, -2] select isDedicated]

Used for debug purposes to send a string to all clients with interfaces.

+ +

SHOULDSAVEEVENTS

#define SHOULDSAVEEVENTS (
   (missionNamespace getVariable [QGVAR(recording), false]) && missionNamespace getVariable [QGVAR(startTime), -1] -1
)

Used to determine if events should currently be saved based on OCAP_recorder_recording and <OCAP_recorder_startTime>.

+ +

BOOL

#define BOOL(_cond) ([0,1] select (_cond))

Forces a true/false return of input.

+ +

ARR2

#define ARR2(_arg1,
_arg2) [_arg1, _arg2]

Resolves arguments to array, used for entries to LOG that requires array input.

+ +
+ + + + + + + + + + +
#define PREFIX OCAP
#define COMPONENT_NAME QUOTE(PREFIX COMPONENT_BEAUTIFIED)
#define COMPONENT main
#define VERSION 2.0
#define VERSION_STR 2.0.0
#define VERSION_AR 2,0,0
#define VERSION_REQUIRED 2.10
#define OCAPEXTLOG(_args) [":LOG:", _args] call EFUNC(extension,sendData)
Used for logging messages to the extension (ocap-ext log file).
#define SYSCHAT remoteExec ["systemChat", [0, -2] select isDedicated]
Used for debug purposes to send a string to all clients with interfaces.
#define SHOULDSAVEEVENTS (
   (missionNamespace getVariable [QGVAR(recording), false]) && missionNamespace getVariable [QGVAR(startTime), -1] -1
)
Used to determine if events should currently be saved based on OCAP_recorder_recording and OCAP_recorder_startTime.
Global variable that represents whether or not recording is active [Bool]
#define BOOL(_cond) ([0,1] select (_cond))
Forces a true/false return of input.
#define ARR2(_arg1,
_arg2) [_arg1, _arg2]
Resolves arguments to array, used for entries to LOG that requires array input.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/XEH_preInit-sqf.html b/docs/files/recorder/XEH_preInit-sqf.html new file mode 100644 index 0000000..28d43d2 --- /dev/null +++ b/docs/files/recorder/XEH_preInit-sqf.html @@ -0,0 +1,87 @@ + + +CBA Settings - OCAP2 + + + + + + + + + +

CBA Settings

Summary
CBA Settings
Auto-Start Settings
CBA Settings
OCAP_settings_autoStartAutomatically start OCAP recordings at session start.
OCAP_settings_minPlayerCountAuto-start will begin once this player count is reached.
Core
CBA Settings
OCAP_settings_frameCaptureDelayPositioning, medical status, and crew states of units and vehicles will be captured every X amount of seconds.
OCAP_settings_preferACEUnconsciousIf true, will check ACE3 medical status on units.
Exclusions
CBA Settings
OCAP_settings_excludeClassFromRecordArray of object classnames that should be excluded from recording.
OCAP_settings_excludeKindFromRecordArray of classnames which, along with all child classes, should be excluded from recording.
OCAP_settings_excludeMarkerFromRecordArray of prefixes.
Extra Tracking
CBA Settings
OCAP_settings_trackTicketsWill track respawn ticket counts for missionNamespace and each playable faction every 30th frame.
OCAP_settings_trackTimesWill continuously track in-game world time during a mission.
OCAP_settings_trackTimeIntervalIf OCAP_settings_trackTimes is enabled, it will be checked every X capture frames.
Save/Export Settings
CBA Settings
OCAP_settings_saveTagIf not overriden by the OCAP_exportData CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions.
OCAP_settings_saveMissionEndedIf true, automatically save and export the mission when the MPEnded event fires.
OCAP_settings_saveOnEmptyWill automatically save recording when there are 0 players on the server and existing data accounts for more time than the minimum save duration setting.
OCAP_settings_minMissionTimeA recording must be at least this long (in minutes) to auto-save.
+ +

Auto-Start Settings

Summary
CBA Settings
OCAP_settings_autoStartAutomatically start OCAP recordings at session start.
OCAP_settings_minPlayerCountAuto-start will begin once this player count is reached.
+ +

CBA Settings

+ +

OCAP_settings_autoStart

Description

Automatically start OCAP recordings at session start.  Default: true

Setting Name

Auto Start Recording

Value Type

Boolean

+ +

OCAP_settings_minPlayerCount

Description

Auto-start will begin once this player count is reached.  Default: 15

Setting Name

Minimum Player Count

Value Type

Number

+ +

Core

Summary
CBA Settings
OCAP_settings_frameCaptureDelayPositioning, medical status, and crew states of units and vehicles will be captured every X amount of seconds.
OCAP_settings_preferACEUnconsciousIf true, will check ACE3 medical status on units.
+ +

CBA Settings

+ +

OCAP_settings_frameCaptureDelay

Description

Positioning, medical status, and crew states of units and vehicles will be captured every X amount of seconds.  Default: 1

Setting Name

Frame Capture Delay

Value Type

Number

+ +

OCAP_settings_preferACEUnconscious

Description

If true, will check ACE3 medical status on units.  If false, or ACE3 isn’t loaded, fall back to vanilla.  Default: true

Setting Name

Use ACE3 Medical

Value Type

Boolean

+ +

Exclusions

Summary
CBA Settings
OCAP_settings_excludeClassFromRecordArray of object classnames that should be excluded from recording.
OCAP_settings_excludeKindFromRecordArray of classnames which, along with all child classes, should be excluded from recording.
OCAP_settings_excludeMarkerFromRecordArray of prefixes.
+ +

CBA Settings

+ +

OCAP_settings_excludeClassFromRecord

Description

Array of object classnames that should be excluded from recording.  Use single quotes!  Default: [‘ACE_friesAnchorBar’, ‘WeaponHolderSimulated’]

Setting Name

Classnames to Exclude

Value Type

Stringified Array

Example

"['ACE_friesAnchorBar']"
+ +

OCAP_settings_excludeKindFromRecord

Description

Array of classnames which, along with all child classes, should be excluded from recording.  Use single quotes!  Default: []

Setting Name

Object KindOfs to Exclude

Value Type

Stringified Array

Example

"['WeaponHolder']"
+ +

OCAP_settings_excludeMarkerFromRecord

Description

Array of prefixes.  Any markers matching these prefixes will be excluded from recording.  Use single quotes!  Default: [‘SystemMarker_’,’ACE_BFT_’]

Setting Name

Marker Prefixes To Exclude

Value Type

Stringified Array

Example

"['SystemMarker_','ACE_BFT_']"
+ +

Extra Tracking

Summary
CBA Settings
OCAP_settings_trackTicketsWill track respawn ticket counts for missionNamespace and each playable faction every 30th frame.
OCAP_settings_trackTimesWill continuously track in-game world time during a mission.
OCAP_settings_trackTimeIntervalIf OCAP_settings_trackTimes is enabled, it will be checked every X capture frames.
+ +

CBA Settings

+ +

OCAP_settings_trackTickets

Description

Will track respawn ticket counts for missionNamespace and each playable faction every 30th frame.  Default: true

Setting Name

Enable Ticket Tracking

Value Type

Boolean

+ +

OCAP_settings_trackTimes

Description

Will continuously track in-game world time during a mission.  Useful for accelerated/skipped time scenarios.  Default: false

Setting Name

Enable Mission Time Tracking

Value Type

Boolean

+ +

OCAP_settings_trackTimeInterval

Description

If OCAP_settings_trackTimes is enabled, it will be checked every X capture frames.  Default: 10

Setting Name

Mission Time Tracking Interval

Value Type

Number

+ +

Save/Export Settings

Summary
CBA Settings
OCAP_settings_saveTagIf not overriden by the OCAP_exportData CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions.
OCAP_settings_saveMissionEndedIf true, automatically save and export the mission when the MPEnded event fires.
OCAP_settings_saveOnEmptyWill automatically save recording when there are 0 players on the server and existing data accounts for more time than the minimum save duration setting.
OCAP_settings_minMissionTimeA recording must be at least this long (in minutes) to auto-save.
+ +

CBA Settings

+ +

OCAP_settings_saveTag

Description

If not overriden by the OCAP_exportData CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions.

Setting Name

Mission Type Tag

Value Type

String

+ +

OCAP_settings_saveMissionEnded

Description

If true, automatically save and export the mission when the MPEnded event fires.  Default: true

Setting Name

Auto-save on MPEnded Event

Value Type

Boolean

+ +

OCAP_settings_saveOnEmpty

Description

Will automatically save recording when there are 0 players on the server and existing data accounts for more time than the minimum save duration setting.  Default: true

Setting Name

Auto-Save When No Players

Value Type

Boolean

+ +

OCAP_settings_minMissionTime

Description

A recording must be at least this long (in minutes) to auto-save.  Calling an OCAP_exportData CBA server event will override this restriction.  Default: 20

Setting Name

Required Duration to Sav

Value Type

Boolean

+ +
+ + + + + + + + + + +
Will continuously track in-game world time during a mission.
Used to stop recording & signal the extension to save and upload it to the web component.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_aceExplosives-sqf.html b/docs/files/recorder/fnc_aceExplosives-sqf.html new file mode 100644 index 0000000..2a08c66 --- /dev/null +++ b/docs/files/recorder/fnc_aceExplosives-sqf.html @@ -0,0 +1,43 @@ + + +fnc_aceExplosives.sqf - OCAP2 + + + + + + + + + +

fnc_aceExplosives.sqf

Summary
fnc_aceExplosives.sqf
Functions
OCAP_recorder_fnc_aceExplosivesAdds marker on the mine’s position to the recording timeline.
+ +

Functions

+ +

OCAP_recorder_fnc_aceExplosives

Description

Adds marker on the mine’s position to the recording timeline.  Then waits until the explosive is null (exploded) and indicates it with a 10-frame long red X before removing the marker.

Called by ace_explosives_place CBA listener.

Parameters

None

Returns

Nothing

Examples

call FUNC(aceExplosives);

Notes

Example of emitting event from ACE3 code:

[QGVAR(place), [_explosive, _dir, _pitch, _unit]] call CBA_fnc_globalEvent;

Public

No

Author

IndigoFox

+ +
+ + + + + + + + + + +
EGVAR(
   listener,
   aceExplosives
) = ["ace_explosives_place", { call FUNC(aceExplosives); }] call CBA_fnc_addEventHandler
Event listener for ACE3 global event indicating a mine has been placed and armed.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_addEventMission-sqf.html b/docs/files/recorder/fnc_addEventMission-sqf.html new file mode 100644 index 0000000..0285f34 --- /dev/null +++ b/docs/files/recorder/fnc_addEventMission-sqf.html @@ -0,0 +1,94 @@ + + +fnc_addEventMission.sqf - OCAP2 + + + + + + + + + +

fnc_addEventMission.sqf

Summary
fnc_addEventMission.sqf
Functions
OCAP_recorder_fnc_addEventMissionUsed for applying mission event handlers.
Event Handlers
Event Handlers
OCAP_EH_HandleDisconnectFired when a player leaves the mission by returning to lobby or disconnecting.
OCAP_EH_PlayerConnectedHandle for the “PlayerConnected” mission event handler.
OCAP_EH_OnUserAdminStateChangedHandle for the “OnUserAdminStateChange” mission event handler.
OCAP_EH_EntityKilledHandle for the “EntityKilled” mission event handler.
OCAP_EH_EntityRespawnedHandle for the “EntityRespawned” mission event handler.
OCAP_EH_MPEndedHandle for the “MPEnded” mission event handler.
OCAP_EH_EndedHandle for the “Ended” mission event handler.
CBA Events
Variables
CBA Listener Handles
CBA Events
ace_advanced_throwing_throwFiredXEHFired when a throwable is primed.
ace_explosives_placeEvent listener for ACE3 global event indicating a mine has been placed and armed.
OCAP_customEventEvent listener for custom event text to be added to the timeline.
OCAP_counterInitMeant for use in custom tracking of points or score between two sides.
OCAP_counterEventMeant for use in custom tracking of points or score between two sides.
OCAP_recordUsed to start or resume recording.
OCAP_pauseUsed to pause recording.
OCAP_exportDataUsed to stop recording & signal the extension to save and upload it to the web component.
+ +

Functions

+ +

OCAP_recorder_fnc_addEventMission

Description

Used for applying mission event handlers.  Applied during initialization of OCAP in OCAP_recorder_fnc_init.

Parameters

None

Returns

Nothing

Examples

call FUNC(addEventMission);

Public

No

Author

IndigoFox, Dell

+ +

Event Handlers

Summary
Event Handlers
OCAP_EH_HandleDisconnectFired when a player leaves the mission by returning to lobby or disconnecting.
OCAP_EH_PlayerConnectedHandle for the “PlayerConnected” mission event handler.
OCAP_EH_OnUserAdminStateChangedHandle for the “OnUserAdminStateChange” mission event handler.
OCAP_EH_EntityKilledHandle for the “EntityKilled” mission event handler.
OCAP_EH_EntityRespawnedHandle for the “EntityRespawned” mission event handler.
OCAP_EH_MPEndedHandle for the “MPEnded” mission event handler.
OCAP_EH_EndedHandle for the “Ended” mission event handler.
+ +

Event Handlers

+ +

OCAP_EH_HandleDisconnect

Fired when a player leaves the mission by returning to lobby or disconnecting.  Calls OCAP_recorder_fnc_eh_disconnected.

+ +

OCAP_EH_PlayerConnected

Handle for the “PlayerConnected” mission event handler.  Fired when a player joins the mission from lobby and appears in the world.  Calls OCAP_recorder_fnc_eh_connected.

+ +

OCAP_EH_OnUserAdminStateChanged

Handle for the “OnUserAdminStateChange” mission event handler.  Fired when a player’s admin status changes.  Calls OCAP_recorder_fnc_eh_onUserAdminStateChanged.

+ +

OCAP_EH_EntityKilled

Handle for the “EntityKilled” mission event handler.  Fired when an entity is killed.  Calls OCAP_recorder_fnc_eh_killed.

+ +

OCAP_EH_EntityRespawned

Handle for the “EntityRespawned” mission event handler.  Fired when an entity is respawned.  Sets new body to not-killed and calls OCAP_recorder_fnc_addUnitEventHandlers on it.  Then excludes corpse from further capture.

+ +

OCAP_EH_MPEnded

Handle for the “MPEnded” mission event handler.  Fired on the MPEnded mission event.  This is used to automatically save and export if OCAP_settings_saveMissionEnded is true and OCAP_settings_minMissionTime was reached.

+ +

OCAP_EH_Ended

Handle for the “Ended” mission event handler.  Fired on the singleplayer Ended mission event.  This is used to automatically save and export if OCAP_settings_saveMissionEnded is true and OCAP_settings_minMissionTime was reached.  Kept in just in case this event triggers.

+ +

CBA Events

Summary
Variables
CBA Listener Handles
CBA Events
ace_advanced_throwing_throwFiredXEHFired when a throwable is primed.
ace_explosives_placeEvent listener for ACE3 global event indicating a mine has been placed and armed.
OCAP_customEventEvent listener for custom event text to be added to the timeline.
OCAP_counterInitMeant for use in custom tracking of points or score between two sides.
OCAP_counterEventMeant for use in custom tracking of points or score between two sides.
OCAP_recordUsed to start or resume recording.
OCAP_pauseUsed to pause recording.
OCAP_exportDataUsed to stop recording & signal the extension to save and upload it to the web component.
+ +

Variables

+ +

CBA Listener Handles

OCAP_listener_aceThrowingHandle for ace_advanced_throwing_throwFiredXEH listener.
OCAP_listener_aceExplosivesHandle for ace_explosives_place listener.
OCAP_listener_customEventHandle for OCAP_customEvent listener.
OCAP_listener_counterInitHandle for OCAP_counterInit listener.
OCAP_listener_counterEventHandle for OCAP_counterEvent listener.
OCAP_counter_sidesSides that are tracked by the custom counter system.  [Array]
OCAP_listener_recordHandle for OCAP_record listener.
OCAP_listener_pauseHandle for OCAP_pause listener.
OCAP_listener_exportDataHandle for OCAP_exportData listener.
+ +

CBA Events

+ +

ace_advanced_throwing_throwFiredXEH

EGVAR(
   listener,
   aceThrowing
) = ["ace_advanced_throwing_throwFiredXEH", { _this call FUNC(eh_firedMan) }] call CBA_fnc_addEventHandler

Fired when a throwable is primed.  This is a global event the server will handle and forward to OCAP_recorder_fnc_eh_firedMan.  Created only if PBO “ace_advanced_throwing” is loaded.

+ +

ace_explosives_place

EGVAR(
   listener,
   aceExplosives
) = ["ace_explosives_place", { call FUNC(aceExplosives); }] call CBA_fnc_addEventHandler

Event listener for ACE3 global event indicating a mine has been placed and armed.  Calls OCAP_recorder_fnc_aceExplosives when triggered.  Created only if PBO “ace_explosives” is loaded.

+ +

OCAP_customEvent

Description

Event listener for custom event text to be added to the timeline.  Calls OCAP_recorder_fnc_handleCustomEvent when triggered.

Parameters

0Event name [String]
1Event data [Array]
1.0Always “generalEvent” [String]
1.1Custom event text [String]

Example

["OCAP_customEvent", ["generalEvent", "The warehouse has been secured!"]] call CBA_fnc_serverEvent;
+[QGVARMAIN(customEvent), ["generalEvent", "The warehouse has been secured!"]] call CBA_fnc_serverEvent;
+ +

OCAP_counterInit

Description

Meant for use in custom tracking of points or score between two sides.  Separate from BIS_fnc_respawnTickets.  Initializes the system.  Calls <OCAP_recorder_fnc_counterInit> when triggered.

Parameters

0Event name [String]
1Key/value for one or more sides [Array]
1.0Pair [Array]
1.0.0Side <SIDE>
1.0.1Initial value [Number]

Example

["OCAP_counterInit", [
+  [west, 0],
+  [east, 0]
+]] call CBA_fnc_serverEvent;
+
+[QGVARMAIN(counterInit), [
+  [west, 0],
+  [east, 0]
+]] call CBA_fnc_serverEvent;
+ +

OCAP_counterEvent

Description

Meant for use in custom tracking of points or score between two sides.  Separate from BIS_fnc_respawnTickets.  Updates the system.  Calls <OCAP_recorder_fnc_counterEvent> when triggered.

Parameters

0Event name [String]
1Event data [Array]
1.0Side <SIDE>
1.1Value to set [Number]

Example

["OCAP_counterEvent", [west, 1]] call CBA_fnc_serverEvent;
+ +

OCAP_record

Description

Used to start or resume recording.  Calls OCAP_recorder_fnc_startRecording when triggered.

Example

["OCAP_record"] call CBA_fnc_serverEvent;
+ +

OCAP_pause

Description

Used to pause recording.  Calls OCAP_recorder_fnc_stopRecording when triggered.

Example

["OCAP_pause"] call CBA_fnc_serverEvent;
+ +

OCAP_exportData

Description

Used to stop recording & signal the extension to save and upload it to the web component.  Calls OCAP_recorder_fnc_exportData when triggered.

Will always bypass OCAP_settings_minMissionTime.

Parameters

0Event name [String]
1Event data [Array]
1.0(optional) Winning side <SIDE>
1.1(optional) Message describing mission end [String]
1.2(optional) Custom save tag (overrides OCAP_settings_saveTag) [String]
+ +
+ + + + + + + + + + +
EGVAR(
   listener,
   aceThrowing
) = ["ace_advanced_throwing_throwFiredXEH", { _this call FUNC(eh_firedMan) }] call CBA_fnc_addEventHandler
Fired when a throwable is primed.
EGVAR(
   listener,
   aceExplosives
) = ["ace_explosives_place", { call FUNC(aceExplosives); }] call CBA_fnc_addEventHandler
Event listener for ACE3 global event indicating a mine has been placed and armed.
Initializes event listeners, event handlers, gathers OCAP_version and OCAP_extension_version, and kicks off waiters for the auto-start conditions if settings are configured to enable it.
This function uses the OCAP_EH_HandleDisconnect event handler to log “disconnected” events to the timeline.
This function uses the OCAP_EH_Connected event handler to log “connected” events to the timeline.
Uses OCAP_EH_OnUserAdminStateChanged to detect when someone is has logged in or out of the server and calls OCAP_recorder_fnc_adminUIControl to update the admin UI.
Tracks when a unit is killed.
Used for applying unit-specific event handlers to units during initialization.
If true, automatically save and export the mission when the MPEnded event fires.
A recording must be at least this long (in minutes) to auto-save.
Event listener for custom event text to be added to the timeline.
Meant for use in custom tracking of points or score between two sides.
Meant for use in custom tracking of points or score between two sides.
Used to start or resume recording.
Used to pause recording.
Used to stop recording & signal the extension to save and upload it to the web component.
Tracks bullet and non-bullet projectiles.
Adds marker on the mine’s position to the recording timeline.
Sends custom event data to the extension to save it to the timeline.
Begins recording the current mission.
Stops recording the current mission.
This function facilitates the actual endMission and save events in the extension, prompting it to pack the mission and upload it to the web component.
If not overriden by the OCAP_exportData CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_addUnitEventHandlers-sqf.html b/docs/files/recorder/fnc_addUnitEventHandlers-sqf.html new file mode 100644 index 0000000..217a2a9 --- /dev/null +++ b/docs/files/recorder/fnc_addUnitEventHandlers-sqf.html @@ -0,0 +1,43 @@ + + +fnc_addUnitEventHandlers.sqf - OCAP2 + + + + + + + + + +

fnc_addUnitEventHandlers.sqf

Summary
fnc_addUnitEventHandlers.sqf
Functions
OCAP_recorder_fnc_addUnitEventHandlersUsed for applying unit-specific event handlers to units during initialization.
+ +

Functions

+ +

OCAP_recorder_fnc_addUnitEventHandlers

Description

Used for applying unit-specific event handlers to units during initialization.  These event handlers will trigger on the server.

Applied during initialization of a unit in OCAP_recorder_fnc_captureLoop.

Note: Hit tracking moved to projectile EHs in OCAP_recorder_fnc_eh_firedMan

Parameters

_entityObject to apply event handlers to.  [Object]
_respawnDetermines if unit is initialized for the first time, or has respawned and does not need certain handlers reapplied.  [[Bool], default: false]

Returns

Nothing

Examples

[_unit] spawn FUNC(addUnitEventHandlers);

Public

No

Author

IndigoFox, Fank

+ +
+ + + + + + + + + + +
This function is run unscheduled and creates a CBA PerFrameHandler object, a logic object which executes code every specified interval (OCAP_settings_frameCaptureDelay) while a condition (SHOULDSAVEEVENTS) is true.
Tracks bullet and non-bullet projectiles.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_adminUIcontrol-sqf.html b/docs/files/recorder/fnc_adminUIcontrol-sqf.html new file mode 100644 index 0000000..94b9f04 --- /dev/null +++ b/docs/files/recorder/fnc_adminUIcontrol-sqf.html @@ -0,0 +1,47 @@ + + +fnc_adminUIControl.sqf - OCAP2 + + + + + + + + + +

fnc_adminUIControl.sqf

Summary
fnc_adminUIControl.sqf
Functions
OCAP_recorder_fnc_adminUIControlRuns checks to determine if a player should have the administrative diary entry added or removed upon joining the mission or logging in/out as admin.
Variables
OCAP_hasAdminControlsApplied on units processed in OCAP_recorder_fnc_adminUIControl.
+ +

Functions

+ +

OCAP_recorder_fnc_adminUIControl

Description

Runs checks to determine if a player should have the administrative diary entry added or removed upon joining the mission or logging in/out as admin.

Parameters

_PIDPlayerID indicating unique network client on the server [String]
_eventEvent that triggered this call [[String], one of: “connect”, “login”, “logout”]

Returns

Nothing

Examples

["1234567890", "connect"] call FUNC(adminUIControl);

Public

No

Author

IndigoFox

+ +

Variables

+ +

OCAP_hasAdminControls

Applied on units processed in OCAP_recorder_fnc_adminUIControl.  Indicates whether or not they have the administrative diary entry available.  Server missionNamespace only.

+ +
+ + + + + + + + + + +
Runs checks to determine if a player should have the administrative diary entry added or removed upon joining the mission or logging in/out as admin.
This function uses the OCAP_EH_Connected event handler to log “connected” events to the timeline.
An array or server-visible variable referencing one that is a list of playerUIDs.
Uses OCAP_EH_OnUserAdminStateChanged to detect when someone is has logged in or out of the server and calls OCAP_recorder_fnc_adminUIControl to update the admin UI.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_captureLoop-sqf.html b/docs/files/recorder/fnc_captureLoop-sqf.html new file mode 100644 index 0000000..4ddfc1a --- /dev/null +++ b/docs/files/recorder/fnc_captureLoop-sqf.html @@ -0,0 +1,47 @@ + + +fnc_captureLoop.sqf - OCAP2 + + + + + + + + + +

fnc_captureLoop.sqf

Summary
fnc_captureLoop.sqf
Functions
OCAP_recorder_fnc_captureLoopThis function is run unscheduled and creates a CBA PerFrameHandler object, a logic object which executes code every specified interval (OCAP_settings_frameCaptureDelay) while a condition (SHOULDSAVEEVENTS) is true.
Variables
OCAP_PFHObjectThe CBA PerFrameHandler object that is created and used to run the capture loop.
+ +

Functions

+ +

OCAP_recorder_fnc_captureLoop

Description

This function is run unscheduled and creates a CBA PerFrameHandler object, a logic object which executes code every specified interval (OCAP_settings_frameCaptureDelay) while a condition (SHOULDSAVEEVENTS) is true.

Iterates through units and vehicles, declares they exist, and conditionally sends their information to the extension to populate recording data.

This is the core processing loop that determines when new units enter the world, all the details about them, classifies which to exclude, and determines their health/life status.  It has both unit and vehicle tracking.

Parameters

None

Returns

Nothing

Examples

call FUNC(captureLoop);

Public

No

Author

Dell, Zealot, IndigoFox, Fank

+ +

Variables

+ +

OCAP_PFHObject

The CBA PerFrameHandler object that is created and used to run the capture loop.

+ +
+ + + + + + + + + + +
Positioning, medical status, and crew states of units and vehicles will be captured every X amount of seconds.
#define SHOULDSAVEEVENTS (
   (missionNamespace getVariable [QGVAR(recording), false]) && missionNamespace getVariable [QGVAR(startTime), -1] -1
)
Used to determine if events should currently be saved based on OCAP_recorder_recording and OCAP_recorder_startTime.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_eh_connected-sqf.html b/docs/files/recorder/fnc_eh_connected-sqf.html new file mode 100644 index 0000000..cc40877 --- /dev/null +++ b/docs/files/recorder/fnc_eh_connected-sqf.html @@ -0,0 +1,43 @@ + + +fnc_eh_connected.sqf - OCAP2 + + + + + + + + + +

fnc_eh_connected.sqf

Summary
fnc_eh_connected.sqf
Functions
OCAP_recorder_fnc_eh_connectedThis function uses the <OCAP_EH_Connected> event handler to log “connected” events to the timeline.
+ +

Functions

+ +

OCAP_recorder_fnc_eh_connected

Description

This function uses the <OCAP_EH_Connected> event handler to log “connected” events to the timeline.

It also calls OCAP_recorder_fnc_adminUIControl to apply the admin UI if the player is in OCAP_administratorList.

Parameters

See the wiki for details.  https://community.bistudio.com/wiki/Arma_3:_Mission_Event_Handlers#PlayerConnected

Returns

Nothing

Examples

call FUNC(eh_connected);

Public

No

Author

IndigoFox

+ +
+ + + + + + + + + + +
Runs checks to determine if a player should have the administrative diary entry added or removed upon joining the mission or logging in/out as admin.
An array or server-visible variable referencing one that is a list of playerUIDs.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_eh_disconnected-sqf.html b/docs/files/recorder/fnc_eh_disconnected-sqf.html new file mode 100644 index 0000000..13093ce --- /dev/null +++ b/docs/files/recorder/fnc_eh_disconnected-sqf.html @@ -0,0 +1,43 @@ + + +fnc_eh_disconnected.sqf - OCAP2 + + + + + + + + + +

fnc_eh_disconnected.sqf

Summary
fnc_eh_disconnected.sqf
Functions
OCAP_recorder_fnc_eh_disconnectedThis function uses the OCAP_EH_HandleDisconnect event handler to log “disconnected” events to the timeline.
+ +

Functions

+ +

OCAP_recorder_fnc_eh_disconnected

Description

This function uses the OCAP_EH_HandleDisconnect event handler to log “disconnected” events to the timeline.  It will exclude any body left over from further recording.

Parameters

See the wiki for details.  https://community.bistudio.com/wiki/Arma_3:_Mission_Event_Handlers#HandleDisconnect

Returns

False [Bool]

Examples

call FUNC(eh_disconnected);

Public

No

Author

IndigoFox

+ +
+ + + + + + + + + + +
Fired when a player leaves the mission by returning to lobby or disconnecting.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_eh_firedMan-sqf.html b/docs/files/recorder/fnc_eh_firedMan-sqf.html new file mode 100644 index 0000000..7335b91 --- /dev/null +++ b/docs/files/recorder/fnc_eh_firedMan-sqf.html @@ -0,0 +1,57 @@ + + +fnc_eh_firedMan.sqf - OCAP2 + + + + + + + + + +

fnc_eh_firedMan.sqf

Summary
fnc_eh_firedMan.sqf
Functions
OCAP_recorder_fnc_eh_firedManTracks bullet and non-bullet projectiles.
Variables
OCAP_lastFiredIndicates a formatted string of the last weapon and magazine type fired by the unit.
Event Handlers
Projectiles (Bullets)
Projectiles (Non-Bullets)
CBA Events
Projectiles
+ +

Functions

+ +

OCAP_recorder_fnc_eh_firedMan

Description

Tracks bullet and non-bullet projectiles.  This is the code triggered when a unit firing is detected by the “FiredMan” Event Handler applied to units during OCAP_recorder_fnc_addUnitEventHandlers.

Parameters

_firerUnit the event handler is assigned to (the instigator) [Object]
_weaponFired weapon [String]
_muzzleMuzzle that was used [String]
_modeCurrent mode of the fired weapon [String]
_ammoClassname of ammo used [String]
_magazineClassname of magazine used [String]
_projectileObject of the projectile that was shot out [Object]
_vehicleif weapon is vehicle weapon, otherwise objNull [Object]

Returns

Nothing

Examples

[_firer, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile, _vehicle] call FUNC(eh_firedMan);

Public

No

Author

IndigoFox, Dell

+ +

Variables

+ +

OCAP_lastFired

Indicates a formatted string of the last weapon and magazine type fired by the unit.  Used for logging hits/kills.  Applied to a firing unit.

+ +

Event Handlers

+ +

Projectiles (Bullets)

DeletedMakes extension call to draw a fire-line between the firer and the final destination.
ExplodeMakes extension call to draw a fire-line between the firer and the final destination.
HitPartTriggered when a projectile hits a part of a unit.  Calls OCAP_recorder_fnc_eh_projectileHit.
HitExplosionTriggered when a projectile explodes and damages a part of a unit.  Calls OCAP_recorder_fnc_eh_projectileHit.
+ +

Projectiles (Non-Bullets)

DeletedTriggered when a non-bullet projectile is deleted.  Updates marker position, then removes it 3 frames later.
ExplodeTriggered when a non-bullet projectile explodes.  Updates marker position, then removes it 3 frames later.
HitPartTriggered when a projectile hits a part of a unit.  Calls OCAP_recorder_fnc_eh_projectileHit.
HitExplosionTriggered when a projectile explodes and damages a part of a unit.  Calls OCAP_recorder_fnc_eh_projectileHit.
+ +

CBA Events

+ +

Projectiles

OCAP_recorder_addDebugBulletTriggered when a bullet is fired and the debug mode is enabled.  Shares recent bullet data to all clients.
OCAP_recorder_addDebugMagIconTriggered when a non-bullet projectile is fired and the debug mode is enabled.  Shares recent data to all clients.
+ +
+ + + + + + + + + + +
Used for applying unit-specific event handlers to units during initialization.
Tracks when a unit is hit/takes damage and saves to the timeline.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_eh_killed-sqf.html b/docs/files/recorder/fnc_eh_killed-sqf.html new file mode 100644 index 0000000..9ab0aff --- /dev/null +++ b/docs/files/recorder/fnc_eh_killed-sqf.html @@ -0,0 +1,43 @@ + + +fnc_eh_killed.sqf - OCAP2 + + + + + + + + + +

fnc_eh_killed.sqf

Summary
+ +

Functions

+ +

OCAP_recorder_fnc_eh_killed

Description

Tracks when a unit is killed.  This is the code triggered by the OCAP_EH_EntityKilled mission event handler.

Parameters

_unitObject the event handler is assigned to.  [Object]
_killerObject that killed the unit.  [Object]
_instigatorPerson who pulled the trigger.  [Object]
_useEffectssame as useEffects in setDamage alt syntax.  [Bool]

Returns

Nothing

Examples

call FUNC(eh_killed);

Public

No

Author

Dell, IndigoFox, Fank

+ +
+ + + + + + + + + + +
Handle for the “EntityKilled” mission event handler.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_eh_onUserAdminStateChanged-sqf.html b/docs/files/recorder/fnc_eh_onUserAdminStateChanged-sqf.html new file mode 100644 index 0000000..251b308 --- /dev/null +++ b/docs/files/recorder/fnc_eh_onUserAdminStateChanged-sqf.html @@ -0,0 +1,43 @@ + + +fnc_eh_onUserAdminStateChanged.sqf - OCAP2 + + + + + + + + + +

fnc_eh_onUserAdminStateChanged.sqf

Summary
fnc_eh_onUserAdminStateChanged.sqf
Functions
OCAP_recorder_fnc_eh_onUserAdminStateChangedUses OCAP_EH_OnUserAdminStateChanged to detect when someone is has logged in or out of the server and calls OCAP_recorder_fnc_adminUIControl to update the admin UI.
+ +

Functions

+ +

OCAP_recorder_fnc_eh_onUserAdminStateChanged

Description

Uses OCAP_EH_OnUserAdminStateChanged to detect when someone is has logged in or out of the server and calls OCAP_recorder_fnc_adminUIControl to update the admin UI.

Parameters

_networkIdThe network ID of the player who has logged in or out of the server [String]
_loggedInWhether the player has logged in or out as admin [Boolean]
_votedInWhether the player has been voted in or out of admin [Boolean]

Returns

Nothing

Examples

call FUNC(eh_onUserAdminStateChanged);

Public

No

Author

IndigoFox

+ +
+ + + + + + + + + + +
Handle for the “OnUserAdminStateChange” mission event handler.
Runs checks to determine if a player should have the administrative diary entry added or removed upon joining the mission or logging in/out as admin.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_eh_projectileHit-sqf.html b/docs/files/recorder/fnc_eh_projectileHit-sqf.html new file mode 100644 index 0000000..723ca96 --- /dev/null +++ b/docs/files/recorder/fnc_eh_projectileHit-sqf.html @@ -0,0 +1,43 @@ + + +fnc_eh_projectileHit.sqf - OCAP2 + + + + + + + + + +

fnc_eh_projectileHit.sqf

Summary
fnc_eh_projectileHit.sqf
Functions
OCAP_recorder_fnc_eh_projectileHitTracks when a unit is hit/takes damage and saves to the timeline.
+ +

Functions

+ +

OCAP_recorder_fnc_eh_projectileHit

Description

Tracks when a unit is hit/takes damage and saves to the timeline.  This is called by projectile event handlers in OCAP_recorder_fnc_eh_firedMan.

Parameters

_unitObject that took damage [Object]
_shooterObject that caused the damage [Object]

Returns

Nothing

Examples

[_hitEntity, _projectileOwner] call FUNC(eh_projectileHit);

Public

No

Author

IndigoFox, Fank

+ +
+ + + + + + + + + + +
Tracks bullet and non-bullet projectiles.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_entityMonitors-sqf.html b/docs/files/recorder/fnc_entityMonitors-sqf.html new file mode 100644 index 0000000..5c1d33b --- /dev/null +++ b/docs/files/recorder/fnc_entityMonitors-sqf.html @@ -0,0 +1,47 @@ + + +fnc_entityMonitors.sqf - OCAP2 + + + + + + + + + +

fnc_entityMonitors.sqf

Summary
fnc_entityMonitors.sqf
Functions
OCAP_recorder_fnc_entityMonitorsWhile debug mode is enabled, this function will render 2D icons and text representing all entities that have been initialized by OCAP and are not being excluded from the recording.
Variables
OCAP_entityMonitorsInitializedThis variable on the server indicates whether or not the entity monitors have been initialized for all clients + JIP.
+ +

Functions

+ +

OCAP_recorder_fnc_entityMonitors

Description

While debug mode is enabled, this function will render 2D icons and text representing all entities that have been initialized by OCAP and are not being excluded from the recording.

This is useful for debugging and verifying that the correct entities are being recorded (see OCAP_settings_excludeClassFromRecord and OCAP_settings_excludeKindFromRecord.

Parameters

None

Returns

Nothing

Examples

[_hitEntity, _projectileOwner] call FUNC(eh_projectileHit);

Public

No

Author

IndigoFox

+ +

Variables

+ +

OCAP_entityMonitorsInitialized

This variable on the server indicates whether or not the entity monitors have been initialized for all clients + JIP.

+ +
+ + + + + + + + + + +
Array of object classnames that should be excluded from recording.
Array of classnames which, along with all child classes, should be excluded from recording.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_exportData-sqf.html b/docs/files/recorder/fnc_exportData-sqf.html new file mode 100644 index 0000000..388c45d --- /dev/null +++ b/docs/files/recorder/fnc_exportData-sqf.html @@ -0,0 +1,56 @@ + + +fnc_exportData.sqf - OCAP2 + + + + + + + + + +

fnc_exportData.sqf

Summary
fnc_exportData.sqf
Functions
OCAP_recorder_fnc_exportDataThis function facilitates the actual endMission and save events in the extension, prompting it to pack the mission and upload it to the web component.
+ +

Functions

+ +

OCAP_recorder_fnc_exportData

Description

This function facilitates the actual endMission and save events in the extension, prompting it to pack the mission and upload it to the web component.

Called directly, it is subject to the OCAP_settings_minMissionTime setting, and will not export if the mission is not long enough.  It can also be called using OCAP_listener_exportData to bypass this check.

When OCAP_settings_saveMissionEnded is true, this function will be called automatically when the mission ends.

When OCAP_settings_saveOnEmpty is true, this function will execute when the last player leaves the mission (to lobby or when disconnecting).

OCAP_settings_saveTag is used to tag the mission with a custom string, which can be used to identify the mission in the web component.

Parameters

_sideThe winning side [optional, Side]
_messageA custom description of how the victory was achieved [optional, String]
_tagA custom tag to override that which is defined in userconfig.hpp that will make it filterable in web [optional, String]

Returns

Nothing

Examples

// "Mission ended"
+[] call FUNC(exportData);
+
+// "BLUFOR Win."
+[west] call FUNC(exportData);
+
+// "OPFOR Win. OPFOR controlled all sectors!
+[east, "OPFOR controlled all sectors!"] call FUNC(exportData);
+
+// "Independent Win. INDFOR stole the intel!"
+// Mission is saved under filterable "SnatchAndGrab" tag on web
+[independent, "INDFOR stole the intel!", "SnatchAndGrab"] call FUNC(exportData);
+
+["OCAP_exportData", west] call CBA_fnc_serverEvent;

Public

No

Author

Dell, Zealot, IndigoFox, TyroneMF

+ +
+ + + + + + + + + + +
A recording must be at least this long (in minutes) to auto-save.
Handle for OCAP_exportData listener.
If true, automatically save and export the mission when the MPEnded event fires.
Will automatically save recording when there are 0 players on the server and existing data accounts for more time than the minimum save duration setting.
If not overriden by the OCAP_exportData CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_getAmmoMarkerData-sqf.html b/docs/files/recorder/fnc_getAmmoMarkerData-sqf.html new file mode 100644 index 0000000..cbb4f37 --- /dev/null +++ b/docs/files/recorder/fnc_getAmmoMarkerData-sqf.html @@ -0,0 +1,43 @@ + + +fnc_getAmmoMarkerData.sqf - OCAP2 + + + + + + + + + +

fnc_getAmmoMarkerData.sqf

Summary
fnc_getAmmoMarkerData.sqf
Functions
OCAP_recorder_fnc_getAmmoMarkerDataThis function will intake information from <OCAP_EH_FiredMan> and return data used to format a marker for entry into the timeline.
+ +

Functions

+ +

OCAP_recorder_fnc_getAmmoMarkerData

Description

This function will intake information from <OCAP_EH_FiredMan> and return data used to format a marker for entry into the timeline.

Parameters

_weaponThe weapon used [String]
_muzzleThe muzzle used [String]
_ammoThe ammo used [String]
_magazineThe magazine used [String]
_projectileThe projectile object [Object]
_vehicleThe vehicle the weapon is mounted on, if any [Object]
_ammoSimTypeThe ammo simulation type [String]

Returns

[_markTextLocal,_markName,_markColor,_markerType]The marker data [Array]

Examples

([_weapon, _muzzle, _ammo, _magazine, _projectile, _vehicle, _ammoSimType] call FUNC(getAmmoMarkerData)) params ["_markTextLocal","_markName","_markColor","_markerType"];

Public

No

Author

IndigoFox

+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_getClass-sqf.html b/docs/files/recorder/fnc_getClass-sqf.html new file mode 100644 index 0000000..cac387b --- /dev/null +++ b/docs/files/recorder/fnc_getClass-sqf.html @@ -0,0 +1,43 @@ + + +fnc_getClass.sqf - OCAP2 + + + + + + + + + +

fnc_getClass.sqf

Summary
fnc_getClass.sqf
Functions
OCAP_recorder_fnc_getClassDetermines what type of vehicle is being recorded to match with the more limited icon set preloaded in the OCAP playback UI.
+ +

Functions

+ +

OCAP_recorder_fnc_getClass

Description

Determines what type of vehicle is being recorded to match with the more limited icon set preloaded in the OCAP playback UI.

Parameters

_thisThe vehicle being queried [Object]

Returns

[String]The icon name that should be used to represent the vehicle in the playback UI

Examples

_class = _vehType call FUNC(getClass);

Public

No

Author

Zealot, Dell

+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_getEventWeaponText-sqf.html b/docs/files/recorder/fnc_getEventWeaponText-sqf.html new file mode 100644 index 0000000..35cfcf7 --- /dev/null +++ b/docs/files/recorder/fnc_getEventWeaponText-sqf.html @@ -0,0 +1,43 @@ + + +fnc_getEventWeaponText.sqf - OCAP2 + + + + + + + + + +

fnc_getEventWeaponText.sqf

Summary
fnc_getEventWeaponText.sqf
Functions
OCAP_recorder_fnc_getEventWeaponTextUsed to identify the current weapon a unit is using that has injured or killed another.
+ +

Functions

+ +

OCAP_recorder_fnc_getEventWeaponText

Description

Used to identify the current weapon a unit is using that has injured or killed another.  Will determine the handheld weapon or vehicle weapon they’re using.

Attempts to reference OCAP_lastFired but will fall back to current value if not available.

Called during <OCAP_recorder_fnc_projectileHit> and OCAP_recorder_fnc_eh_killed.

Parameters

_instigatorThe unit to evaluate [Object]

Returns

The description of weapon or vehicle > weapon.  [String]

Examples

[_shooter] call FUNC(getEventWeaponText)

Public

No

Author

IndigoFox

+ +
+ + + + + + + + + + +
Indicates a formatted string of the last weapon and magazine type fired by the unit.
Tracks when a unit is killed.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_getInstigator-sqf.html b/docs/files/recorder/fnc_getInstigator-sqf.html new file mode 100644 index 0000000..d371ded --- /dev/null +++ b/docs/files/recorder/fnc_getInstigator-sqf.html @@ -0,0 +1,43 @@ + + +fnc_getInstigator.sqf - OCAP2 + + + + + + + + + +

fnc_getInstigator.sqf

Summary
fnc_getInstigator.sqf
Functions
OCAP_recorder_fnc_getInstigatorAttempts to identify who truly pulled the trigger on a kill event.
+ +

Functions

+ +

OCAP_recorder_fnc_getInstigator

Description

Attempts to identify who truly pulled the trigger on a kill event.

Called in OCAP_recorder_fnc_eh_killed.

Parameters

_victimWho was killed.  [Object]
_killerWhat caused the damage.  [Object, default objNull]
_instigatorWho pulled the trigger, as reported by Arma.  [Object, default objNull]

Returns

The true killer.  [Object]

Examples

[_victim, _killer] call FUNC(getInstigator);

Public

No

Author

Dell

+ +
+ + + + + + + + + + +
Tracks when a unit is killed.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_getUnitType-sqf.html b/docs/files/recorder/fnc_getUnitType-sqf.html new file mode 100644 index 0000000..d787381 --- /dev/null +++ b/docs/files/recorder/fnc_getUnitType-sqf.html @@ -0,0 +1,43 @@ + + +fnc_getUnitType.sqf - OCAP2 + + + + + + + + + +

fnc_getUnitType.sqf

Summary
fnc_getUnitType.sqf
Functions
OCAP_recorder_fnc_getUnitTypeIdentifies the role of a unit using similar methodology to Arma 3’s.
+ +

Functions

+ +

OCAP_recorder_fnc_getUnitType

Description

Identifies the role of a unit using similar methodology to Arma 3’s.  Used in <FUNC(captureLoop)>.

Parameters

_unitToCheckUnit to evaluate.  [Object]

Returns

The role text.  [String]

Examples

[_x] call ocap_fnc_getUnitType;

Public

No

Author

IndigoFox, veteran29

+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_getWeaponDisplayData-sqf.html b/docs/files/recorder/fnc_getWeaponDisplayData-sqf.html new file mode 100644 index 0000000..2200c15 --- /dev/null +++ b/docs/files/recorder/fnc_getWeaponDisplayData-sqf.html @@ -0,0 +1,43 @@ + + +fnc_getWeaponDisplayData.sqf - OCAP2 + + + + + + + + + +
+ +

Functions

+ +

OCAP_recorder_fnc_getWeaponDisplayData

Description

Used to populate OCAP_lastFired on units in OCAP_recorder_fnc_eh_firedMan.

Parameters

_weaponWeapon class name [String]
_muzzleMuzzle class name [String]
_magazineMagazine class name [String]
_ammoAmmo class name [String]

Returns

[Array]

0Muzzle display name [String]
1Magazine display name [String]

Examples

([_weapon, _muzzle, _magazine, _ammo] call FUNC(getWeaponDisplayData)) params ["_muzzleDisp", "_magDisp"];

Public

No

Author

IndigoFox

+ +
+ + + + + + + + + + +
Indicates a formatted string of the last weapon and magazine type fired by the unit.
Tracks bullet and non-bullet projectiles.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_handleCustomEvent-sqf.html b/docs/files/recorder/fnc_handleCustomEvent-sqf.html new file mode 100644 index 0000000..5fa9feb --- /dev/null +++ b/docs/files/recorder/fnc_handleCustomEvent-sqf.html @@ -0,0 +1,65 @@ + + +fnc_handleCustomEvent.sqf - OCAP2 + + + + + + + + + +

fnc_handleCustomEvent.sqf

Summary
fnc_handleCustomEvent.sqf
Functions
OCAP_recorder_fnc_handleCustomEventSends custom event data to the extension to save it to the timeline.
+ +

Functions

+ +

OCAP_recorder_fnc_handleCustomEvent

Description

Sends custom event data to the extension to save it to the timeline.  This custom event data is later read by Javascript in the web component to determine how it should be displayed.

Applied during initialization of OCAP in OCAP_recorder_fnc_init.

Parameters

_typeclassifier for the type of event. used to determine text & icon [[String], one of: “flag”, “generalEvent”]
_unitname of the unit that performed the action [String]
_unitColor(optional) color for the unit’s name shown in Events list and for the pulse on the map [[String], Hex RGB, defaults “” and will show as white]
_objectiveColor(optional) color representing the icon in Events list [[String], Hex RGB, defaults “” and will show as white]
_position(optional) the location to pulse on the map [<PositionATL>, default nil]

Returns

Nothing

Examples

["ocap_handleCustomEvent", ["eventType", "eventMessage"]] call CBA_fnc_serverEvent;
+
+// saves a general event to the timeline
+["ocap_handleCustomEvent", ["generalEvent", "eventText"]] call CBA_fnc_serverEvent;
+
+// indicates a flag has been captured
+["ocap_handleCustomEvent", ["captured", [
+  "flag",
+  name _unit,
+  str side group _unit,
+  "#FF0000",
+  getPosAtl _flag
+]]] call call CBA_fnc_serverEvent;
+
+
+// Not yet implemented
+["ocap_handleCustomEvent", ["captured", [
+  "sector",
+  name _unit,
+  str side group _unit,
+  "#FF0000",
+  getPosAtl _sectorObject
+]]] call call CBA_fnc_serverEvent;

Public

Yes

Author

Fank, Zealot

+ +
+ + + + + + + + + + +
Initializes event listeners, event handlers, gathers OCAP_version and OCAP_extension_version, and kicks off waiters for the auto-start conditions if settings are configured to enable it.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_handleMarkers-sqf.html b/docs/files/recorder/fnc_handleMarkers-sqf.html new file mode 100644 index 0000000..ae82c66 --- /dev/null +++ b/docs/files/recorder/fnc_handleMarkers-sqf.html @@ -0,0 +1,61 @@ + + +fnc_handleMarkers.sqf - OCAP2 + + + + + + + + + +

fnc_handleMarkers.sqf

Summary
fnc_handleMarkers.sqf
Functions
OCAP_recorder_fnc_handleMarkersUsed for tracking all markers in the vanilla Arma 3 system.
Variables
OCAP_recorder_trackedMarkersPersistent global variable on server that defines unique marker names currently being tracked.
OCAP_listener_markersContains handle for OCAP_handleMarker CBA event handler.
CBA Events
OCAP_handleMarkerHandles marker creation, modification, and deletion events.
Event Handlers
MarkerCreatedTracks marker creations.
MarkerUpdatedTracks marker updates (moves).
MarkerDeletedTracks marker deletions.
+ +

Functions

+ +

OCAP_recorder_fnc_handleMarkers

Description

Used for tracking all markers in the vanilla Arma 3 system.

This function creates a server-side CBA listener as well as local Event Handlers on the server and all clients.  It facilitates marker creation, modification, and deletion that occurs across any machine or on the server.

Delays are integrated into the system to allow for multi-line scripted marker creations during a mission to reflect correctly in the created marker during playback.  These delays are accounted for so that playback reflects the true creation time.

Due to the nature of locality and single-view playback, markers of the same name which exist in different states on different clients may display odd behavior during playback.

Marker exclusions as configured in OCAP_settings_excludeMarkerFromRecord are handled client-side to avoid unnecessary network traffic.

This will also wait until the mission proceeds past the briefing screen, then gather all existing markers and send them to the server for entry onto the Editor/Briefing Markers layer during playback.

Applied during mission event handler application in OCAP_recorder_fnc_addEventMission.

Parameters

None

Returns

Nothing

Examples

call FUNC(handleMarkers);

Public

No

Author

IndigoFox, Fank

+ +

Variables

+ +

OCAP_recorder_trackedMarkers

Persistent global variable on server that defines unique marker names currently being tracked.  Entries are added at marker create events and removed at marker delete events to avoid duplicate processing.

+ +

OCAP_listener_markers

Contains handle for OCAP_handleMarker CBA event handler.

+ +

CBA Events

+ +

OCAP_handleMarker

Handles marker creation, modification, and deletion events.

+ +

Event Handlers

+ +

MarkerCreated

Description

Tracks marker creations.  Present on server and all clients.  Ignores remotely-owned markers.

References OCAP_settings_excludeMarkerFromRecord on each local machine to determine if a marker should be recorded.

If so, sends marker data to OCAP_handleMarker on the server for processing.

+ +

MarkerUpdated

Description

Tracks marker updates (moves).  Present on server and all clients.  Ignores remotely-owned markers.

References OCAP_settings_excludeMarkerFromRecord on each local machine to determine if a marker should be recorded.

If so, sends marker data to OCAP_handleMarker on the server for processing.

+ +

MarkerDeleted

Description

Tracks marker deletions.  Present on server and all clients.  Ignores remotely-owned markers.

References OCAP_settings_excludeMarkerFromRecord on each local machine to determine if a marker should be recorded.

If so, sends marker data to OCAP_handleMarker on the server for processing.

+ +
+ + + + + + + + + + +
Handles marker creation, modification, and deletion events.
Array of prefixes.
Used for applying mission event handlers.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_init-sqf.html b/docs/files/recorder/fnc_init-sqf.html new file mode 100644 index 0000000..2059184 --- /dev/null +++ b/docs/files/recorder/fnc_init-sqf.html @@ -0,0 +1,61 @@ + + +fnc_init.sqf - OCAP2 + + + + + + + + + +

fnc_init.sqf

Summary
fnc_init.sqf
Functions
OCAP_recorder_fnc_initInitializes event listeners, event handlers, gathers OCAP_version and OCAP_extension_version, and kicks off waiters for the auto-start conditions if settings are configured to enable it.
Variables
OCAP_recorder_recordingGlobal variable that represents whether or not recording is active [Bool]
OCAP_recorder_captureFrameNoGlobal variable that represents the current frame number [Number]
OCAP_recorder_nextIdGlobal variable that represents the next available id to assign to a unit or vehicle [Number]
OCAP_recorder_frameCaptureDelayGlobal variable that represents the delay between frame captures in seconds.
OCAP_recorder_autoStartGlobal variable that represents whether or not recording should automatically start.
OCAP_recorder_minMissionTimeGlobal variable that represents the minimum mission time in seconds to qualify for saving.
OCAP_versionGlobal variable that represents the version of OCAP addon being used [String]
OCAP_extension_versionGlobal variable that represents the version of OCAP extension being used [String]
+ +

Functions

+ +

OCAP_recorder_fnc_init

Description

Initializes event listeners, event handlers, gathers OCAP_version and OCAP_extension_version, and kicks off waiters for the auto-start conditions if settings are configured to enable it.

Parameters

None

Returns

Nothing

Example

call OCAP_recorder_fnc_init

Public

No

Author

Dell, Zealot, IndigoFox

+ +

Variables

+ +

OCAP_recorder_recording

Global variable that represents whether or not recording is active [Bool]

+ +

OCAP_recorder_captureFrameNo

Global variable that represents the current frame number [Number]

+ +

OCAP_recorder_nextId

Global variable that represents the next available id to assign to a unit or vehicle [Number]

+ +

OCAP_recorder_frameCaptureDelay

Global variable that represents the delay between frame captures in seconds.  Gathered from CBA settings at init.  [Number]

+ +

OCAP_recorder_autoStart

Global variable that represents whether or not recording should automatically start.  Gathered from CBA settings at init.  [Bool]

+ +

OCAP_recorder_minMissionTime

Global variable that represents the minimum mission time in seconds to qualify for saving.  Can be overridden by using the <ocap_exportData> CBA event.  Gathered from CBA settings at init.  [Number]

+ +

OCAP_version

Global variable that represents the version of OCAP addon being used [String]

+ +

OCAP_extension_version

Global variable that represents the version of OCAP extension being used [String]

+ +
+ + + + + + + + + + +
Global variable that represents the version of OCAP addon being used [String]
Global variable that represents the version of OCAP extension being used [String]
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_isKindOfApc-sqf.html b/docs/files/recorder/fnc_isKindOfApc-sqf.html new file mode 100644 index 0000000..0033cb7 --- /dev/null +++ b/docs/files/recorder/fnc_isKindOfApc-sqf.html @@ -0,0 +1,43 @@ + + +fnc_isKindOfApc.sqf - OCAP2 + + + + + + + + + +

fnc_isKindOfApc.sqf

Summary
fnc_isKindOfApc.sqf
Functions
OCAP_recorder_fnc_isKindOfApcHelper function for OCAP_recorder_fnc_getClass to prevent APCs from being classified as Cars or Trucks.
+ +

Functions

+ +

OCAP_recorder_fnc_isKindOfApc

Description

Helper function for OCAP_recorder_fnc_getClass to prevent APCs from being classified as Cars or Trucks.

Parameters

_thisThe vehicle to check [Object]

Returns

[Bool]True if the vehicle is an APC, false otherwise

Examples

if (_this call FUNC(isKindOfApc)) exitWith {"apc"};

Public

No

Author

Dell, Zealot

+ +
+ + + + + + + + + + +
Determines what type of vehicle is being recorded to match with the more limited icon set preloaded in the OCAP playback UI.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_projectileMonitors-sqf.html b/docs/files/recorder/fnc_projectileMonitors-sqf.html new file mode 100644 index 0000000..7faa168 --- /dev/null +++ b/docs/files/recorder/fnc_projectileMonitors-sqf.html @@ -0,0 +1,49 @@ + + +fnc_projectileMonitors.sqf - OCAP2 + + + + + + + + + +

fnc_projectileMonitors.sqf

Summary
fnc_projectileMonitors.sqf
Functions
OCAP_recorder_fnc_projectileMonitorsThis initializes projectile monitoring for the purposes of moving non-bullet projectile markers across the map during playback as well as to display them on the in-game map while OCAP_isDebug is true.
Variables
OCAP_recorder_liveDebugBulletsUsed by clients to draw bullet lines.
OCAP_recorder_liveDebugMagIconsUsed by clients to draw magazine icons of non-bullet projectiles.
+ +

Functions

+ +

OCAP_recorder_fnc_projectileMonitors

Description

This initializes projectile monitoring for the purposes of moving non-bullet projectile markers across the map during playback as well as to display them on the in-game map while OCAP_isDebug is true.

On clients, it will create a “Draw” UI event handler to display both fire-lines representing bullets and markers representing non-bullet projectiles.  It will also create an event handler used by the server in OCAP_recorder_fnc_eh_firedMan to integrate new projectiles to the array being procesed by the “Draw” handler.

On the server, it will initialize <OCAP_recorder_liveMissiles> and <OCAP_recorder_liveGrenades>.  These are watch arrays that are used to track the position of non-bullet projectiles and update the extension with their positions as they travel.  This causes the effect of a ‘moving marker’ during playback.

Parameters

None

Returns

Nothing

Example

call FUNC(projectileMonitors);

Public

No

Author

IndigoFox

+ +

Variables

+ +

OCAP_recorder_liveDebugBullets

Used by clients to draw bullet lines.  Entered via OCAP_recorder_fnc_eh_firedMan and managed in ??

+ +

OCAP_recorder_liveDebugMagIcons

Used by clients to draw magazine icons of non-bullet projectiles.  Entered via OCAP_recorder_fnc_eh_firedMan and managed in ??

+ +
+ + + + + + + + + + +
Enables increased logging of addon actions.
Tracks bullet and non-bullet projectiles.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_startRecording-sqf.html b/docs/files/recorder/fnc_startRecording-sqf.html new file mode 100644 index 0000000..b066e75 --- /dev/null +++ b/docs/files/recorder/fnc_startRecording-sqf.html @@ -0,0 +1,43 @@ + + +fnc_startRecording.sqf - OCAP2 + + + + + + + + + +

fnc_startRecording.sqf

Summary
+ +

Functions

+ +

OCAP_recorder_fnc_startRecording

Description

Begins recording the current mission.

Called via OCAP_record via direct CBA event or the administrative diary entry, or by a waiter in OCAP_recorder_fnc_init (see OCAP_settings_autoStart).

Will not start recording if OCAP_recorder_recording is true and will notify players.

Parameters

None

Returns

Nothing

Examples

call FUNC(startRecording);

Public

No

Author

Dell, Zealot, IndigoFox

+ +
+ + + + + + + + + + +
Used to start or resume recording.
Initializes event listeners, event handlers, gathers OCAP_version and OCAP_extension_version, and kicks off waiters for the auto-start conditions if settings are configured to enable it.
Automatically start OCAP recordings at session start.
Global variable that represents whether or not recording is active [Bool]
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_stopRecording-sqf.html b/docs/files/recorder/fnc_stopRecording-sqf.html new file mode 100644 index 0000000..81ba12a --- /dev/null +++ b/docs/files/recorder/fnc_stopRecording-sqf.html @@ -0,0 +1,43 @@ + + +fnc_stopRecording.sqf - OCAP2 + + + + + + + + + +

fnc_stopRecording.sqf

Summary
+ +

Functions

+ +

OCAP_recorder_fnc_stopRecording

Description

Stops recording the current mission.  Can be used to pause the recording for later resumption.  Also called automatically as part of OCAP_recorder_fnc_exportData.

Called via OCAP_pause via direct CBA event or the administrative diary entry.

Parameters

None

Returns

Nothing

Examples

call FUNC(stopRecording);

Public

No

Author

Dell, Zealot, IndigoFox

+ +
+ + + + + + + + + + +
This function facilitates the actual endMission and save events in the extension, prompting it to pack the mission and upload it to the web component.
Used to pause recording.
+ + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/fnc_updateTime-sqf.html b/docs/files/recorder/fnc_updateTime-sqf.html new file mode 100644 index 0000000..195641f --- /dev/null +++ b/docs/files/recorder/fnc_updateTime-sqf.html @@ -0,0 +1,43 @@ + + +fnc_updateTime.sqf - OCAP2 + + + + + + + + + +

fnc_updateTime.sqf

Summary
fnc_updateTime.sqf
Functions
OCAP_recorder_fnc_updateTimeSends server’s system time, mission environment date/time, time multiplier setting, and time since mission start (post-briefing) to the extension.
+ +

Functions

+ +

OCAP_recorder_fnc_updateTime

Description

Sends server’s system time, mission environment date/time, time multiplier setting, and time since mission start (post-briefing) to the extension.  Will run on a recurring basis as part of <FUNC(captureLoop)> if the setting in userconfig.hpp is configured to do so.  This is required in missions that utilize time acceleration or have time skips as part of mission flow.

Parameters

_dateA manual in-game time to check.  [optional, Array]

Returns

Nothing

Examples

[] call FUNC(updateTime);

Public

No

Author

Fank

+ +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/files/recorder/script_component-hpp.html b/docs/files/recorder/script_component-hpp.html new file mode 100644 index 0000000..ecbe98c --- /dev/null +++ b/docs/files/recorder/script_component-hpp.html @@ -0,0 +1,45 @@ + + +script_component.hpp - OCAP2 + + + + + + + + + +
+ +

Macros

+ +

COMPONENT

#define COMPONENT recorder
+ +

COMPONENT_BEAUTIFIED

#define COMPONENT_BEAUTIFIED Recorder
+ +
+ + + + + + + + + + +
#define COMPONENT recorder
#define COMPONENT_BEAUTIFIED Recorder
+ + + + + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..d15bd03 --- /dev/null +++ b/docs/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/index/CBAEvents.html b/docs/index/CBAEvents.html new file mode 100644 index 0000000..5f52a58 --- /dev/null +++ b/docs/index/CBAEvents.html @@ -0,0 +1,54 @@ + + +CBA Event Index - OCAP2 + + + + + + + + + +
CBA Event Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
A
 ace_advanced_throwing_throwFiredXEH
 ace_explosives_place
OCAP_recorder_addDebugBullet
OCAP_recorder_addDebugMagIcon
C
OCAP_counterEvent
OCAP_counterInit
OCAP_customEvent
E
OCAP_exportData
H
OCAP_handleMarker
P
OCAP_pause
 Projectiles
R
OCAP_record
+ +
EGVAR(
   listener,
   aceThrowing
) = ["ace_advanced_throwing_throwFiredXEH", { _this call FUNC(eh_firedMan) }] call CBA_fnc_addEventHandler
Fired when a throwable is primed.
EGVAR(
   listener,
   aceExplosives
) = ["ace_explosives_place", { call FUNC(aceExplosives); }] call CBA_fnc_addEventHandler
Event listener for ACE3 global event indicating a mine has been placed and armed.
Triggered when a bullet is fired and the debug mode is enabled.
Triggered when a non-bullet projectile is fired and the debug mode is enabled.
+ + + +
Meant for use in custom tracking of points or score between two sides.
Meant for use in custom tracking of points or score between two sides.
Event listener for custom event text to be added to the timeline.
+ + + +
Used to stop recording & signal the extension to save and upload it to the web component.
+ + + +
Handles marker creation, modification, and deletion events.
+ + + +
Used to pause recording.
+ + + +
Used to start or resume recording.
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index/CBASettings.html b/docs/index/CBASettings.html new file mode 100644 index 0000000..da70e7d --- /dev/null +++ b/docs/index/CBASettings.html @@ -0,0 +1,62 @@ + + +CBA Setting Index - OCAP2 + + + + + + + + + +
CBA Setting Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
A
OCAP_administratorList
OCAP_settings_autoStart
E
OCAP_enabled
OCAP_settings_excludeClassFromRecord
OCAP_settings_excludeKindFromRecord
OCAP_settings_excludeMarkerFromRecord
F
OCAP_settings_frameCaptureDelay
I
OCAP_isDebug
M
OCAP_settings_minMissionTime
OCAP_settings_minPlayerCount
P
OCAP_settings_preferACEUnconscious
S
OCAP_settings_saveMissionEnded
OCAP_settings_saveOnEmpty
OCAP_settings_saveTag
T
OCAP_settings_trackTickets
OCAP_settings_trackTimeInterval
OCAP_settings_trackTimes
+ +
An array or server-visible variable referencing one that is a list of playerUIDs.
Automatically start OCAP recordings at session start.
+ + + +
Turns on or off most recording functionality.
Array of object classnames that should be excluded from recording.
Array of classnames which, along with all child classes, should be excluded from recording.
Array of prefixes.
+ + + +
Positioning, medical status, and crew states of units and vehicles will be captured every X amount of seconds.
+ + + +
Enables increased logging of addon actions.
+ + + +
A recording must be at least this long (in minutes) to auto-save.
Auto-start will begin once this player count is reached.
+ + + +
If true, will check ACE3 medical status on units.
+ + + +
If true, automatically save and export the mission when the MPEnded event fires.
Will automatically save recording when there are 0 players on the server and existing data accounts for more time than the minimum save duration setting.
If not overriden by the OCAP_exportData CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions.
+ + + +
Will track respawn ticket counts for missionNamespace and each playable faction every 30th frame.
If OCAP_settings_trackTimes is enabled, it will be checked every X capture frames.
Will continuously track in-game world time during a mission.
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index/EventHandlers.html b/docs/index/EventHandlers.html new file mode 100644 index 0000000..33534db --- /dev/null +++ b/docs/index/EventHandlers.html @@ -0,0 +1,54 @@ + + +Event Handler Index - OCAP2 + + + + + + + + + +
Event Handler Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
D
 Deleted
E
OCAP_EH_Ended
OCAP_EH_EntityKilled
OCAP_EH_EntityRespawned
 Explode
H
OCAP_EH_HandleDisconnect
 HitExplosion
 HitPart
M
 MarkerCreated
 MarkerDeleted
 MarkerUpdated
OCAP_EH_MPEnded
O
OCAP_EH_OnUserAdminStateChanged
P
OCAP_EH_PlayerConnected
 Projectiles(Bullets)
 Projectiles(Non-Bullets)
+ +
Makes extension call to draw a fire-line between the firer and the final destination.
+ + + +
Handle for the “Ended” mission event handler.
Handle for the “EntityKilled” mission event handler.
Handle for the “EntityRespawned” mission event handler.
Makes extension call to draw a fire-line between the firer and the final destination.
+ + + +
Fired when a player leaves the mission by returning to lobby or disconnecting.
Triggered when a projectile explodes and damages a part of a unit.
Triggered when a projectile hits a part of a unit.
+ + + +
Tracks marker creations.
Tracks marker deletions.
Tracks marker updates (moves).
Handle for the “MPEnded” mission event handler.
+ + + +
Handle for the “OnUserAdminStateChange” mission event handler.
+ + + +
Handle for the “PlayerConnected” mission event handler.
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index/Files.html b/docs/index/Files.html new file mode 100644 index 0000000..01e6987 --- /dev/null +++ b/docs/index/Files.html @@ -0,0 +1,42 @@ + + +File Index - OCAP2 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index/Functions.html b/docs/index/Functions.html new file mode 100644 index 0000000..73b3014 --- /dev/null +++ b/docs/index/Functions.html @@ -0,0 +1,66 @@ + + +Function Index - OCAP2 + + + + + + + + + +
Function Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
A
OCAP_recorder_fnc_aceExplosives
OCAP_recorder_fnc_addEventMission
OCAP_recorder_fnc_addUnitEventHandlers
OCAP_recorder_fnc_adminUIControl
C
OCAP_recorder_fnc_captureLoop
E
OCAP_recorder_fnc_eh_connected
OCAP_recorder_fnc_eh_disconnected
OCAP_recorder_fnc_eh_firedMan
OCAP_recorder_fnc_eh_killed
OCAP_recorder_fnc_eh_onUserAdminStateChanged
OCAP_recorder_fnc_eh_projectileHit
OCAP_recorder_fnc_entityMonitors
OCAP_recorder_fnc_exportData
G
OCAP_recorder_fnc_getAmmoMarkerData
OCAP_recorder_fnc_getClass
OCAP_recorder_fnc_getEventWeaponText
OCAP_recorder_fnc_getInstigator
OCAP_recorder_fnc_getUnitType
OCAP_recorder_fnc_getWeaponDisplayData
H
OCAP_recorder_fnc_handleCustomEvent
OCAP_recorder_fnc_handleMarkers
I
OCAP_recorder_fnc_init
OCAP_recorder_fnc_isKindOfApc
P
OCAP_recorder_fnc_projectileMonitors
S
OCAP_extension_fnc_sendData
OCAP_recorder_fnc_startRecording
OCAP_recorder_fnc_stopRecording
U
OCAP_recorder_fnc_updateTime
+ +
Adds marker on the mine’s position to the recording timeline.
Used for applying mission event handlers.
Used for applying unit-specific event handlers to units during initialization.
Runs checks to determine if a player should have the administrative diary entry added or removed upon joining the mission or logging in/out as admin.
+ + + +
This function is run unscheduled and creates a CBA PerFrameHandler object, a logic object which executes code every specified interval (OCAP_settings_frameCaptureDelay) while a condition (SHOULDSAVEEVENTS) is true.
+ + + +
This function uses the OCAP_EH_Connected event handler to log “connected” events to the timeline.
This function uses the OCAP_EH_HandleDisconnect event handler to log “disconnected” events to the timeline.
Tracks bullet and non-bullet projectiles.
Tracks when a unit is killed.
Uses OCAP_EH_OnUserAdminStateChanged to detect when someone is has logged in or out of the server and calls OCAP_recorder_fnc_adminUIControl to update the admin UI.
Tracks when a unit is hit/takes damage and saves to the timeline.
While debug mode is enabled, this function will render 2D icons and text representing all entities that have been initialized by OCAP and are not being excluded from the recording.
This function facilitates the actual endMission and save events in the extension, prompting it to pack the mission and upload it to the web component.
+ + + +
This function will intake information from OCAP_EH_FiredMan and return data used to format a marker for entry into the timeline.
Determines what type of vehicle is being recorded to match with the more limited icon set preloaded in the OCAP playback UI.
Used to identify the current weapon a unit is using that has injured or killed another.
Attempts to identify who truly pulled the trigger on a kill event.
Identifies the role of a unit using similar methodology to Arma 3’s.
Used to populate OCAP_lastFired on units in OCAP_recorder_fnc_eh_firedMan.
+ + + +
Sends custom event data to the extension to save it to the timeline.
Used for tracking all markers in the vanilla Arma 3 system.
+ + + +
Initializes event listeners, event handlers, gathers OCAP_version and OCAP_extension_version, and kicks off waiters for the auto-start conditions if settings are configured to enable it.
Helper function for OCAP_recorder_fnc_getClass to prevent APCs from being classified as Cars or Trucks.
+ + + +
This initializes projectile monitoring for the purposes of moving non-bullet projectile markers across the map during playback as well as to display them on the in-game map while OCAP_isDebug is true.
+ + + +
Manages raw extension calls and returns values / logs errors where relevant.
Begins recording the current mission.
Stops recording the current mission.
+ + + +
Sends server’s system time, mission environment date/time, time multiplier setting, and time since mission start (post-briefing) to the extension.
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index/General.html b/docs/index/General.html new file mode 100644 index 0000000..624e7f6 --- /dev/null +++ b/docs/index/General.html @@ -0,0 +1,82 @@ + + +Index - OCAP2 + + + + + + + + + +
Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
A
 ace_advanced_throwing_throwFiredXEH
 ace_explosives_place
OCAP_recorder_fnc_aceExplosives
OCAP_recorder_addDebugBullet
OCAP_recorder_addDebugMagIcon
OCAP_recorder_fnc_addEventMission
 ADDON
OCAP_recorder_fnc_addUnitEventHandlers
OCAP_administratorList
OCAP_recorder_fnc_adminUIControl
 ARR2
 Auto-Start Settings
OCAP_recorder_autoStart
OCAP_settings_autoStart
B
 BOOL
C
OCAP_recorder_captureFrameNo
OCAP_recorder_fnc_captureLoop
 CBA Events
 CBA Listener Handles
 CBA Settings
 COMPONENT
 COMPONENT_BEAUTIFIED
 COMPONENT_NAME
 Core
OCAP_counter_sides
OCAP_counterEvent
OCAP_counterInit
OCAP_customEvent
D
 Deleted
E
OCAP_recorder_fnc_eh_connected
OCAP_recorder_fnc_eh_disconnected
OCAP_recorder_fnc_eh_firedMan
OCAP_recorder_fnc_eh_killed
OCAP_recorder_fnc_eh_onUserAdminStateChanged
OCAP_recorder_fnc_eh_projectileHit
OCAP_enabled
OCAP_EH_Ended
OCAP_EH_EntityKilled
OCAP_recorder_fnc_entityMonitors
OCAP_entityMonitorsInitialized
OCAP_EH_EntityRespawned
 Event Handlers
OCAP_settings_excludeClassFromRecord
OCAP_settings_excludeKindFromRecord
OCAP_settings_excludeMarkerFromRecord
 Exclusions
 Explode
OCAP_exportData
OCAP_recorder_fnc_exportData
 Extra Tracking
F
 fnc_aceExplosives.sqf
 fnc_addEventMission.sqf
 fnc_addUnitEventHandlers.sqf
 fnc_adminUIControl.sqf
 fnc_captureLoop.sqf
 fnc_eh_connected.sqf
 fnc_eh_disconnected.sqf
 fnc_eh_firedMan.sqf
 fnc_eh_killed.sqf
 fnc_eh_onUserAdminStateChanged.sqf
 fnc_eh_projectileHit.sqf
 fnc_entityMonitors.sqf
 fnc_exportData.sqf
 fnc_getAmmoMarkerData.sqf
 fnc_getClass.sqf
 fnc_getEventWeaponText.sqf
 fnc_getInstigator.sqf
 fnc_getUnitType.sqf
 fnc_getWeaponDisplayData.sqf
 fnc_handleCustomEvent.sqf
 fnc_handleMarkers.sqf
 fnc_init.sqf
 fnc_isKindOfApc.sqf
 fnc_projectileMonitors.sqf
 fnc_sendData.sqf
 fnc_startRecording.sqf
 fnc_stopRecording.sqf
 fnc_updateTime.sqf
OCAP_recorder_frameCaptureDelay
OCAP_settings_frameCaptureDelay
 Functions
G
OCAP_recorder_fnc_getAmmoMarkerData
OCAP_recorder_fnc_getClass
OCAP_recorder_fnc_getEventWeaponText
OCAP_recorder_fnc_getInstigator
OCAP_recorder_fnc_getUnitType
OCAP_recorder_fnc_getWeaponDisplayData
H
OCAP_recorder_fnc_handleCustomEvent
OCAP_EH_HandleDisconnect
OCAP_handleMarker
OCAP_recorder_fnc_handleMarkers
OCAP_hasAdminControls
 HitExplosion
 HitPart
I
OCAP_recorder_fnc_init
OCAP_isDebug
OCAP_recorder_fnc_isKindOfApc
L
OCAP_lastFired
OCAP_listener_aceExplosives
OCAP_listener_aceThrowing
OCAP_listener_counterEvent
OCAP_listener_counterInit
OCAP_listener_customEvent
OCAP_listener_exportData
OCAP_listener_markers
OCAP_listener_pause
OCAP_listener_record
OCAP_recorder_liveDebugBullets
OCAP_recorder_liveDebugMagIcons
 LOG
M
 Macros
 MarkerCreated
 MarkerDeleted
 MarkerUpdated
OCAP_recorder_minMissionTime
OCAP_settings_minMissionTime
OCAP_settings_minPlayerCount
OCAP_EH_MPEnded
N
OCAP_recorder_nextId
O
OCAP_EH_OnUserAdminStateChanged
+ +
EGVAR(
   listener,
   aceThrowing
) = ["ace_advanced_throwing_throwFiredXEH", { _this call FUNC(eh_firedMan) }] call CBA_fnc_addEventHandler
Fired when a throwable is primed.
EGVAR(
   listener,
   aceExplosives
) = ["ace_explosives_place", { call FUNC(aceExplosives); }] call CBA_fnc_addEventHandler
Event listener for ACE3 global event indicating a mine has been placed and armed.
Adds marker on the mine’s position to the recording timeline.
Triggered when a bullet is fired and the debug mode is enabled.
Triggered when a non-bullet projectile is fired and the debug mode is enabled.
Used for applying mission event handlers.
PREFIX_COMPONENT
Used for applying unit-specific event handlers to units during initialization.
An array or server-visible variable referencing one that is a list of playerUIDs.
Runs checks to determine if a player should have the administrative diary entry added or removed upon joining the mission or logging in/out as admin.
#define ARR2(_arg1,
_arg2) [_arg1, _arg2]
Resolves arguments to array, used for entries to LOG that requires array input.
Global variable that represents whether or not recording should automatically start.
Automatically start OCAP recordings at session start.
+ + + +
#define BOOL(_cond) ([0,1] select (_cond))
Forces a true/false return of input.
+ + + +
Global variable that represents the current frame number [Number]
This function is run unscheduled and creates a CBA PerFrameHandler object, a logic object which executes code every specified interval (OCAP_settings_frameCaptureDelay) while a condition (SHOULDSAVEEVENTS) is true.
#define COMPONENT extension
#define COMPONENT_BEAUTIFIED Extension
#define COMPONENT_NAME QUOTE(PREFIX COMPONENT_BEAUTIFIED)
Sides that are tracked by the custom counter system.
Meant for use in custom tracking of points or score between two sides.
Meant for use in custom tracking of points or score between two sides.
Event listener for custom event text to be added to the timeline.
+ + + +
Makes extension call to draw a fire-line between the firer and the final destination.
+ + + +
This function uses the OCAP_EH_Connected event handler to log “connected” events to the timeline.
This function uses the OCAP_EH_HandleDisconnect event handler to log “disconnected” events to the timeline.
Tracks bullet and non-bullet projectiles.
Tracks when a unit is killed.
Uses OCAP_EH_OnUserAdminStateChanged to detect when someone is has logged in or out of the server and calls OCAP_recorder_fnc_adminUIControl to update the admin UI.
Tracks when a unit is hit/takes damage and saves to the timeline.
Turns on or off most recording functionality.
Handle for the “Ended” mission event handler.
Handle for the “EntityKilled” mission event handler.
While debug mode is enabled, this function will render 2D icons and text representing all entities that have been initialized by OCAP and are not being excluded from the recording.
This variable on the server indicates whether or not the entity monitors have been initialized for all clients + JIP.
Handle for the “EntityRespawned” mission event handler.
Array of object classnames that should be excluded from recording.
Array of classnames which, along with all child classes, should be excluded from recording.
Array of prefixes.
Makes extension call to draw a fire-line between the firer and the final destination.
Used to stop recording & signal the extension to save and upload it to the web component.
This function facilitates the actual endMission and save events in the extension, prompting it to pack the mission and upload it to the web component.
+ + + +
Global variable that represents the delay between frame captures in seconds.
Positioning, medical status, and crew states of units and vehicles will be captured every X amount of seconds.
+ + + +
This function will intake information from OCAP_EH_FiredMan and return data used to format a marker for entry into the timeline.
Determines what type of vehicle is being recorded to match with the more limited icon set preloaded in the OCAP playback UI.
Used to identify the current weapon a unit is using that has injured or killed another.
Attempts to identify who truly pulled the trigger on a kill event.
Identifies the role of a unit using similar methodology to Arma 3’s.
Used to populate OCAP_lastFired on units in OCAP_recorder_fnc_eh_firedMan.
+ + + +
Sends custom event data to the extension to save it to the timeline.
Fired when a player leaves the mission by returning to lobby or disconnecting.
Handles marker creation, modification, and deletion events.
Used for tracking all markers in the vanilla Arma 3 system.
Applied on units processed in OCAP_recorder_fnc_adminUIControl.
Triggered when a projectile explodes and damages a part of a unit.
Triggered when a projectile hits a part of a unit.
+ + + +
Initializes event listeners, event handlers, gathers OCAP_version and OCAP_extension_version, and kicks off waiters for the auto-start conditions if settings are configured to enable it.
Enables increased logging of addon actions.
Helper function for OCAP_recorder_fnc_getClass to prevent APCs from being classified as Cars or Trucks.
+ + + +
Indicates a formatted string of the last weapon and magazine type fired by the unit.
Handle for ace_explosives_place listener.
Handle for ace_advanced_throwing_throwFiredXEH listener.
Handle for OCAP_counterEvent listener.
Handle for OCAP_counterInit listener.
Handle for OCAP_customEvent listener.
Handle for OCAP_exportData listener.
Contains handle for OCAP_handleMarker CBA event handler.
Handle for OCAP_pause listener.
Handle for OCAP_record listener.
Used by clients to draw bullet lines.
Used by clients to draw magazine icons of non-bullet projectiles.
#define OCAPEXTLOG(_args) [":LOG:", _args] call EFUNC(extension,sendData)
Used for logging messages to the extension (ocap-ext log file).
+ + + +
Tracks marker creations.
Tracks marker deletions.
Tracks marker updates (moves).
Global variable that represents the minimum mission time in seconds to qualify for saving.
A recording must be at least this long (in minutes) to auto-save.
Auto-start will begin once this player count is reached.
Handle for the “MPEnded” mission event handler.
+ + + +
Global variable that represents the next available id to assign to a unit or vehicle [Number]
+ + + +
Handle for the “OnUserAdminStateChange” mission event handler.
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index/General2.html b/docs/index/General2.html new file mode 100644 index 0000000..89a36c9 --- /dev/null +++ b/docs/index/General2.html @@ -0,0 +1,54 @@ + + +Index - OCAP2 + + + + + + + + + +
Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
P
OCAP_pause
OCAP_PFHObject
OCAP_EH_PlayerConnected
OCAP_settings_preferACEUnconscious
 PREFIX
OCAP_recorder_fnc_projectileMonitors
 Projectiles
 Projectiles(Bullets)
 Projectiles(Non-Bullets)
R
OCAP_record
OCAP_recorder_recording
S
 Save/Export Settings
OCAP_settings_saveMissionEnded
OCAP_settings_saveOnEmpty
OCAP_settings_saveTag
 script_component.hpp
 script_macros.hpp
OCAP_extension_fnc_sendData
 SHOULDSAVEEVENTS
OCAP_recorder_fnc_startRecording
OCAP_recorder_fnc_stopRecording
 SYSCHAT
T
OCAP_recorder_trackedMarkers
OCAP_settings_trackTickets
OCAP_settings_trackTimeInterval
OCAP_settings_trackTimes
U
OCAP_recorder_fnc_updateTime
V
 Variables
OCAP_version
OCAP_extension_version
 VERSION
 VERSION_AR
 VERSION_REQUIRED
 VERSION_STR
+ +
Used to pause recording.
The CBA PerFrameHandler object that is created and used to run the capture loop.
Handle for the “PlayerConnected” mission event handler.
If true, will check ACE3 medical status on units.
#define PREFIX OCAP
This initializes projectile monitoring for the purposes of moving non-bullet projectile markers across the map during playback as well as to display them on the in-game map while OCAP_isDebug is true.
+ + + +
Used to start or resume recording.
Global variable that represents whether or not recording is active [Bool]
+ + + +
If true, automatically save and export the mission when the MPEnded event fires.
Will automatically save recording when there are 0 players on the server and existing data accounts for more time than the minimum save duration setting.
If not overriden by the OCAP_exportData CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions.
Defines macros imported to other functions
Manages raw extension calls and returns values / logs errors where relevant.
#define SHOULDSAVEEVENTS (
   (missionNamespace getVariable [QGVAR(recording), false]) && missionNamespace getVariable [QGVAR(startTime), -1] -1
)
Used to determine if events should currently be saved based on OCAP_recorder_recording and OCAP_recorder_startTime.
Begins recording the current mission.
Stops recording the current mission.
#define SYSCHAT remoteExec ["systemChat", [0, -2] select isDedicated]
Used for debug purposes to send a string to all clients with interfaces.
+ + + +
Persistent global variable on server that defines unique marker names currently being tracked.
Will track respawn ticket counts for missionNamespace and each playable faction every 30th frame.
If OCAP_settings_trackTimes is enabled, it will be checked every X capture frames.
Will continuously track in-game world time during a mission.
+ + + +
Sends server’s system time, mission environment date/time, time multiplier setting, and time since mission start (post-briefing) to the extension.
+ + + +
Global variable that represents the version of OCAP addon being used [String]
Global variable that represents the version of OCAP extension being used [String]
#define VERSION 2.0
#define VERSION_AR 2,0,0
#define VERSION_REQUIRED 2.10
#define VERSION_STR 2.0.0
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index/Macros.html b/docs/index/Macros.html new file mode 100644 index 0000000..3b9b603 --- /dev/null +++ b/docs/index/Macros.html @@ -0,0 +1,58 @@ + + +Macro Index - OCAP2 + + + + + + + + + +
Macro Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
A
 ADDON
 ARR2
B
 BOOL
C
 COMPONENT
 COMPONENT_BEAUTIFIED
 COMPONENT_NAME
L
 LOG
P
 PREFIX
S
 SHOULDSAVEEVENTS
 SYSCHAT
V
 VERSION
 VERSION_AR
 VERSION_REQUIRED
 VERSION_STR
+ +
PREFIX_COMPONENT
#define ARR2(_arg1,
_arg2) [_arg1, _arg2]
Resolves arguments to array, used for entries to LOG that requires array input.
+ + + +
#define BOOL(_cond) ([0,1] select (_cond))
Forces a true/false return of input.
+ + + +
#define COMPONENT extension
#define COMPONENT_BEAUTIFIED Extension
#define COMPONENT_NAME QUOTE(PREFIX COMPONENT_BEAUTIFIED)
+ + + +
#define OCAPEXTLOG(_args) [":LOG:", _args] call EFUNC(extension,sendData)
Used for logging messages to the extension (ocap-ext log file).
+ + + +
#define PREFIX OCAP
+ + + +
#define SHOULDSAVEEVENTS (
   (missionNamespace getVariable [QGVAR(recording), false]) && missionNamespace getVariable [QGVAR(startTime), -1] -1
)
Used to determine if events should currently be saved based on OCAP_recorder_recording and OCAP_recorder_startTime.
#define SYSCHAT remoteExec ["systemChat", [0, -2] select isDedicated]
Used for debug purposes to send a string to all clients with interfaces.
+ + + +
#define VERSION 2.0
#define VERSION_AR 2,0,0
#define VERSION_REQUIRED 2.10
#define VERSION_STR 2.0.0
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index/Variables.html b/docs/index/Variables.html new file mode 100644 index 0000000..a3859f8 --- /dev/null +++ b/docs/index/Variables.html @@ -0,0 +1,78 @@ + + +Variable Index - OCAP2 + + + + + + + + + +
Variable Index
$#! · 0-9 · A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z
A
OCAP_recorder_autoStart
C
OCAP_recorder_captureFrameNo
 CBA Listener Handles
OCAP_counter_sides
E
OCAP_entityMonitorsInitialized
F
OCAP_recorder_frameCaptureDelay
H
OCAP_hasAdminControls
L
OCAP_lastFired
OCAP_listener_aceExplosives
OCAP_listener_aceThrowing
OCAP_listener_counterEvent
OCAP_listener_counterInit
OCAP_listener_customEvent
OCAP_listener_exportData
OCAP_listener_markers
OCAP_listener_pause
OCAP_listener_record
OCAP_recorder_liveDebugBullets
OCAP_recorder_liveDebugMagIcons
M
OCAP_recorder_minMissionTime
N
OCAP_recorder_nextId
P
OCAP_PFHObject
R
OCAP_recorder_recording
T
OCAP_recorder_trackedMarkers
V
OCAP_version
OCAP_extension_version
+ +
Global variable that represents whether or not recording should automatically start.
+ + + +
Global variable that represents the current frame number [Number]
Sides that are tracked by the custom counter system.
+ + + +
This variable on the server indicates whether or not the entity monitors have been initialized for all clients + JIP.
+ + + +
Global variable that represents the delay between frame captures in seconds.
+ + + +
Applied on units processed in OCAP_recorder_fnc_adminUIControl.
+ + + +
Indicates a formatted string of the last weapon and magazine type fired by the unit.
Handle for ace_explosives_place listener.
Handle for ace_advanced_throwing_throwFiredXEH listener.
Handle for OCAP_counterEvent listener.
Handle for OCAP_counterInit listener.
Handle for OCAP_customEvent listener.
Handle for OCAP_exportData listener.
Contains handle for OCAP_handleMarker CBA event handler.
Handle for OCAP_pause listener.
Handle for OCAP_record listener.
Used by clients to draw bullet lines.
Used by clients to draw magazine icons of non-bullet projectiles.
+ + + +
Global variable that represents the minimum mission time in seconds to qualify for saving.
+ + + +
Global variable that represents the next available id to assign to a unit or vehicle [Number]
+ + + +
The CBA PerFrameHandler object that is created and used to run the capture loop.
+ + + +
Global variable that represents whether or not recording is active [Bool]
+ + + +
Persistent global variable on server that defines unique marker names currently being tracked.
+ + + +
Global variable that represents the version of OCAP addon being used [String]
Global variable that represents the version of OCAP extension being used [String]
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/javascript/main.js b/docs/javascript/main.js new file mode 100644 index 0000000..b008be9 --- /dev/null +++ b/docs/javascript/main.js @@ -0,0 +1,841 @@ +// This file is part of Natural Docs, which is Copyright 2003-2010 Greg Valure +// Natural Docs is licensed under version 3 of the GNU Affero General Public License (AGPL) +// Refer to License.txt for the complete details + +// This file may be distributed with documentation files generated by Natural Docs. +// Such documentation is not covered by Natural Docs' copyright and licensing, +// and may have its own copyright and distribution terms as decided by its author. + + +// +// Browser Styles +// ____________________________________________________________________________ + +var agt=navigator.userAgent.toLowerCase(); +var browserType; +var browserVer; + +if (agt.indexOf("opera") != -1) + { + browserType = "Opera"; + + if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1) + { browserVer = "Opera7"; } + else if (agt.indexOf("opera 8") != -1 || agt.indexOf("opera/8") != -1) + { browserVer = "Opera8"; } + else if (agt.indexOf("opera 9") != -1 || agt.indexOf("opera/9") != -1) + { browserVer = "Opera9"; } + } + +else if (agt.indexOf("applewebkit") != -1) + { + browserType = "Safari"; + + if (agt.indexOf("version/3") != -1) + { browserVer = "Safari3"; } + else if (agt.indexOf("safari/4") != -1) + { browserVer = "Safari2"; } + } + +else if (agt.indexOf("khtml") != -1) + { + browserType = "Konqueror"; + } + +else if (agt.indexOf("msie") != -1) + { + browserType = "IE"; + + if (agt.indexOf("msie 6") != -1) + { browserVer = "IE6"; } + else if (agt.indexOf("msie 7") != -1) + { browserVer = "IE7"; } + } + +else if (agt.indexOf("gecko") != -1) + { + browserType = "Firefox"; + + if (agt.indexOf("rv:1.7") != -1) + { browserVer = "Firefox1"; } + else if (agt.indexOf("rv:1.8)") != -1 || agt.indexOf("rv:1.8.0") != -1) + { browserVer = "Firefox15"; } + else if (agt.indexOf("rv:1.8.1") != -1) + { browserVer = "Firefox2"; } + } + + +// +// Support Functions +// ____________________________________________________________________________ + + +function GetXPosition(item) + { + var position = 0; + + if (item.offsetWidth != null) + { + while (item != document.body && item != null) + { + position += item.offsetLeft; + item = item.offsetParent; + }; + }; + + return position; + }; + + +function GetYPosition(item) + { + var position = 0; + + if (item.offsetWidth != null) + { + while (item != document.body && item != null) + { + position += item.offsetTop; + item = item.offsetParent; + }; + }; + + return position; + }; + + +function MoveToPosition(item, x, y) + { + // Opera 5 chokes on the px extension, so it can use the Microsoft one instead. + + if (item.style.left != null) + { + item.style.left = x + "px"; + item.style.top = y + "px"; + } + else if (item.style.pixelLeft != null) + { + item.style.pixelLeft = x; + item.style.pixelTop = y; + }; + }; + + +// +// Menu +// ____________________________________________________________________________ + + +function ToggleMenu(id) + { + if (!window.document.getElementById) + { return; }; + + var display = window.document.getElementById(id).style.display; + + if (display == "none") + { display = "block"; } + else + { display = "none"; } + + window.document.getElementById(id).style.display = display; + } + +function HideAllBut(ids, max) + { + if (document.getElementById) + { + ids.sort( function(a,b) { return a - b; } ); + var number = 1; + + while (number < max) + { + if (ids.length > 0 && number == ids[0]) + { ids.shift(); } + else + { + document.getElementById("MGroupContent" + number).style.display = "none"; + }; + + number++; + }; + }; + } + + +// +// Tooltips +// ____________________________________________________________________________ + + +var tooltipTimer = 0; + +function ShowTip(event, tooltipID, linkID) + { + if (tooltipTimer) + { clearTimeout(tooltipTimer); }; + + var docX = event.clientX + window.pageXOffset; + var docY = event.clientY + window.pageYOffset; + + var showCommand = "ReallyShowTip('" + tooltipID + "', '" + linkID + "', " + docX + ", " + docY + ")"; + + tooltipTimer = setTimeout(showCommand, 1000); + } + +function ReallyShowTip(tooltipID, linkID, docX, docY) + { + tooltipTimer = 0; + + var tooltip; + var link; + + if (document.getElementById) + { + tooltip = document.getElementById(tooltipID); + link = document.getElementById(linkID); + } +/* else if (document.all) + { + tooltip = eval("document.all['" + tooltipID + "']"); + link = eval("document.all['" + linkID + "']"); + } +*/ + if (tooltip) + { + var left = GetXPosition(link); + var top = GetYPosition(link); + top += link.offsetHeight; + + + // The fallback method is to use the mouse X and Y relative to the document. We use a separate if and test if its a number + // in case some browser snuck through the above if statement but didn't support everything. + + if (!isFinite(top) || top == 0) + { + left = docX; + top = docY; + } + + // Some spacing to get it out from under the cursor. + + top += 10; + + // Make sure the tooltip doesnt get smushed by being too close to the edge, or in some browsers, go off the edge of the + // page. We do it here because Konqueror does get offsetWidth right even if it doesnt get the positioning right. + + if (tooltip.offsetWidth != null) + { + var width = tooltip.offsetWidth; + var docWidth = document.body.clientWidth; + + if (left + width > docWidth) + { left = docWidth - width - 1; } + + // If there's a horizontal scroll bar we could go past zero because it's using the page width, not the window width. + if (left < 0) + { left = 0; }; + } + + MoveToPosition(tooltip, left, top); + tooltip.style.visibility = "visible"; + } + } + +function HideTip(tooltipID) + { + if (tooltipTimer) + { + clearTimeout(tooltipTimer); + tooltipTimer = 0; + } + + var tooltip; + + if (document.getElementById) + { tooltip = document.getElementById(tooltipID); } + else if (document.all) + { tooltip = eval("document.all['" + tooltipID + "']"); } + + if (tooltip) + { tooltip.style.visibility = "hidden"; } + } + + +// +// Blockquote fix for IE +// ____________________________________________________________________________ + + +function NDOnLoad() + { + if (browserVer == "IE6") + { + var scrollboxes = document.getElementsByTagName('blockquote'); + + if (scrollboxes.item(0)) + { + NDDoResize(); + window.onresize=NDOnResize; + }; + }; + }; + + +var resizeTimer = 0; + +function NDOnResize() + { + if (resizeTimer != 0) + { clearTimeout(resizeTimer); }; + + resizeTimer = setTimeout(NDDoResize, 250); + }; + + +function NDDoResize() + { + var scrollboxes = document.getElementsByTagName('blockquote'); + + var i; + var item; + + i = 0; + while (item = scrollboxes.item(i)) + { + item.style.width = 100; + i++; + }; + + i = 0; + while (item = scrollboxes.item(i)) + { + item.style.width = item.parentNode.offsetWidth; + i++; + }; + + clearTimeout(resizeTimer); + resizeTimer = 0; + } + + + +/* ________________________________________________________________________________________________________ + + Class: SearchPanel + ________________________________________________________________________________________________________ + + A class handling everything associated with the search panel. + + Parameters: + + name - The name of the global variable that will be storing this instance. Is needed to be able to set timeouts. + mode - The mode the search is going to work in. Pass CommandLineOption()>, so the + value will be something like "HTML" or "FramedHTML". + + ________________________________________________________________________________________________________ +*/ + + +function SearchPanel(name, mode, resultsPath) + { + if (!name || !mode || !resultsPath) + { alert("Incorrect parameters to SearchPanel."); }; + + + // Group: Variables + // ________________________________________________________________________ + + /* + var: name + The name of the global variable that will be storing this instance of the class. + */ + this.name = name; + + /* + var: mode + The mode the search is going to work in, such as "HTML" or "FramedHTML". + */ + this.mode = mode; + + /* + var: resultsPath + The relative path from the current HTML page to the results page directory. + */ + this.resultsPath = resultsPath; + + /* + var: keyTimeout + The timeout used between a keystroke and when a search is performed. + */ + this.keyTimeout = 0; + + /* + var: keyTimeoutLength + The length of in thousandths of a second. + */ + this.keyTimeoutLength = 500; + + /* + var: lastSearchValue + The last search string executed, or an empty string if none. + */ + this.lastSearchValue = ""; + + /* + var: lastResultsPage + The last results page. The value is only relevant if is set. + */ + this.lastResultsPage = ""; + + /* + var: deactivateTimeout + + The timeout used between when a control is deactivated and when the entire panel is deactivated. Is necessary + because a control may be deactivated in favor of another control in the same panel, in which case it should stay + active. + */ + this.deactivateTimout = 0; + + /* + var: deactivateTimeoutLength + The length of in thousandths of a second. + */ + this.deactivateTimeoutLength = 200; + + + + + // Group: DOM Elements + // ________________________________________________________________________ + + + // Function: DOMSearchField + this.DOMSearchField = function() + { return document.getElementById("MSearchField"); }; + + // Function: DOMSearchType + this.DOMSearchType = function() + { return document.getElementById("MSearchType"); }; + + // Function: DOMPopupSearchResults + this.DOMPopupSearchResults = function() + { return document.getElementById("MSearchResults"); }; + + // Function: DOMPopupSearchResultsWindow + this.DOMPopupSearchResultsWindow = function() + { return document.getElementById("MSearchResultsWindow"); }; + + // Function: DOMSearchPanel + this.DOMSearchPanel = function() + { return document.getElementById("MSearchPanel"); }; + + + + + // Group: Event Handlers + // ________________________________________________________________________ + + + /* + Function: OnSearchFieldFocus + Called when focus is added or removed from the search field. + */ + this.OnSearchFieldFocus = function(isActive) + { + this.Activate(isActive); + }; + + + /* + Function: OnSearchFieldChange + Called when the content of the search field is changed. + */ + this.OnSearchFieldChange = function() + { + if (this.keyTimeout) + { + clearTimeout(this.keyTimeout); + this.keyTimeout = 0; + }; + + var searchValue = this.DOMSearchField().value.replace(/ +/g, ""); + + if (searchValue != this.lastSearchValue) + { + if (searchValue != "") + { + this.keyTimeout = setTimeout(this.name + ".Search()", this.keyTimeoutLength); + } + else + { + if (this.mode == "HTML") + { this.DOMPopupSearchResultsWindow().style.display = "none"; }; + this.lastSearchValue = ""; + }; + }; + }; + + + /* + Function: OnSearchTypeFocus + Called when focus is added or removed from the search type. + */ + this.OnSearchTypeFocus = function(isActive) + { + this.Activate(isActive); + }; + + + /* + Function: OnSearchTypeChange + Called when the search type is changed. + */ + this.OnSearchTypeChange = function() + { + var searchValue = this.DOMSearchField().value.replace(/ +/g, ""); + + if (searchValue != "") + { + this.Search(); + }; + }; + + + + // Group: Action Functions + // ________________________________________________________________________ + + + /* + Function: CloseResultsWindow + Closes the results window. + */ + this.CloseResultsWindow = function() + { + this.DOMPopupSearchResultsWindow().style.display = "none"; + this.Activate(false, true); + }; + + + /* + Function: Search + Performs a search. + */ + this.Search = function() + { + this.keyTimeout = 0; + + var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + var searchTopic = this.DOMSearchType().value; + + var pageExtension = searchValue.substr(0,1); + + if (pageExtension.match(/^[a-z]/i)) + { pageExtension = pageExtension.toUpperCase(); } + else if (pageExtension.match(/^[0-9]/)) + { pageExtension = 'Numbers'; } + else + { pageExtension = "Symbols"; }; + + var resultsPage; + var resultsPageWithSearch; + var hasResultsPage; + + // indexSectionsWithContent is defined in searchdata.js + if (indexSectionsWithContent[searchTopic][pageExtension] == true) + { + resultsPage = this.resultsPath + '/' + searchTopic + pageExtension + '.html'; + resultsPageWithSearch = resultsPage+'?'+escape(searchValue); + hasResultsPage = true; + } + else + { + resultsPage = this.resultsPath + '/NoResults.html'; + resultsPageWithSearch = resultsPage; + hasResultsPage = false; + }; + + var resultsFrame; + if (this.mode == "HTML") + { resultsFrame = window.frames.MSearchResults; } + else if (this.mode == "FramedHTML") + { resultsFrame = window.top.frames['Content']; }; + + + if (resultsPage != this.lastResultsPage || + + // Bug in IE. If everything becomes hidden in a run, none of them will be able to be reshown in the next for some + // reason. It counts the right number of results, and you can even read the display as "block" after setting it, but it + // just doesn't work in IE 6 or IE 7. So if we're on the right page but the previous search had no results, reload the + // page anyway to get around the bug. + (browserType == "IE" && hasResultsPage && + (!resultsFrame.searchResults || resultsFrame.searchResults.lastMatchCount == 0)) ) + + { + resultsFrame.location.href = resultsPageWithSearch; + } + + // So if the results page is right and there's no IE bug, reperform the search on the existing page. We have to check if there + // are results because NoResults.html doesn't have any JavaScript, and it would be useless to do anything on that page even + // if it did. + else if (hasResultsPage) + { + // We need to check if this exists in case the frame is present but didn't finish loading. + if (resultsFrame.searchResults) + { resultsFrame.searchResults.Search(searchValue); } + + // Otherwise just reload instead of waiting. + else + { resultsFrame.location.href = resultsPageWithSearch; }; + }; + + + var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + + if (this.mode == "HTML" && domPopupSearchResultsWindow.style.display != "block") + { + var domSearchType = this.DOMSearchType(); + + var left = GetXPosition(domSearchType); + var top = GetYPosition(domSearchType) + domSearchType.offsetHeight; + + MoveToPosition(domPopupSearchResultsWindow, left, top); + domPopupSearchResultsWindow.style.display = 'block'; + }; + + + this.lastSearchValue = searchValue; + this.lastResultsPage = resultsPage; + }; + + + + // Group: Activation Functions + // Functions that handle whether the entire panel is active or not. + // ________________________________________________________________________ + + + /* + Function: Activate + + Activates or deactivates the search panel, resetting things to their default values if necessary. You can call this on every + control's OnBlur() and it will handle not deactivating the entire panel when focus is just switching between them transparently. + + Parameters: + + isActive - Whether you're activating or deactivating the panel. + ignoreDeactivateDelay - Set if you're positive the action will deactivate the panel and thus want to skip the delay. + */ + this.Activate = function(isActive, ignoreDeactivateDelay) + { + // We want to ignore isActive being false while the results window is open. + if (isActive || (this.mode == "HTML" && this.DOMPopupSearchResultsWindow().style.display == "block")) + { + if (this.inactivateTimeout) + { + clearTimeout(this.inactivateTimeout); + this.inactivateTimeout = 0; + }; + + this.DOMSearchPanel().className = 'MSearchPanelActive'; + + var searchField = this.DOMSearchField(); + + if (searchField.value == 'Search') + { searchField.value = ""; } + } + else if (!ignoreDeactivateDelay) + { + this.inactivateTimeout = setTimeout(this.name + ".InactivateAfterTimeout()", this.inactivateTimeoutLength); + } + else + { + this.InactivateAfterTimeout(); + }; + }; + + + /* + Function: InactivateAfterTimeout + + Called by , which is set by . Inactivation occurs on a timeout because a control may + receive OnBlur() when focus is really transferring to another control in the search panel. In this case we don't want to + actually deactivate the panel because not only would that cause a visible flicker but it could also reset the search value. + So by doing it on a timeout instead, there's a short period where the second control's OnFocus() can cancel the deactivation. + */ + this.InactivateAfterTimeout = function() + { + this.inactivateTimeout = 0; + + this.DOMSearchPanel().className = 'MSearchPanelInactive'; + this.DOMSearchField().value = "Search"; + + this.lastSearchValue = ""; + this.lastResultsPage = ""; + }; + }; + + + + +/* ________________________________________________________________________________________________________ + + Class: SearchResults + _________________________________________________________________________________________________________ + + The class that handles everything on the search results page. + _________________________________________________________________________________________________________ +*/ + + +function SearchResults(name, mode) + { + /* + var: mode + The mode the search is going to work in, such as "HTML" or "FramedHTML". + */ + this.mode = mode; + + /* + var: lastMatchCount + The number of matches from the last run of . + */ + this.lastMatchCount = 0; + + + /* + Function: Toggle + Toggles the visibility of the passed element ID. + */ + this.Toggle = function(id) + { + if (this.mode == "FramedHTML") + { return; }; + + var parentElement = document.getElementById(id); + + var element = parentElement.firstChild; + + while (element && element != parentElement) + { + if (element.nodeName == 'DIV' && element.className == 'ISubIndex') + { + if (element.style.display == 'block') + { element.style.display = "none"; } + else + { element.style.display = 'block'; } + }; + + if (element.nodeName == 'DIV' && element.hasChildNodes()) + { element = element.firstChild; } + else if (element.nextSibling) + { element = element.nextSibling; } + else + { + do + { + element = element.parentNode; + } + while (element && element != parentElement && !element.nextSibling); + + if (element && element != parentElement) + { element = element.nextSibling; }; + }; + }; + }; + + + /* + Function: Search + + Searches for the passed string. If there is no parameter, it takes it from the URL query. + + Always returns true, since other documents may try to call it and that may or may not be possible. + */ + this.Search = function(search) + { + if (!search) + { + search = window.location.search; + search = search.substring(1); // Remove the leading ? + search = unescape(search); + }; + + search = search.replace(/^ +/, ""); + search = search.replace(/ +$/, ""); + search = search.toLowerCase(); + + if (search.match(/[^a-z0-9]/)) // Just a little speedup so it doesn't have to go through the below unnecessarily. + { + search = search.replace(/\_/g, "_und"); + search = search.replace(/\ +/gi, "_spc"); + search = search.replace(/\~/g, "_til"); + search = search.replace(/\!/g, "_exc"); + search = search.replace(/\@/g, "_att"); + search = search.replace(/\#/g, "_num"); + search = search.replace(/\$/g, "_dol"); + search = search.replace(/\%/g, "_pct"); + search = search.replace(/\^/g, "_car"); + search = search.replace(/\&/g, "_amp"); + search = search.replace(/\*/g, "_ast"); + search = search.replace(/\(/g, "_lpa"); + search = search.replace(/\)/g, "_rpa"); + search = search.replace(/\-/g, "_min"); + search = search.replace(/\+/g, "_plu"); + search = search.replace(/\=/g, "_equ"); + search = search.replace(/\{/g, "_lbc"); + search = search.replace(/\}/g, "_rbc"); + search = search.replace(/\[/g, "_lbk"); + search = search.replace(/\]/g, "_rbk"); + search = search.replace(/\:/g, "_col"); + search = search.replace(/\;/g, "_sco"); + search = search.replace(/\"/g, "_quo"); + search = search.replace(/\'/g, "_apo"); + search = search.replace(/\/g, "_ran"); + search = search.replace(/\,/g, "_com"); + search = search.replace(/\./g, "_per"); + search = search.replace(/\?/g, "_que"); + search = search.replace(/\//g, "_sla"); + search = search.replace(/[^a-z0-9\_]i/gi, "_zzz"); + }; + + var resultRows = document.getElementsByTagName("div"); + var matches = 0; + + var i = 0; + while (i < resultRows.length) + { + var row = resultRows.item(i); + + if (row.className == "SRResult") + { + var rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); + + if (search.length <= rowMatchName.length && rowMatchName.substr(0, search.length) == search) + { + row.style.display = "block"; + matches++; + } + else + { row.style.display = "none"; }; + }; + + i++; + }; + + document.getElementById("Searching").style.display="none"; + + if (matches == 0) + { document.getElementById("NoMatches").style.display="block"; } + else + { document.getElementById("NoMatches").style.display="none"; } + + this.lastMatchCount = matches; + + return true; + }; + }; + diff --git a/docs/javascript/prettify.js b/docs/javascript/prettify.js new file mode 100644 index 0000000..fda4bf1 --- /dev/null +++ b/docs/javascript/prettify.js @@ -0,0 +1,1526 @@ + +// This code comes from the December 2009 release of Google Prettify, which is Copyright 2006 Google Inc. +// Minor modifications are marked with "ND Change" comments. +// As part of Natural Docs, this code is licensed under version 3 of the GNU Affero General Public License (AGPL.) +// However, it may also be obtained separately under version 2.0 of the Apache License. +// Refer to License.txt for the complete details + + +// Main code +// ____________________________________________________________________________ + +// Copyright (C) 2006 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview + * some functions for browser-side pretty printing of code contained in html. + *

+ * + * For a fairly comprehensive set of languages see the + * README + * file that came with this source. At a minimum, the lexer should work on a + * number of languages including C and friends, Java, Python, Bash, SQL, HTML, + * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk + * and a subset of Perl, but, because of commenting conventions, doesn't work on + * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class. + *

+ * Usage:

    + *
  1. include this source file in an html page via + * {@code } + *
  2. define style rules. See the example page for examples. + *
  3. mark the {@code
    } and {@code } tags in your source with
    + *    {@code class=prettyprint.}
    + *    You can also use the (html deprecated) {@code } tag, but the pretty
    + *    printer needs to do more substantial DOM manipulations to support that, so
    + *    some css styles may not be preserved.
    + * </ol>
    + * That's it.  I wanted to keep the API as simple as possible, so there's no
    + * need to specify which language the code is in, but if you wish, you can add
    + * another class to the {@code <pre>} or {@code <code>} element to specify the
    + * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
    + * starts with "lang-" followed by a file extension, specifies the file type.
    + * See the "lang-*.js" files in this directory for code that implements
    + * per-language file handlers.
    + * <p>
    + * Change log:<br>
    + * cbeust, 2006/08/22
    + * <blockquote>
    + *   Java annotations (start with "@") are now captured as literals ("lit")
    + * </blockquote>
    + * @requires console
    + * @overrides window
    + */
    +
    +// JSLint declarations
    +/*global console, document, navigator, setTimeout, window */
    +
    +/**
    + * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
    + * UI events.
    + * If set to {@code false}, {@code prettyPrint()} is synchronous.
    + */
    +window['PR_SHOULD_USE_CONTINUATION'] = true;
    +
    +/** the number of characters between tab columns */
    +window['PR_TAB_WIDTH'] = 8;
    +
    +/** Walks the DOM returning a properly escaped version of innerHTML.
    +  * @param {Node} node
    +  * @param {Array.<string>} out output buffer that receives chunks of HTML.
    +  */
    +window['PR_normalizedHtml']
    +
    +/** Contains functions for creating and registering new language handlers.
    +  * @type {Object}
    +  */
    +  = window['PR']
    +
    +/** Pretty print a chunk of code.
    +  *
    +  * @param {string} sourceCodeHtml code as html
    +  * @return {string} code as html, but prettier
    +  */
    +  = window['prettyPrintOne']
    +/** Find all the {@code <pre>} and {@code <code>} tags in the DOM with
    +  * {@code class=prettyprint} and prettify them.
    +  * @param {Function?} opt_whenDone if specified, called when the last entry
    +  *     has been finished.
    +  */
    +  = window['prettyPrint'] = void 0;
    +
    +/** browser detection. @extern @returns false if not IE, otherwise the major version. */
    +window['_pr_isIE6'] = function () {
    +  var ieVersion = navigator && navigator.userAgent &&
    +      navigator.userAgent.match(/\bMSIE ([678])\./);
    +  ieVersion = ieVersion ? +ieVersion[1] : false;
    +  window['_pr_isIE6'] = function () { return ieVersion; };
    +  return ieVersion;
    +};
    +
    +
    +(function () {
    +  // Keyword lists for various languages.
    +  var FLOW_CONTROL_KEYWORDS =
    +      "break continue do else for if return while ";
    +  var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " +
    +      "double enum extern float goto int long register short signed sizeof " +
    +      "static struct switch typedef union unsigned void volatile ";
    +  var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " +
    +      "new operator private protected public this throw true try typeof ";
    +  var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " +
    +      "concept concept_map const_cast constexpr decltype " +
    +      "dynamic_cast explicit export friend inline late_check " +
    +      "mutable namespace nullptr reinterpret_cast static_assert static_cast " +
    +      "template typeid typename using virtual wchar_t where ";
    +  var JAVA_KEYWORDS = COMMON_KEYWORDS +
    +      "abstract boolean byte extends final finally implements import " +
    +      "instanceof null native package strictfp super synchronized throws " +
    +      "transient ";
    +  var CSHARP_KEYWORDS = JAVA_KEYWORDS +
    +      "as base by checked decimal delegate descending event " +
    +      "fixed foreach from group implicit in interface internal into is lock " +
    +      "object out override orderby params partial readonly ref sbyte sealed " +
    +      "stackalloc string select uint ulong unchecked unsafe ushort var ";
    +  var JSCRIPT_KEYWORDS = COMMON_KEYWORDS +
    +      "debugger eval export function get null set undefined var with " +
    +      "Infinity NaN ";
    +  var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " +
    +      "goto if import last local my next no our print package redo require " +
    +      "sub undef unless until use wantarray while BEGIN END ";
    +  var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " +
    +      "elif except exec finally from global import in is lambda " +
    +      "nonlocal not or pass print raise try with yield " +
    +      "False True None ";
    +  var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" +
    +      " defined elsif end ensure false in module next nil not or redo rescue " +
    +      "retry self super then true undef unless until when yield BEGIN END ";
    +  var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " +
    +      "function in local set then until ";
    +  var ALL_KEYWORDS = (
    +      CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS +
    +      PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS);
    +
    +  // token style names.  correspond to css classes
    +  /** token style for a string literal */
    +  var PR_STRING = 'str';
    +  /** token style for a keyword */
    +  var PR_KEYWORD = 'kwd';
    +  /** token style for a comment */
    +  var PR_COMMENT = 'com';
    +  /** token style for a type */
    +  var PR_TYPE = 'typ';
    +  /** token style for a literal value.  e.g. 1, null, true. */
    +  var PR_LITERAL = 'lit';
    +  /** token style for a punctuation string. */
    +  var PR_PUNCTUATION = 'pun';
    +  /** token style for a punctuation string. */
    +  var PR_PLAIN = 'pln';
    +
    +  /** token style for an sgml tag. */
    +  var PR_TAG = 'tag';
    +  /** token style for a markup declaration such as a DOCTYPE. */
    +  var PR_DECLARATION = 'dec';
    +  /** token style for embedded source. */
    +  var PR_SOURCE = 'src';
    +  /** token style for an sgml attribute name. */
    +  var PR_ATTRIB_NAME = 'atn';
    +  /** token style for an sgml attribute value. */
    +  var PR_ATTRIB_VALUE = 'atv';
    +
    +  /**
    +   * A class that indicates a section of markup that is not code, e.g. to allow
    +   * embedding of line numbers within code listings.
    +   */
    +  var PR_NOCODE = 'nocode';
    +
    +  /** A set of tokens that can precede a regular expression literal in
    +    * javascript.
    +    * http://www.mozilla.org/js/language/js20/rationale/syntax.html has the full
    +    * list, but I've removed ones that might be problematic when seen in
    +    * languages that don't support regular expression literals.
    +    *
    +    * <p>Specifically, I've removed any keywords that can't precede a regexp
    +    * literal in a syntactically legal javascript program, and I've removed the
    +    * "in" keyword since it's not a keyword in many languages, and might be used
    +    * as a count of inches.
    +    *
    +    * <p>The link a above does not accurately describe EcmaScript rules since
    +    * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
    +    * very well in practice.
    +    *
    +    * @private
    +    */
    +  var REGEXP_PRECEDER_PATTERN = function () {
    +      var preceders = [
    +          "!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=",
    +          "&=", "(", "*", "*=", /* "+", */ "+=", ",", /* "-", */ "-=",
    +          "->", /*".", "..", "...", handled below */ "/", "/=", ":", "::", ";",
    +          "<", "<<", "<<=", "<=", "=", "==", "===", ">",
    +          ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[",
    +          "^", "^=", "^^", "^^=", "{", "|", "|=", "||",
    +          "||=", "~" /* handles =~ and !~ */,
    +          "break", "case", "continue", "delete",
    +          "do", "else", "finally", "instanceof",
    +          "return", "throw", "try", "typeof"
    +          ];
    +      var pattern = '(?:^^|[+-]';
    +      for (var i = 0; i < preceders.length; ++i) {
    +        pattern += '|' + preceders[i].replace(/([^=<>:&a-z])/g, '\\$1');
    +      }
    +      pattern += ')\\s*';  // matches at end, and matches empty string
    +      return pattern;
    +      // CAVEAT: this does not properly handle the case where a regular
    +      // expression immediately follows another since a regular expression may
    +      // have flags for case-sensitivity and the like.  Having regexp tokens
    +      // adjacent is not valid in any language I'm aware of, so I'm punting.
    +      // TODO: maybe style special characters inside a regexp as punctuation.
    +    }();
    +
    +  // Define regexps here so that the interpreter doesn't have to create an
    +  // object each time the function containing them is called.
    +  // The language spec requires a new object created even if you don't access
    +  // the $1 members.
    +  var pr_amp = /&/g;
    +  var pr_lt = /</g;
    +  var pr_gt = />/g;
    +  var pr_quot = /\"/g;
    +  /** like textToHtml but escapes double quotes to be attribute safe. */
    +  function attribToHtml(str) {
    +    return str.replace(pr_amp, '&amp;')
    +        .replace(pr_lt, '&lt;')
    +        .replace(pr_gt, '&gt;')
    +        .replace(pr_quot, '&quot;');
    +  }
    +
    +  /** escapest html special characters to html. */
    +  function textToHtml(str) {
    +    return str.replace(pr_amp, '&amp;')
    +        .replace(pr_lt, '&lt;')
    +        .replace(pr_gt, '&gt;');
    +  }
    +
    +
    +  var pr_ltEnt = /&lt;/g;
    +  var pr_gtEnt = /&gt;/g;
    +  var pr_aposEnt = /&apos;/g;
    +  var pr_quotEnt = /&quot;/g;
    +  var pr_ampEnt = /&amp;/g;
    +  var pr_nbspEnt = /&nbsp;/g;
    +  /** unescapes html to plain text. */
    +  function htmlToText(html) {
    +    var pos = html.indexOf('&');
    +    if (pos < 0) { return html; }
    +    // Handle numeric entities specially.  We can't use functional substitution
    +    // since that doesn't work in older versions of Safari.
    +    // These should be rare since most browsers convert them to normal chars.
    +    for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0;) {
    +      var end = html.indexOf(';', pos);
    +      if (end >= 0) {
    +        var num = html.substring(pos + 3, end);
    +        var radix = 10;
    +        if (num && num.charAt(0) === 'x') {
    +          num = num.substring(1);
    +          radix = 16;
    +        }
    +        var codePoint = parseInt(num, radix);
    +        if (!isNaN(codePoint)) {
    +          html = (html.substring(0, pos) + String.fromCharCode(codePoint) +
    +                  html.substring(end + 1));
    +        }
    +      }
    +    }
    +
    +    return html.replace(pr_ltEnt, '<')
    +        .replace(pr_gtEnt, '>')
    +        .replace(pr_aposEnt, "'")
    +        .replace(pr_quotEnt, '"')
    +        .replace(pr_nbspEnt, ' ')
    +        .replace(pr_ampEnt, '&');
    +  }
    +
    +  /** is the given node's innerHTML normally unescaped? */
    +  function isRawContent(node) {
    +    return 'XMP' === node.tagName;
    +  }
    +
    +  var newlineRe = /[\r\n]/g;
    +  /**
    +   * Are newlines and adjacent spaces significant in the given node's innerHTML?
    +   */
    +  function isPreformatted(node, content) {
    +    // PRE means preformatted, and is a very common case, so don't create
    +    // unnecessary computed style objects.
    +    if ('PRE' === node.tagName) { return true; }
    +    if (!newlineRe.test(content)) { return true; }  // Don't care
    +    var whitespace = '';
    +    // For disconnected nodes, IE has no currentStyle.
    +    if (node.currentStyle) {
    +      whitespace = node.currentStyle.whiteSpace;
    +    } else if (window.getComputedStyle) {
    +      // Firefox makes a best guess if node is disconnected whereas Safari
    +      // returns the empty string.
    +      whitespace = window.getComputedStyle(node, null).whiteSpace;
    +    }
    +    return !whitespace || whitespace === 'pre';
    +  }
    +
    +  function normalizedHtml(node, out) {
    +    switch (node.nodeType) {
    +      case 1:  // an element
    +        var name = node.tagName.toLowerCase();
    +        out.push('<', name);
    +        for (var i = 0; i < node.attributes.length; ++i) {
    +          var attr = node.attributes[i];
    +          if (!attr.specified) { continue; }
    +          out.push(' ');
    +          normalizedHtml(attr, out);
    +        }
    +        out.push('>');
    +        for (var child = node.firstChild; child; child = child.nextSibling) {
    +          normalizedHtml(child, out);
    +        }
    +        if (node.firstChild || !/^(?:br|link|img)$/.test(name)) {
    +          out.push('<\/', name, '>');
    +        }
    +        break;
    +      case 2: // an attribute
    +        out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"');
    +        break;
    +      case 3: case 4: // text
    +        out.push(textToHtml(node.nodeValue));
    +        break;
    +    }
    +  }
    +
    +  /**
    +   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
    +   * matches the union o the sets o strings matched d by the input RegExp.
    +   * Since it matches globally, if the input strings have a start-of-input
    +   * anchor (/^.../), it is ignored for the purposes of unioning.
    +   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
    +   * @return {RegExp} a global regex.
    +   */
    +  function combinePrefixPatterns(regexs) {
    +    var capturedGroupIndex = 0;
    +
    +    var needToFoldCase = false;
    +    var ignoreCase = false;
    +    for (var i = 0, n = regexs.length; i < n; ++i) {
    +      var regex = regexs[i];
    +      if (regex.ignoreCase) {
    +        ignoreCase = true;
    +      } else if (/[a-z]/i.test(regex.source.replace(
    +                     /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
    +        needToFoldCase = true;
    +        ignoreCase = false;
    +        break;
    +      }
    +    }
    +
    +    function decodeEscape(charsetPart) {
    +      if (charsetPart.charAt(0) !== '\\') { return charsetPart.charCodeAt(0); }
    +      switch (charsetPart.charAt(1)) {
    +        case 'b': return 8;
    +        case 't': return 9;
    +        case 'n': return 0xa;
    +        case 'v': return 0xb;
    +        case 'f': return 0xc;
    +        case 'r': return 0xd;
    +        case 'u': case 'x':
    +          return parseInt(charsetPart.substring(2), 16)
    +              || charsetPart.charCodeAt(1);
    +        case '0': case '1': case '2': case '3': case '4':
    +        case '5': case '6': case '7':
    +          return parseInt(charsetPart.substring(1), 8);
    +        default: return charsetPart.charCodeAt(1);
    +      }
    +    }
    +
    +    function encodeEscape(charCode) {
    +      if (charCode < 0x20) {
    +        return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
    +      }
    +      var ch = String.fromCharCode(charCode);
    +      if (ch === '\\' || ch === '-' || ch === '[' || ch === ']') {
    +        ch = '\\' + ch;
    +      }
    +      return ch;
    +    }
    +
    +    function caseFoldCharset(charSet) {
    +      var charsetParts = charSet.substring(1, charSet.length - 1).match(
    +          new RegExp(
    +              '\\\\u[0-9A-Fa-f]{4}'
    +              + '|\\\\x[0-9A-Fa-f]{2}'
    +              + '|\\\\[0-3][0-7]{0,2}'
    +              + '|\\\\[0-7]{1,2}'
    +              + '|\\\\[\\s\\S]'
    +              + '|-'
    +              + '|[^-\\\\]',
    +              'g'));
    +      var groups = [];
    +      var ranges = [];
    +      var inverse = charsetParts[0] === '^';
    +      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
    +        var p = charsetParts[i];
    +        switch (p) {
    +          case '\\B': case '\\b':
    +          case '\\D': case '\\d':
    +          case '\\S': case '\\s':
    +          case '\\W': case '\\w':
    +            groups.push(p);
    +            continue;
    +        }
    +        var start = decodeEscape(p);
    +        var end;
    +        if (i + 2 < n && '-' === charsetParts[i + 1]) {
    +          end = decodeEscape(charsetParts[i + 2]);
    +          i += 2;
    +        } else {
    +          end = start;
    +        }
    +        ranges.push([start, end]);
    +        // If the range might intersect letters, then expand it.
    +        if (!(end < 65 || start > 122)) {
    +          if (!(end < 65 || start > 90)) {
    +            ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
    +          }
    +          if (!(end < 97 || start > 122)) {
    +            ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
    +          }
    +        }
    +      }
    +
    +      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
    +      // -> [[1, 12], [14, 14], [16, 17]]
    +      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });
    +      var consolidatedRanges = [];
    +      var lastRange = [NaN, NaN];
    +      for (var i = 0; i < ranges.length; ++i) {
    +        var range = ranges[i];
    +        if (range[0] <= lastRange[1] + 1) {
    +          lastRange[1] = Math.max(lastRange[1], range[1]);
    +        } else {
    +          consolidatedRanges.push(lastRange = range);
    +        }
    +      }
    +
    +      var out = ['['];
    +      if (inverse) { out.push('^'); }
    +      out.push.apply(out, groups);
    +      for (var i = 0; i < consolidatedRanges.length; ++i) {
    +        var range = consolidatedRanges[i];
    +        out.push(encodeEscape(range[0]));
    +        if (range[1] > range[0]) {
    +          if (range[1] + 1 > range[0]) { out.push('-'); }
    +          out.push(encodeEscape(range[1]));
    +        }
    +      }
    +      out.push(']');
    +      return out.join('');
    +    }
    +
    +    function allowAnywhereFoldCaseAndRenumberGroups(regex) {
    +      // Split into character sets, escape sequences, punctuation strings
    +      // like ('(', '(?:', ')', '^'), and runs of characters that do not
    +      // include any of the above.
    +      var parts = regex.source.match(
    +          new RegExp(
    +              '(?:'
    +              + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]'  // a character set
    +              + '|\\\\u[A-Fa-f0-9]{4}'  // a unicode escape
    +              + '|\\\\x[A-Fa-f0-9]{2}'  // a hex escape
    +              + '|\\\\[0-9]+'  // a back-reference or octal escape
    +              + '|\\\\[^ux0-9]'  // other escape sequence
    +              + '|\\(\\?[:!=]'  // start of a non-capturing group
    +              + '|[\\(\\)\\^]'  // start/emd of a group, or line start
    +              + '|[^\\x5B\\x5C\\(\\)\\^]+'  // run of other characters
    +              + ')',
    +              'g'));
    +      var n = parts.length;
    +
    +      // Maps captured group numbers to the number they will occupy in
    +      // the output or to -1 if that has not been determined, or to
    +      // undefined if they need not be capturing in the output.
    +      var capturedGroups = [];
    +
    +      // Walk over and identify back references to build the capturedGroups
    +      // mapping.
    +      for (var i = 0, groupIndex = 0; i < n; ++i) {
    +        var p = parts[i];
    +        if (p === '(') {
    +          // groups are 1-indexed, so max group index is count of '('
    +          ++groupIndex;
    +        } else if ('\\' === p.charAt(0)) {
    +          var decimalValue = +p.substring(1);
    +          if (decimalValue && decimalValue <= groupIndex) {
    +            capturedGroups[decimalValue] = -1;
    +          }
    +        }
    +      }
    +
    +      // Renumber groups and reduce capturing groups to non-capturing groups
    +      // where possible.
    +      for (var i = 1; i < capturedGroups.length; ++i) {
    +        if (-1 === capturedGroups[i]) {
    +          capturedGroups[i] = ++capturedGroupIndex;
    +        }
    +      }
    +      for (var i = 0, groupIndex = 0; i < n; ++i) {
    +        var p = parts[i];
    +        if (p === '(') {
    +          ++groupIndex;
    +          if (capturedGroups[groupIndex] === undefined) {
    +            parts[i] = '(?:';
    +          }
    +        } else if ('\\' === p.charAt(0)) {
    +          var decimalValue = +p.substring(1);
    +          if (decimalValue && decimalValue <= groupIndex) {
    +            parts[i] = '\\' + capturedGroups[groupIndex];
    +          }
    +        }
    +      }
    +
    +      // Remove any prefix anchors so that the output will match anywhere.
    +      // ^^ really does mean an anchored match though.
    +      for (var i = 0, groupIndex = 0; i < n; ++i) {
    +        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
    +      }
    +
    +      // Expand letters to groupts to handle mixing of case-sensitive and
    +      // case-insensitive patterns if necessary.
    +      if (regex.ignoreCase && needToFoldCase) {
    +        for (var i = 0; i < n; ++i) {
    +          var p = parts[i];
    +          var ch0 = p.charAt(0);
    +          if (p.length >= 2 && ch0 === '[') {
    +            parts[i] = caseFoldCharset(p);
    +          } else if (ch0 !== '\\') {
    +            // TODO: handle letters in numeric escapes.
    +            parts[i] = p.replace(
    +                /[a-zA-Z]/g,
    +                function (ch) {
    +                  var cc = ch.charCodeAt(0);
    +                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
    +                });
    +          }
    +        }
    +      }
    +
    +      return parts.join('');
    +    }
    +
    +    var rewritten = [];
    +    for (var i = 0, n = regexs.length; i < n; ++i) {
    +      var regex = regexs[i];
    +      if (regex.global || regex.multiline) { throw new Error('' + regex); }
    +      rewritten.push(
    +          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
    +    }
    +
    +    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
    +  }
    +
    +  var PR_innerHtmlWorks = null;
    +  function getInnerHtml(node) {
    +    // inner html is hopelessly broken in Safari 2.0.4 when the content is
    +    // an html description of well formed XML and the containing tag is a PRE
    +    // tag, so we detect that case and emulate innerHTML.
    +    if (null === PR_innerHtmlWorks) {
    +      var testNode = document.createElement('PRE');
    +      testNode.appendChild(
    +          document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />'));
    +      PR_innerHtmlWorks = !/</.test(testNode.innerHTML);
    +    }
    +
    +    if (PR_innerHtmlWorks) {
    +      var content = node.innerHTML;
    +      // XMP tags contain unescaped entities so require special handling.
    +      if (isRawContent(node)) {
    +        content = textToHtml(content);
    +      } else if (!isPreformatted(node, content)) {
    +        content = content.replace(/(<br\s*\/?>)[\r\n]+/g, '$1')
    +            .replace(/(?:[\r\n]+[ \t]*)+/g, ' ');
    +      }
    +      return content;
    +    }
    +
    +    var out = [];
    +    for (var child = node.firstChild; child; child = child.nextSibling) {
    +      normalizedHtml(child, out);
    +    }
    +    return out.join('');
    +  }
    +
    +  /** returns a function that expand tabs to spaces.  This function can be fed
    +    * successive chunks of text, and will maintain its own internal state to
    +    * keep track of how tabs are expanded.
    +    * @return {function (string) : string} a function that takes
    +    *   plain text and return the text with tabs expanded.
    +    * @private
    +    */
    +  function makeTabExpander(tabWidth) {
    +    var SPACES = '                ';
    +    var charInLine = 0;
    +
    +    return function (plainText) {
    +      // walk over each character looking for tabs and newlines.
    +      // On tabs, expand them.  On newlines, reset charInLine.
    +      // Otherwise increment charInLine
    +      var out = null;
    +      var pos = 0;
    +      for (var i = 0, n = plainText.length; i < n; ++i) {
    +        var ch = plainText.charAt(i);
    +
    +        switch (ch) {
    +          case '\t':
    +            if (!out) { out = []; }
    +            out.push(plainText.substring(pos, i));
    +            // calculate how much space we need in front of this part
    +            // nSpaces is the amount of padding -- the number of spaces needed
    +            // to move us to the next column, where columns occur at factors of
    +            // tabWidth.
    +            var nSpaces = tabWidth - (charInLine % tabWidth);
    +            charInLine += nSpaces;
    +            for (; nSpaces >= 0; nSpaces -= SPACES.length) {
    +              out.push(SPACES.substring(0, nSpaces));
    +            }
    +            pos = i + 1;
    +            break;
    +          case '\n':
    +            charInLine = 0;
    +            break;
    +          default:
    +            ++charInLine;
    +        }
    +      }
    +      if (!out) { return plainText; }
    +      out.push(plainText.substring(pos));
    +      return out.join('');
    +    };
    +  }
    +
    +  var pr_chunkPattern = new RegExp(
    +      '[^<]+'  // A run of characters other than '<'
    +      + '|<\!--[\\s\\S]*?--\>'  // an HTML comment
    +      + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>'  // a CDATA section
    +      // a probable tag that should not be highlighted
    +      + '|<\/?[a-zA-Z](?:[^>\"\']|\'[^\']*\'|\"[^\"]*\")*>'
    +      + '|<',  // A '<' that does not begin a larger chunk
    +      'g');
    +  var pr_commentPrefix = /^<\!--/;
    +  var pr_cdataPrefix = /^<!\[CDATA\[/;
    +  var pr_brPrefix = /^<br\b/i;
    +  var pr_tagNameRe = /^<(\/?)([a-zA-Z][a-zA-Z0-9]*)/;
    +
    +  /** split markup into chunks of html tags (style null) and
    +    * plain text (style {@link #PR_PLAIN}), converting tags which are
    +    * significant for tokenization (<br>) into their textual equivalent.
    +    *
    +    * @param {string} s html where whitespace is considered significant.
    +    * @return {Object} source code and extracted tags.
    +    * @private
    +    */
    +  function extractTags(s) {
    +    // since the pattern has the 'g' modifier and defines no capturing groups,
    +    // this will return a list of all chunks which we then classify and wrap as
    +    // PR_Tokens
    +    var matches = s.match(pr_chunkPattern);
    +    var sourceBuf = [];
    +    var sourceBufLen = 0;
    +    var extractedTags = [];
    +    if (matches) {
    +      for (var i = 0, n = matches.length; i < n; ++i) {
    +        var match = matches[i];
    +        if (match.length > 1 && match.charAt(0) === '<') {
    +          if (pr_commentPrefix.test(match)) { continue; }
    +          if (pr_cdataPrefix.test(match)) {
    +            // strip CDATA prefix and suffix.  Don't unescape since it's CDATA
    +            sourceBuf.push(match.substring(9, match.length - 3));
    +            sourceBufLen += match.length - 12;
    +          } else if (pr_brPrefix.test(match)) {
    +            // <br> tags are lexically significant so convert them to text.
    +            // This is undone later.
    +            sourceBuf.push('\n');
    +            ++sourceBufLen;
    +          } else {
    +            if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) {
    +              // A <span class="nocode"> will start a section that should be
    +              // ignored.  Continue walking the list until we see a matching end
    +              // tag.
    +              var name = match.match(pr_tagNameRe)[2];
    +              var depth = 1;
    +              var j;
    +              end_tag_loop:
    +              for (j = i + 1; j < n; ++j) {
    +                var name2 = matches[j].match(pr_tagNameRe);
    +                if (name2 && name2[2] === name) {
    +                  if (name2[1] === '/') {
    +                    if (--depth === 0) { break end_tag_loop; }
    +                  } else {
    +                    ++depth;
    +                  }
    +                }
    +              }
    +              if (j < n) {
    +                extractedTags.push(
    +                    sourceBufLen, matches.slice(i, j + 1).join(''));
    +                i = j;
    +              } else {  // Ignore unclosed sections.
    +                extractedTags.push(sourceBufLen, match);
    +              }
    +            } else {
    +              extractedTags.push(sourceBufLen, match);
    +            }
    +          }
    +        } else {
    +          var literalText = htmlToText(match);
    +          sourceBuf.push(literalText);
    +          sourceBufLen += literalText.length;
    +        }
    +      }
    +    }
    +    return { source: sourceBuf.join(''), tags: extractedTags };
    +  }
    +
    +  /** True if the given tag contains a class attribute with the nocode class. */
    +  function isNoCodeTag(tag) {
    +    return !!tag
    +        // First canonicalize the representation of attributes
    +        .replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,
    +                 ' $1="$2$3$4"')
    +        // Then look for the attribute we want.
    +        .match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/);
    +  }
    +
    +  /**
    +   * Apply the given language handler to sourceCode and add the resulting
    +   * decorations to out.
    +   * @param {number} basePos the index of sourceCode within the chunk of source
    +   *    whose decorations are already present on out.
    +   */
    +  function appendDecorations(basePos, sourceCode, langHandler, out) {
    +    if (!sourceCode) { return; }
    +    var job = {
    +      source: sourceCode,
    +      basePos: basePos
    +    };
    +    langHandler(job);
    +    out.push.apply(out, job.decorations);
    +  }
    +
    +  /** Given triples of [style, pattern, context] returns a lexing function,
    +    * The lexing function interprets the patterns to find token boundaries and
    +    * returns a decoration list of the form
    +    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
    +    * where index_n is an index into the sourceCode, and style_n is a style
    +    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
    +    * all characters in sourceCode[index_n-1:index_n].
    +    *
    +    * The stylePatterns is a list whose elements have the form
    +    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
    +    *
    +    * Style is a style constant like PR_PLAIN, or can be a string of the
    +    * form 'lang-FOO', where FOO is a language extension describing the
    +    * language of the portion of the token in $1 after pattern executes.
    +    * E.g., if style is 'lang-lisp', and group 1 contains the text
    +    * '(hello (world))', then that portion of the token will be passed to the
    +    * registered lisp handler for formatting.
    +    * The text before and after group 1 will be restyled using this decorator
    +    * so decorators should take care that this doesn't result in infinite
    +    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
    +    * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
    +    * '<script>foo()<\/script>', which would cause the current decorator to
    +    * be called with '<script>' which would not match the same rule since
    +    * group 1 must not be empty, so it would be instead styled as PR_TAG by
    +    * the generic tag rule.  The handler registered for the 'js' extension would
    +    * then be called with 'foo()', and finally, the current decorator would
    +    * be called with '<\/script>' which would not match the original rule and
    +    * so the generic tag rule would identify it as a tag.
    +    *
    +    * Pattern must only match prefixes, and if it matches a prefix, then that
    +    * match is considered a token with the same style.
    +    *
    +    * Context is applied to the last non-whitespace, non-comment token
    +    * recognized.
    +    *
    +    * Shortcut is an optional string of characters, any of which, if the first
    +    * character, gurantee that this pattern and only this pattern matches.
    +    *
    +    * @param {Array} shortcutStylePatterns patterns that always start with
    +    *   a known character.  Must have a shortcut string.
    +    * @param {Array} fallthroughStylePatterns patterns that will be tried in
    +    *   order if the shortcut ones fail.  May have shortcuts.
    +    *
    +    * @return {function (Object)} a
    +    *   function that takes source code and returns a list of decorations.
    +    */
    +  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
    +    var shortcuts = {};
    +    var tokenizer;
    +    (function () {
    +      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
    +      var allRegexs = [];
    +      var regexKeys = {};
    +      for (var i = 0, n = allPatterns.length; i < n; ++i) {
    +        var patternParts = allPatterns[i];
    +        var shortcutChars = patternParts[3];
    +        if (shortcutChars) {
    +          for (var c = shortcutChars.length; --c >= 0;) {
    +            shortcuts[shortcutChars.charAt(c)] = patternParts;
    +          }
    +        }
    +        var regex = patternParts[1];
    +        var k = '' + regex;
    +        if (!regexKeys.hasOwnProperty(k)) {
    +          allRegexs.push(regex);
    +          regexKeys[k] = null;
    +        }
    +      }
    +      allRegexs.push(/[\0-\uffff]/);
    +      tokenizer = combinePrefixPatterns(allRegexs);
    +    })();
    +
    +    var nPatterns = fallthroughStylePatterns.length;
    +    var notWs = /\S/;
    +
    +    /**
    +     * Lexes job.source and produces an output array job.decorations of style
    +     * classes preceded by the position at which they start in job.source in
    +     * order.
    +     *
    +     * @param {Object} job an object like {@code
    +     *    source: {string} sourceText plain text,
    +     *    basePos: {int} position of job.source in the larger chunk of
    +     *        sourceCode.
    +     * }
    +     */
    +    var decorate = function (job) {
    +      var sourceCode = job.source, basePos = job.basePos;
    +      /** Even entries are positions in source in ascending order.  Odd enties
    +        * are style markers (e.g., PR_COMMENT) that run from that position until
    +        * the end.
    +        * @type {Array.<number|string>}
    +        */
    +      var decorations = [basePos, PR_PLAIN];
    +      var pos = 0;  // index into sourceCode
    +      var tokens = sourceCode.match(tokenizer) || [];
    +      var styleCache = {};
    +
    +      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
    +        var token = tokens[ti];
    +        var style = styleCache[token];
    +        var match = void 0;
    +
    +        var isEmbedded;
    +        if (typeof style === 'string') {
    +          isEmbedded = false;
    +        } else {
    +          var patternParts = shortcuts[token.charAt(0)];
    +          if (patternParts) {
    +            match = token.match(patternParts[1]);
    +            style = patternParts[0];
    +          } else {
    +            for (var i = 0; i < nPatterns; ++i) {
    +              patternParts = fallthroughStylePatterns[i];
    +              match = token.match(patternParts[1]);
    +              if (match) {
    +                style = patternParts[0];
    +                break;
    +              }
    +            }
    +
    +            if (!match) {  // make sure that we make progress
    +              style = PR_PLAIN;
    +            }
    +          }
    +
    +          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
    +          if (isEmbedded && !(match && typeof match[1] === 'string')) {
    +            isEmbedded = false;
    +            style = PR_SOURCE;
    +          }
    +
    +          if (!isEmbedded) { styleCache[token] = style; }
    +        }
    +
    +        var tokenStart = pos;
    +        pos += token.length;
    +
    +        if (!isEmbedded) {
    +          decorations.push(basePos + tokenStart, style);
    +        } else {  // Treat group 1 as an embedded block of source code.
    +          var embeddedSource = match[1];
    +          var embeddedSourceStart = token.indexOf(embeddedSource);
    +          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
    +          if (match[2]) {
    +            // If embeddedSource can be blank, then it would match at the
    +            // beginning which would cause us to infinitely recurse on the
    +            // entire token, so we catch the right context in match[2].
    +            embeddedSourceEnd = token.length - match[2].length;
    +            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
    +          }
    +          var lang = style.substring(5);
    +          // Decorate the left of the embedded source
    +          appendDecorations(
    +              basePos + tokenStart,
    +              token.substring(0, embeddedSourceStart),
    +              decorate, decorations);
    +          // Decorate the embedded source
    +          appendDecorations(
    +              basePos + tokenStart + embeddedSourceStart,
    +              embeddedSource,
    +              langHandlerForExtension(lang, embeddedSource),
    +              decorations);
    +          // Decorate the right of the embedded section
    +          appendDecorations(
    +              basePos + tokenStart + embeddedSourceEnd,
    +              token.substring(embeddedSourceEnd),
    +              decorate, decorations);
    +        }
    +      }
    +      job.decorations = decorations;
    +    };
    +    return decorate;
    +  }
    +
    +  /** returns a function that produces a list of decorations from source text.
    +    *
    +    * This code treats ", ', and ` as string delimiters, and \ as a string
    +    * escape.  It does not recognize perl's qq() style strings.
    +    * It has no special handling for double delimiter escapes as in basic, or
    +    * the tripled delimiters used in python, but should work on those regardless
    +    * although in those cases a single string literal may be broken up into
    +    * multiple adjacent string literals.
    +    *
    +    * It recognizes C, C++, and shell style comments.
    +    *
    +    * @param {Object} options a set of optional parameters.
    +    * @return {function (Object)} a function that examines the source code
    +    *     in the input job and builds the decoration list.
    +    */
    +  function sourceDecorator(options) {
    +    var shortcutStylePatterns = [], fallthroughStylePatterns = [];
    +    if (options['tripleQuotedStrings']) {
    +      // '''multi-line-string''', 'single-line-string', and double-quoted
    +      shortcutStylePatterns.push(
    +          [PR_STRING,  /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
    +           null, '\'"']);
    +    } else if (options['multiLineStrings']) {
    +      // 'multi-line-string', "multi-line-string"
    +      shortcutStylePatterns.push(
    +          [PR_STRING,  /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
    +           null, '\'"`']);
    +    } else {
    +      // 'single-line-string', "single-line-string"
    +      shortcutStylePatterns.push(
    +          [PR_STRING,
    +           /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
    +           null, '"\'']);
    +    }
    +    if (options['verbatimStrings']) {
    +      // verbatim-string-literal production from the C# grammar.  See issue 93.
    +      fallthroughStylePatterns.push(
    +          [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
    +    }
    +    if (options['hashComments']) {
    +      if (options['cStyleComments']) {
    +        // Stop C preprocessor declarations at an unclosed open comment
    +        shortcutStylePatterns.push(
    +            [PR_COMMENT, /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,
    +             null, '#']);
    +        fallthroughStylePatterns.push(
    +            [PR_STRING,
    +             /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
    +             null]);
    +      } else {
    +        shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
    +      }
    +    }
    +    if (options['cStyleComments']) {
    +      fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
    +      fallthroughStylePatterns.push(
    +          [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
    +    }
    +    if (options['regexLiterals']) {
    +      var REGEX_LITERAL = (
    +          // A regular expression literal starts with a slash that is
    +          // not followed by * or / so that it is not confused with
    +          // comments.
    +          '/(?=[^/*])'
    +          // and then contains any number of raw characters,
    +          + '(?:[^/\\x5B\\x5C]'
    +          // escape sequences (\x5C),
    +          +    '|\\x5C[\\s\\S]'
    +          // or non-nesting character sets (\x5B\x5D);
    +          +    '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
    +          // finally closed by a /.
    +          + '/');
    +      fallthroughStylePatterns.push(
    +          ['lang-regex',
    +           new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
    +           ]);
    +    }
    +
    +    var keywords = options['keywords'].replace(/^\s+|\s+$/g, '');
    +    if (keywords.length) {
    +      fallthroughStylePatterns.push(
    +          [PR_KEYWORD,
    +           new RegExp('^(?:' + keywords.replace(/\s+/g, '|') + ')\\b'), null]);
    +    }
    +
    +    shortcutStylePatterns.push([PR_PLAIN,       /^\s+/, null, ' \r\n\t\xA0']);
    +    fallthroughStylePatterns.push(
    +        // TODO(mikesamuel): recognize non-latin letters and numerals in idents
    +        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],
    +        [PR_TYPE,        /^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/, null],
    +        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],
    +        [PR_LITERAL,
    +         new RegExp(
    +             '^(?:'
    +             // A hex number
    +             + '0x[a-f0-9]+'
    +             // or an octal or decimal number,
    +             + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
    +             // possibly in scientific notation
    +             + '(?:e[+\\-]?\\d+)?'
    +             + ')'
    +             // with an optional modifier like UL for unsigned long
    +             + '[a-z]*', 'i'),
    +         null, '0123456789'],
    +        [PR_PUNCTUATION, /^.[^\s\w\.$@\'\"\`\/\#]*/, null]);
    +
    +    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
    +  }
    +
    +  var decorateSource = sourceDecorator({
    +        'keywords': ALL_KEYWORDS,
    +        'hashComments': true,
    +        'cStyleComments': true,
    +        'multiLineStrings': true,
    +        'regexLiterals': true
    +      });
    +
    +  /** Breaks {@code job.source} around style boundaries in
    +    * {@code job.decorations} while re-interleaving {@code job.extractedTags},
    +    * and leaves the result in {@code job.prettyPrintedHtml}.
    +    * @param {Object} job like {
    +    *    source: {string} source as plain text,
    +    *    extractedTags: {Array.<number|string>} extractedTags chunks of raw
    +    *                   html preceded by their position in {@code job.source}
    +    *                   in order
    +    *    decorations: {Array.<number|string} an array of style classes preceded
    +    *                 by the position at which they start in job.source in order
    +    * }
    +    * @private
    +    */
    +  function recombineTagsAndDecorations(job) {
    +    var sourceText = job.source;
    +    var extractedTags = job.extractedTags;
    +    var decorations = job.decorations;
    +
    +    var html = [];
    +    // index past the last char in sourceText written to html
    +    var outputIdx = 0;
    +
    +    var openDecoration = null;
    +    var currentDecoration = null;
    +    var tagPos = 0;  // index into extractedTags
    +    var decPos = 0;  // index into decorations
    +    var tabExpander = makeTabExpander(window['PR_TAB_WIDTH']);
    +
    +    var adjacentSpaceRe = /([\r\n ]) /g;
    +    var startOrSpaceRe = /(^| ) /gm;
    +    var newlineRe = /\r\n?|\n/g;
    +    var trailingSpaceRe = /[ \r\n]$/;
    +    var lastWasSpace = true;  // the last text chunk emitted ended with a space.
    +
    +    // A helper function that is responsible for opening sections of decoration
    +    // and outputing properly escaped chunks of source
    +    function emitTextUpTo(sourceIdx) {
    +      if (sourceIdx > outputIdx) {
    +        if (openDecoration && openDecoration !== currentDecoration) {
    +          // Close the current decoration
    +          html.push('</span>');
    +          openDecoration = null;
    +        }
    +        if (!openDecoration && currentDecoration) {
    +          openDecoration = currentDecoration;
    +          html.push('<span class="', openDecoration, '">');
    +        }
    +        // This interacts badly with some wikis which introduces paragraph tags
    +        // into pre blocks for some strange reason.
    +        // It's necessary for IE though which seems to lose the preformattedness
    +        // of <pre> tags when their innerHTML is assigned.
    +        // http://stud3.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
    +        // and it serves to undo the conversion of <br>s to newlines done in
    +        // chunkify.
    +        var htmlChunk = textToHtml(
    +            tabExpander(sourceText.substring(outputIdx, sourceIdx)))
    +            .replace(lastWasSpace
    +                     ? startOrSpaceRe
    +                     : adjacentSpaceRe, '$1&nbsp;');
    +        // Keep track of whether we need to escape space at the beginning of the
    +        // next chunk.
    +        lastWasSpace = trailingSpaceRe.test(htmlChunk);
    +        // IE collapses multiple adjacient <br>s into 1 line break.
    +        // Prefix every <br> with '&nbsp;' can prevent such IE's behavior.
    +        var lineBreakHtml = window['_pr_isIE6']() ? '&nbsp;<br />' : '<br />';
    +        html.push(htmlChunk.replace(newlineRe, lineBreakHtml));
    +        outputIdx = sourceIdx;
    +      }
    +    }
    +
    +    while (true) {
    +      // Determine if we're going to consume a tag this time around.  Otherwise
    +      // we consume a decoration or exit.
    +      var outputTag;
    +      if (tagPos < extractedTags.length) {
    +        if (decPos < decorations.length) {
    +          // Pick one giving preference to extractedTags since we shouldn't open
    +          // a new style that we're going to have to immediately close in order
    +          // to output a tag.
    +          outputTag = extractedTags[tagPos] <= decorations[decPos];
    +        } else {
    +          outputTag = true;
    +        }
    +      } else {
    +        outputTag = false;
    +      }
    +      // Consume either a decoration or a tag or exit.
    +      if (outputTag) {
    +        emitTextUpTo(extractedTags[tagPos]);
    +        if (openDecoration) {
    +          // Close the current decoration
    +          html.push('</span>');
    +          openDecoration = null;
    +        }
    +        html.push(extractedTags[tagPos + 1]);
    +        tagPos += 2;
    +      } else if (decPos < decorations.length) {
    +        emitTextUpTo(decorations[decPos]);
    +        currentDecoration = decorations[decPos + 1];
    +        decPos += 2;
    +      } else {
    +        break;
    +      }
    +    }
    +    emitTextUpTo(sourceText.length);
    +    if (openDecoration) {
    +      html.push('</span>');
    +    }
    +    job.prettyPrintedHtml = html.join('');
    +  }
    +
    +  /** Maps language-specific file extensions to handlers. */
    +  var langHandlerRegistry = {};
    +  /** Register a language handler for the given file extensions.
    +    * @param {function (Object)} handler a function from source code to a list
    +    *      of decorations.  Takes a single argument job which describes the
    +    *      state of the computation.   The single parameter has the form
    +    *      {@code {
    +    *        source: {string} as plain text.
    +    *        decorations: {Array.<number|string>} an array of style classes
    +    *                     preceded by the position at which they start in
    +    *                     job.source in order.
    +    *                     The language handler should assigned this field.
    +    *        basePos: {int} the position of source in the larger source chunk.
    +    *                 All positions in the output decorations array are relative
    +    *                 to the larger source chunk.
    +    *      } }
    +    * @param {Array.<string>} fileExtensions
    +    */
    +  function registerLangHandler(handler, fileExtensions) {
    +    for (var i = fileExtensions.length; --i >= 0;) {
    +      var ext = fileExtensions[i];
    +      if (!langHandlerRegistry.hasOwnProperty(ext)) {
    +        langHandlerRegistry[ext] = handler;
    +      } else if ('console' in window) {
    +        console.warn('cannot override language handler %s', ext);
    +      }
    +    }
    +  }
    +  function langHandlerForExtension(extension, source) {
    +    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
    +      // Treat it as markup if the first non whitespace character is a < and
    +      // the last non-whitespace character is a >.
    +      extension = /^\s*</.test(source)
    +          ? 'default-markup'
    +          : 'default-code';
    +    }
    +    return langHandlerRegistry[extension];
    +  }
    +  registerLangHandler(decorateSource, ['default-code']);
    +  registerLangHandler(
    +      createSimpleLexer(
    +          [],
    +          [
    +           [PR_PLAIN,       /^[^<?]+/],
    +           [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
    +           [PR_COMMENT,     /^<\!--[\s\S]*?(?:-\->|$)/],
    +           // Unescaped content in an unknown language
    +           ['lang-',        /^<\?([\s\S]+?)(?:\?>|$)/],
    +           ['lang-',        /^<%([\s\S]+?)(?:%>|$)/],
    +           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
    +           ['lang-',        /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
    +           // Unescaped content in javascript.  (Or possibly vbscript).
    +           ['lang-js',      /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
    +           // Contains unescaped stylesheet content
    +           ['lang-css',     /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
    +           ['lang-in.tag',  /^(<\/?[a-z][^<>]*>)/i]
    +          ]),
    +      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
    +  registerLangHandler(
    +      createSimpleLexer(
    +          [
    +           [PR_PLAIN,        /^[\s]+/, null, ' \t\r\n'],
    +           [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
    +           ],
    +          [
    +           [PR_TAG,          /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
    +           [PR_ATTRIB_NAME,  /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
    +           ['lang-uq.val',   /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
    +           [PR_PUNCTUATION,  /^[=<>\/]+/],
    +           ['lang-js',       /^on\w+\s*=\s*\"([^\"]+)\"/i],
    +           ['lang-js',       /^on\w+\s*=\s*\'([^\']+)\'/i],
    +           ['lang-js',       /^on\w+\s*=\s*([^\"\'>\s]+)/i],
    +           ['lang-css',      /^style\s*=\s*\"([^\"]+)\"/i],
    +           ['lang-css',      /^style\s*=\s*\'([^\']+)\'/i],
    +           ['lang-css',      /^style\s*=\s*([^\"\'>\s]+)/i]
    +           ]),
    +      ['in.tag']);
    +  registerLangHandler(
    +      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': CPP_KEYWORDS,
    +          'hashComments': true,
    +          'cStyleComments': true
    +        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': 'null true false'
    +        }), ['json']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': CSHARP_KEYWORDS,
    +          'hashComments': true,
    +          'cStyleComments': true,
    +          'verbatimStrings': true
    +        }), ['cs']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': JAVA_KEYWORDS,
    +          'cStyleComments': true
    +        }), ['java']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': SH_KEYWORDS,
    +          'hashComments': true,
    +          'multiLineStrings': true
    +        }), ['bsh', 'csh', 'sh']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': PYTHON_KEYWORDS,
    +          'hashComments': true,
    +          'multiLineStrings': true,
    +          'tripleQuotedStrings': true
    +        }), ['cv', 'py']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': PERL_KEYWORDS,
    +          'hashComments': true,
    +          'multiLineStrings': true,
    +          'regexLiterals': true
    +        }), ['perl', 'pl', 'pm']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': RUBY_KEYWORDS,
    +          'hashComments': true,
    +          'multiLineStrings': true,
    +          'regexLiterals': true
    +        }), ['rb']);
    +  registerLangHandler(sourceDecorator({
    +          'keywords': JSCRIPT_KEYWORDS,
    +          'cStyleComments': true,
    +          'regexLiterals': true
    +        }), ['js']);
    +  registerLangHandler(
    +      createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
    +
    +  function applyDecorator(job) {
    +    var sourceCodeHtml = job.sourceCodeHtml;
    +    var opt_langExtension = job.langExtension;
    +
    +    // Prepopulate output in case processing fails with an exception.
    +    job.prettyPrintedHtml = sourceCodeHtml;
    +
    +    try {
    +      // Extract tags, and convert the source code to plain text.
    +      var sourceAndExtractedTags = extractTags(sourceCodeHtml);
    +      /** Plain text. @type {string} */
    +      var source = sourceAndExtractedTags.source;
    +      job.source = source;
    +      job.basePos = 0;
    +
    +      /** Even entries are positions in source in ascending order.  Odd entries
    +        * are tags that were extracted at that position.
    +        * @type {Array.<number|string>}
    +        */
    +      job.extractedTags = sourceAndExtractedTags.tags;
    +
    +      // Apply the appropriate language handler
    +      langHandlerForExtension(opt_langExtension, source)(job);
    +      // Integrate the decorations and tags back into the source code to produce
    +      // a decorated html string which is left in job.prettyPrintedHtml.
    +      recombineTagsAndDecorations(job);
    +    } catch (e) {
    +      if ('console' in window) {
    +        console.log(e);
    +        console.trace();
    +      }
    +    }
    +  }
    +
    +  function prettyPrintOne(sourceCodeHtml, opt_langExtension) {
    +    var job = {
    +      sourceCodeHtml: sourceCodeHtml,
    +      langExtension: opt_langExtension
    +    };
    +    applyDecorator(job);
    +    return job.prettyPrintedHtml;
    +  }
    +
    +  function prettyPrint(opt_whenDone) {
    +    var isIE678 = window['_pr_isIE6']();
    +    var ieNewline = isIE678 === 6 ? '\r\n' : '\r';
    +    // See bug 71 and http://stackoverflow.com/questions/136443/why-doesnt-ie7-
    +
    +    // fetch a list of nodes to rewrite
    +    var codeSegments = [
    +        document.getElementsByTagName('pre'),
    +        document.getElementsByTagName('code'),
    +        document.getElementsByTagName('td'),  /* ND Change: Add tables to support prototypes. */
    +        document.getElementsByTagName('xmp') ];
    +    var elements = [];
    +    for (var i = 0; i < codeSegments.length; ++i) {
    +      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
    +        elements.push(codeSegments[i][j]);
    +      }
    +    }
    +    codeSegments = null;
    +
    +    var clock = Date;
    +    if (!clock['now']) {
    +      clock = { 'now': function () { return (new Date).getTime(); } };
    +    }
    +
    +    // The loop is broken into a series of continuations to make sure that we
    +    // don't make the browser unresponsive when rewriting a large page.
    +    var k = 0;
    +    var prettyPrintingJob;
    +
    +    function doWork() {
    +      var endTime = (window['PR_SHOULD_USE_CONTINUATION'] ?
    +                     clock.now() + 250 /* ms */ :
    +                     Infinity);
    +      for (; k < elements.length && clock.now() < endTime; k++) {
    +        var cs = elements[k];
    +        if (cs.className && cs.className.indexOf('prettyprint') >= 0) {
    +          // If the classes includes a language extensions, use it.
    +          // Language extensions can be specified like
    +          //     <pre class="prettyprint lang-cpp">
    +          // the language extension "cpp" is used to find a language handler as
    +          // passed to PR_registerLangHandler.
    +          var langExtension = cs.className.match(/\blang-(\w+)\b/);
    +          if (langExtension) { langExtension = langExtension[1]; }
    +
    +          // make sure this is not nested in an already prettified element
    +          var nested = false;
    +          for (var p = cs.parentNode; p; p = p.parentNode) {
    +            if ((p.tagName === 'pre' || p.tagName === 'code' ||
    +                 p.tagName === 'xmp' || p.tagName === 'td') &&  /* ND Change: Add tables to support prototypes */
    +                p.className && p.className.indexOf('prettyprint') >= 0) {
    +              nested = true;
    +              break;
    +            }
    +          }
    +          if (!nested) {
    +            // fetch the content as a snippet of properly escaped HTML.
    +            // Firefox adds newlines at the end.
    +            var content = getInnerHtml(cs);
    +            content = content.replace(/(?:\r\n?|\n)$/, '');
    +
    +	  		/* ND Change: we need to preserve &nbsp;s so change them to a special character instead of a space. */
    +			content = content.replace(/&nbsp;/g, '\x11');
    +
    +            // do the pretty printing
    +            prettyPrintingJob = {
    +              sourceCodeHtml: content,
    +              langExtension: langExtension,
    +              sourceNode: cs
    +            };
    +            applyDecorator(prettyPrintingJob);
    +            replaceWithPrettyPrintedHtml();
    +          }
    +        }
    +      }
    +      if (k < elements.length) {
    +        // finish up in a continuation
    +        setTimeout(doWork, 250);
    +      } else if (opt_whenDone) {
    +        opt_whenDone();
    +      }
    +    }
    +
    +    function replaceWithPrettyPrintedHtml() {
    +      var newContent = prettyPrintingJob.prettyPrintedHtml;
    +      if (!newContent) { return; }
    +
    +      /* ND Change: Restore the preserved &nbsp;s.  */
    +	  newContent = newContent.replace(/\x11/g, '&nbsp;');
    +
    +      var cs = prettyPrintingJob.sourceNode;
    +
    +      // push the prettified html back into the tag.
    +      if (!isRawContent(cs)) {
    +        // just replace the old html with the new
    +        cs.innerHTML = newContent;
    +      } else {
    +        // we need to change the tag to a <pre> since <xmp>s do not allow
    +        // embedded tags such as the span tags used to attach styles to
    +        // sections of source code.
    +        var pre = document.createElement('PRE');
    +        for (var i = 0; i < cs.attributes.length; ++i) {
    +          var a = cs.attributes[i];
    +          if (a.specified) {
    +            var aname = a.name.toLowerCase();
    +            if (aname === 'class') {
    +              pre.className = a.value;  // For IE 6
    +            } else {
    +              pre.setAttribute(a.name, a.value);
    +            }
    +          }
    +        }
    +        pre.innerHTML = newContent;
    +
    +        // remove the old
    +        cs.parentNode.replaceChild(pre, cs);
    +        cs = pre;
    +      }
    +
    +      // Replace <br>s with line-feeds so that copying and pasting works
    +      // on IE 6.
    +      // Doing this on other browsers breaks lots of stuff since \r\n is
    +      // treated as two newlines on Firefox, and doing this also slows
    +      // down rendering.
    +      if (isIE678 && cs.tagName === 'PRE') {
    +        var lineBreaks = cs.getElementsByTagName('br');
    +        for (var j = lineBreaks.length; --j >= 0;) {
    +          var lineBreak = lineBreaks[j];
    +          lineBreak.parentNode.replaceChild(
    +              document.createTextNode(ieNewline), lineBreak);
    +        }
    +      }
    +    }
    +
    +    doWork();
    +  }
    +
    +  window['PR_normalizedHtml'] = normalizedHtml;
    +  window['prettyPrintOne'] = prettyPrintOne;
    +  window['prettyPrint'] = prettyPrint;
    +  window['PR'] = {
    +        'combinePrefixPatterns': combinePrefixPatterns,
    +        'createSimpleLexer': createSimpleLexer,
    +        'registerLangHandler': registerLangHandler,
    +        'sourceDecorator': sourceDecorator,
    +        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
    +        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
    +        'PR_COMMENT': PR_COMMENT,
    +        'PR_DECLARATION': PR_DECLARATION,
    +        'PR_KEYWORD': PR_KEYWORD,
    +        'PR_LITERAL': PR_LITERAL,
    +        'PR_NOCODE': PR_NOCODE,
    +        'PR_PLAIN': PR_PLAIN,
    +        'PR_PUNCTUATION': PR_PUNCTUATION,
    +        'PR_SOURCE': PR_SOURCE,
    +        'PR_STRING': PR_STRING,
    +        'PR_TAG': PR_TAG,
    +        'PR_TYPE': PR_TYPE
    +      };
    +})();
    +
    +
    +// ____________________________________________________________________________
    +
    +
    +
    +// Lua extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\r \xA0]+/,null,'	\n\r \xa0'],[PR.PR_STRING,/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/,null,'\"\'']],[[PR.PR_COMMENT,/^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/],[PR.PR_STRING,/^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/],[PR.PR_KEYWORD,/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],[PR.PR_LITERAL,/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],[PR.PR_PLAIN,/^[a-z_]\w*/i],[PR.PR_PUNCTUATION,/^[^\w\t\n\r \xA0][^\w\t\n\r \xA0\"\'\-\+=]*/]]),['lua'])
    +
    +
    +// Haskell extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\x0B\x0C\r ]+/,null,'	\n\r '],[PR.PR_STRING,/^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,null,'\"'],[PR.PR_STRING,/^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/,null,'\''],[PR.PR_LITERAL,/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,null,'0123456789']],[[PR.PR_COMMENT,/^(?:(?:--+(?:[^\r\n\x0C]*)?)|(?:\{-(?:[^-]|-+[^-\}])*-\}))/],[PR.PR_KEYWORD,/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^a-zA-Z0-9\']|$)/,null],[PR.PR_PLAIN,/^(?:[A-Z][\w\']*\.)*[a-zA-Z][\w\']*/],[PR.PR_PUNCTUATION,/^[^\t\n\x0B\x0C\r a-zA-Z0-9\'\"]+/]]),['hs'])
    +
    +
    +// ML extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\r \xA0]+/,null,'	\n\r \xa0'],[PR.PR_COMMENT,/^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i,null,'#'],[PR.PR_STRING,/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/,null,'\"\'']],[[PR.PR_COMMENT,/^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/],[PR.PR_KEYWORD,/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],[PR.PR_LITERAL,/^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],[PR.PR_PLAIN,/^(?:[a-z_]\w*[!?#]?|``[^\r\n\t`]*(?:``|$))/i],[PR.PR_PUNCTUATION,/^[^\t\n\r \xA0\"\'\w]+/]]),['fs','ml'])
    +
    +
    +// SQL extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\r \xA0]+/,null,'	\n\r \xa0'],[PR.PR_STRING,/^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/,null,'\"\'']],[[PR.PR_COMMENT,/^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/],[PR.PR_KEYWORD,/^(?:ADD|ALL|ALTER|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PERCENT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNION|UNIQUE|UPDATE|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WRITETEXT)(?=[^\w-]|$)/i,null],[PR.PR_LITERAL,/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],[PR.PR_PLAIN,/^[a-z_][\w-]*/i],[PR.PR_PUNCTUATION,/^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/]]),['sql'])
    +
    +
    +// VB extension
    +
    +PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[\t\n\r \xA0\u2028\u2029]+/,null,'	\n\r \xa0\u2028\u2029'],[PR.PR_STRING,/^(?:[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})(?:[\"\u201C\u201D]c|$)|[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})*(?:[\"\u201C\u201D]|$))/i,null,'\"\u201c\u201d'],[PR.PR_COMMENT,/^[\'\u2018\u2019][^\r\n\u2028\u2029]*/,null,'\'\u2018\u2019']],[[PR.PR_KEYWORD,/^(?:AddHandler|AddressOf|Alias|And|AndAlso|Ansi|As|Assembly|Auto|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|New|Next|Not|NotInheritable|NotOverridable|Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Preserve|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TypeOf|Unicode|Until|Variant|Wend|When|While|With|WithEvents|WriteOnly|Xor|EndIf|GoSub|Let|Variant|Wend)\b/i,null],[PR.PR_COMMENT,/^REM[^\r\n\u2028\u2029]*/i],[PR.PR_LITERAL,/^(?:True\b|False\b|Nothing\b|\d+(?:E[+\-]?\d+[FRD]?|[FRDSIL])?|(?:&H[0-9A-F]+|&O[0-7]+)[SIL]?|\d*\.\d+(?:E[+\-]?\d+)?[FRD]?|#\s+(?:\d+[\-\/]\d+[\-\/]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)?|\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)\s+#)/i],[PR.PR_PLAIN,/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*\])/i],[PR.PR_PUNCTUATION,/^[^\w\t\n\r \"\'\[\]\xA0\u2018\u2019\u201C\u201D\u2028\u2029]+/],[PR.PR_PUNCTUATION,/^(?:\[|\])/]]),['vb','vbs'])
    diff --git a/docs/javascript/searchdata.js b/docs/javascript/searchdata.js
    new file mode 100644
    index 0000000..ca41a89
    --- /dev/null
    +++ b/docs/javascript/searchdata.js
    @@ -0,0 +1,242 @@
    +var indexSectionsWithContent = {
    +   "Functions": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": true,
    +      "B": false,
    +      "C": true,
    +      "D": false,
    +      "E": true,
    +      "F": false,
    +      "G": true,
    +      "H": true,
    +      "I": true,
    +      "J": false,
    +      "K": false,
    +      "L": false,
    +      "M": false,
    +      "N": false,
    +      "O": false,
    +      "P": true,
    +      "Q": false,
    +      "R": false,
    +      "S": true,
    +      "T": false,
    +      "U": true,
    +      "V": false,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "Files": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": false,
    +      "B": false,
    +      "C": true,
    +      "D": false,
    +      "E": false,
    +      "F": true,
    +      "G": false,
    +      "H": false,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": false,
    +      "M": false,
    +      "N": false,
    +      "O": false,
    +      "P": false,
    +      "Q": false,
    +      "R": false,
    +      "S": true,
    +      "T": false,
    +      "U": false,
    +      "V": false,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "CBAEvents": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": true,
    +      "B": false,
    +      "C": true,
    +      "D": false,
    +      "E": true,
    +      "F": false,
    +      "G": false,
    +      "H": true,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": false,
    +      "M": false,
    +      "N": false,
    +      "O": false,
    +      "P": true,
    +      "Q": false,
    +      "R": true,
    +      "S": false,
    +      "T": false,
    +      "U": false,
    +      "V": false,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "Variables": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": true,
    +      "B": false,
    +      "C": true,
    +      "D": false,
    +      "E": true,
    +      "F": true,
    +      "G": false,
    +      "H": true,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": true,
    +      "M": true,
    +      "N": true,
    +      "O": false,
    +      "P": true,
    +      "Q": false,
    +      "R": true,
    +      "S": false,
    +      "T": true,
    +      "U": false,
    +      "V": true,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "General": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": true,
    +      "B": true,
    +      "C": true,
    +      "D": false,
    +      "E": true,
    +      "F": true,
    +      "G": true,
    +      "H": false,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": true,
    +      "M": true,
    +      "N": false,
    +      "O": true,
    +      "P": false,
    +      "Q": false,
    +      "R": false,
    +      "S": true,
    +      "T": false,
    +      "U": false,
    +      "V": true,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "Macros": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": true,
    +      "B": true,
    +      "C": true,
    +      "D": false,
    +      "E": false,
    +      "F": false,
    +      "G": false,
    +      "H": false,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": true,
    +      "M": false,
    +      "N": false,
    +      "O": false,
    +      "P": true,
    +      "Q": false,
    +      "R": false,
    +      "S": true,
    +      "T": false,
    +      "U": false,
    +      "V": true,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "CBASettings": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": true,
    +      "B": false,
    +      "C": false,
    +      "D": false,
    +      "E": true,
    +      "F": true,
    +      "G": false,
    +      "H": false,
    +      "I": true,
    +      "J": false,
    +      "K": false,
    +      "L": false,
    +      "M": true,
    +      "N": false,
    +      "O": false,
    +      "P": true,
    +      "Q": false,
    +      "R": false,
    +      "S": true,
    +      "T": true,
    +      "U": false,
    +      "V": false,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      },
    +   "EventHandlers": {
    +      "Symbols": false,
    +      "Numbers": false,
    +      "A": false,
    +      "B": false,
    +      "C": false,
    +      "D": true,
    +      "E": true,
    +      "F": false,
    +      "G": false,
    +      "H": true,
    +      "I": false,
    +      "J": false,
    +      "K": false,
    +      "L": false,
    +      "M": true,
    +      "N": false,
    +      "O": true,
    +      "P": true,
    +      "Q": false,
    +      "R": false,
    +      "S": false,
    +      "T": false,
    +      "U": false,
    +      "V": false,
    +      "W": false,
    +      "X": false,
    +      "Y": false,
    +      "Z": false
    +      }
    +   }
    \ No newline at end of file
    diff --git a/docs/search/CBAEventsA.html b/docs/search/CBAEventsA.html
    new file mode 100644
    index 0000000..0b236d1
    --- /dev/null
    +++ b/docs/search/CBAEventsA.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_ace_undadvanced_undthrowing_undthrowFiredXEH><div class=IEntry><a href="../files/recorder/fnc_addEventMission-sqf.html#ace_advanced_throwing_throwFiredXEH" target=_parent class=ISymbol>ace_advanced_throwing_throwFiredXEH</a></div></div><div class=SRResult id=SR_ace_undexplosives_undplace><div class=IEntry><a href="../files/recorder/fnc_addEventMission-sqf.html#ace_explosives_place" target=_parent class=ISymbol>ace_explosives_place</a></div></div><div class=SRResult id=SR_addDebugBullet><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_eh_firedMan-sqf.html#OCAP_recorder_addDebugBullet" target=_parent class=ISymbol>addDebugBullet</a></div></div><div class=SRResult id=SR_addDebugMagIcon><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_eh_firedMan-sqf.html#OCAP_recorder_addDebugMagIcon" target=_parent class=ISymbol>addDebugMagIcon</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBAEventsC.html b/docs/search/CBAEventsC.html
    new file mode 100644
    index 0000000..5b5199f
    --- /dev/null
    +++ b/docs/search/CBAEventsC.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_counterEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_counterEvent" target=_parent class=ISymbol>counterEvent</a></div></div><div class=SRResult id=SR_counterInit><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_counterInit" target=_parent class=ISymbol>counterInit</a></div></div><div class=SRResult id=SR_customEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_customEvent" target=_parent class=ISymbol>customEvent</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBAEventsE.html b/docs/search/CBAEventsE.html
    new file mode 100644
    index 0000000..0e5ffa0
    --- /dev/null
    +++ b/docs/search/CBAEventsE.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_exportData><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_exportData" target=_parent class=ISymbol>exportData</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBAEventsH.html b/docs/search/CBAEventsH.html
    new file mode 100644
    index 0000000..569f11b
    --- /dev/null
    +++ b/docs/search/CBAEventsH.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_handleMarker><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_handleMarkers-sqf.html#OCAP_handleMarker" target=_parent class=ISymbol>handleMarker</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBAEventsP.html b/docs/search/CBAEventsP.html
    new file mode 100644
    index 0000000..ce5abe3
    --- /dev/null
    +++ b/docs/search/CBAEventsP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_pause><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_pause" target=_parent class=ISymbol>pause</a></div></div><div class=SRResult id=SR_Projectiles><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Projectiles" target=_parent class=ISymbol>Projectiles</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBAEventsR.html b/docs/search/CBAEventsR.html
    new file mode 100644
    index 0000000..e925913
    --- /dev/null
    +++ b/docs/search/CBAEventsR.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_record><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_record" target=_parent class=ISymbol>record</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBASettingsA.html b/docs/search/CBASettingsA.html
    new file mode 100644
    index 0000000..089a878
    --- /dev/null
    +++ b/docs/search/CBASettingsA.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_administratorList><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/main/XEH_preInit-sqf.html#OCAP_administratorList" target=_parent class=ISymbol>administratorList</a></div></div><div class=SRResult id=SR_autoStart><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_autoStart" target=_parent class=ISymbol>autoStart</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBASettingsE.html b/docs/search/CBASettingsE.html
    new file mode 100644
    index 0000000..73d6777
    --- /dev/null
    +++ b/docs/search/CBASettingsE.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_enabled><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/main/XEH_preInit-sqf.html#OCAP_enabled" target=_parent class=ISymbol>enabled</a></div></div><div class=SRResult id=SR_excludeClassFromRecord><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_excludeClassFromRecord" target=_parent class=ISymbol>excludeClassFromRecord</a></div></div><div class=SRResult id=SR_excludeKindFromRecord><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_excludeKindFromRecord" target=_parent class=ISymbol>excludeKindFromRecord</a></div></div><div class=SRResult id=SR_excludeMarkerFromRecord><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_excludeMarkerFromRecord" target=_parent class=ISymbol>excludeMarkerFromRecord</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBASettingsF.html b/docs/search/CBASettingsF.html
    new file mode 100644
    index 0000000..8165696
    --- /dev/null
    +++ b/docs/search/CBASettingsF.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_frameCaptureDelay><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_frameCaptureDelay" target=_parent class=ISymbol>frameCaptureDelay</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBASettingsI.html b/docs/search/CBASettingsI.html
    new file mode 100644
    index 0000000..97ebc23
    --- /dev/null
    +++ b/docs/search/CBASettingsI.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_isDebug><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/main/XEH_preInit-sqf.html#OCAP_isDebug" target=_parent class=ISymbol>isDebug</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBASettingsM.html b/docs/search/CBASettingsM.html
    new file mode 100644
    index 0000000..562ed13
    --- /dev/null
    +++ b/docs/search/CBASettingsM.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_minMissionTime><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_minMissionTime" target=_parent class=ISymbol>minMissionTime</a></div></div><div class=SRResult id=SR_minPlayerCount><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_minPlayerCount" target=_parent class=ISymbol>minPlayerCount</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBASettingsP.html b/docs/search/CBASettingsP.html
    new file mode 100644
    index 0000000..4ea9354
    --- /dev/null
    +++ b/docs/search/CBASettingsP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_preferACEUnconscious><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_preferACEUnconscious" target=_parent class=ISymbol>preferACEUnconscious</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBASettingsS.html b/docs/search/CBASettingsS.html
    new file mode 100644
    index 0000000..aa9f3d9
    --- /dev/null
    +++ b/docs/search/CBASettingsS.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_saveMissionEnded><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_saveMissionEnded" target=_parent class=ISymbol>saveMissionEnded</a></div></div><div class=SRResult id=SR_saveOnEmpty><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_saveOnEmpty" target=_parent class=ISymbol>saveOnEmpty</a></div></div><div class=SRResult id=SR_saveTag><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_saveTag" target=_parent class=ISymbol>saveTag</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/CBASettingsT.html b/docs/search/CBASettingsT.html
    new file mode 100644
    index 0000000..5e38c01
    --- /dev/null
    +++ b/docs/search/CBASettingsT.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_trackTickets><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_trackTickets" target=_parent class=ISymbol>trackTickets</a></div></div><div class=SRResult id=SR_trackTimeInterval><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_trackTimeInterval" target=_parent class=ISymbol>trackTimeInterval</a></div></div><div class=SRResult id=SR_trackTimes><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_trackTimes" target=_parent class=ISymbol>trackTimes</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/EventHandlersD.html b/docs/search/EventHandlersD.html
    new file mode 100644
    index 0000000..b191455
    --- /dev/null
    +++ b/docs/search/EventHandlersD.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Deleted><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Deleted" target=_parent class=ISymbol>Deleted</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/EventHandlersE.html b/docs/search/EventHandlersE.html
    new file mode 100644
    index 0000000..a88db21
    --- /dev/null
    +++ b/docs/search/EventHandlersE.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Ended><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_Ended" target=_parent class=ISymbol>Ended</a></div></div><div class=SRResult id=SR_EntityKilled><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_EntityKilled" target=_parent class=ISymbol>EntityKilled</a></div></div><div class=SRResult id=SR_EntityRespawned><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_EntityRespawned" target=_parent class=ISymbol>EntityRespawned</a></div></div><div class=SRResult id=SR_Explode><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Explode" target=_parent class=ISymbol>Explode</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/EventHandlersH.html b/docs/search/EventHandlersH.html
    new file mode 100644
    index 0000000..a7b1026
    --- /dev/null
    +++ b/docs/search/EventHandlersH.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_HandleDisconnect><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_HandleDisconnect" target=_parent class=ISymbol>HandleDisconnect</a></div></div><div class=SRResult id=SR_HitExplosion><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#HitExplosion" target=_parent class=ISymbol>HitExplosion</a></div></div><div class=SRResult id=SR_HitPart><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#HitPart" target=_parent class=ISymbol>HitPart</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/EventHandlersM.html b/docs/search/EventHandlersM.html
    new file mode 100644
    index 0000000..68af557
    --- /dev/null
    +++ b/docs/search/EventHandlersM.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_MarkerCreated><div class=IEntry><a href="../files/recorder/fnc_handleMarkers-sqf.html#MarkerCreated" target=_parent class=ISymbol>MarkerCreated</a></div></div><div class=SRResult id=SR_MarkerDeleted><div class=IEntry><a href="../files/recorder/fnc_handleMarkers-sqf.html#MarkerDeleted" target=_parent class=ISymbol>MarkerDeleted</a></div></div><div class=SRResult id=SR_MarkerUpdated><div class=IEntry><a href="../files/recorder/fnc_handleMarkers-sqf.html#MarkerUpdated" target=_parent class=ISymbol>MarkerUpdated</a></div></div><div class=SRResult id=SR_MPEnded><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_MPEnded" target=_parent class=ISymbol>MPEnded</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/EventHandlersO.html b/docs/search/EventHandlersO.html
    new file mode 100644
    index 0000000..ca3ecb3
    --- /dev/null
    +++ b/docs/search/EventHandlersO.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_OnUserAdminStateChanged><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_OnUserAdminStateChanged" target=_parent class=ISymbol>OnUserAdminStateChanged</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/EventHandlersP.html b/docs/search/EventHandlersP.html
    new file mode 100644
    index 0000000..347a296
    --- /dev/null
    +++ b/docs/search/EventHandlersP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_PlayerConnected><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_PlayerConnected" target=_parent class=ISymbol>PlayerConnected</a></div></div><div class=SRResult id=SR_Projectiles_lpaBullets_rpa><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Projectiles(Bullets)" target=_parent class=ISymbol>Projectiles(Bullets)</a></div></div><div class=SRResult id=SR_Projectiles_lpaNon_minBullets_rpa><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Projectiles(Non-Bullets)" target=_parent class=ISymbol>Projectiles(Non-Bullets)</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FilesC.html b/docs/search/FilesC.html
    new file mode 100644
    index 0000000..443a96b
    --- /dev/null
    +++ b/docs/search/FilesC.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_CBA_spcSettings><div class=IEntry><a href="javascript:searchResults.Toggle('SR_CBA_spcSettings')" class=ISymbol>CBA Settings</a><div class=ISubIndex><a href="../files/main/XEH_preInit-sqf.html#CBA_Settings" target=_parent class=IFile>main\<wbr>XEH_preInit.sqf</a><a href="../files/recorder/XEH_preInit-sqf.html#CBA_Settings" target=_parent class=IFile>recorder\<wbr>XEH_preInit.sqf</a></div></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FilesF.html b/docs/search/FilesF.html
    new file mode 100644
    index 0000000..79394a7
    --- /dev/null
    +++ b/docs/search/FilesF.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_fnc_undaceExplosives_persqf><div class=IEntry><a href="../files/recorder/fnc_aceExplosives-sqf.html#fnc_aceExplosives.sqf" target=_parent class=ISymbol>fnc_aceExplosives.sqf</a></div></div><div class=SRResult id=SR_fnc_undaddEventMission_persqf><div class=IEntry><a href="../files/recorder/fnc_addEventMission-sqf.html#fnc_addEventMission.sqf" target=_parent class=ISymbol>fnc_addEventMission.sqf</a></div></div><div class=SRResult id=SR_fnc_undaddUnitEventHandlers_persqf><div class=IEntry><a href="../files/recorder/fnc_addUnitEventHandlers-sqf.html#fnc_addUnitEventHandlers.sqf" target=_parent class=ISymbol>fnc_addUnitEventHandlers.sqf</a></div></div><div class=SRResult id=SR_fnc_undadminUIControl_persqf><div class=IEntry><a href="../files/recorder/fnc_adminUIcontrol-sqf.html#fnc_adminUIControl.sqf" target=_parent class=ISymbol>fnc_adminUIControl.sqf</a></div></div><div class=SRResult id=SR_fnc_undcaptureLoop_persqf><div class=IEntry><a href="../files/recorder/fnc_captureLoop-sqf.html#fnc_captureLoop.sqf" target=_parent class=ISymbol>fnc_captureLoop.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undconnected_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_connected-sqf.html#fnc_eh_connected.sqf" target=_parent class=ISymbol>fnc_eh_connected.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_unddisconnected_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_disconnected-sqf.html#fnc_eh_disconnected.sqf" target=_parent class=ISymbol>fnc_eh_disconnected.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undfiredMan_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#fnc_eh_firedMan.sqf" target=_parent class=ISymbol>fnc_eh_firedMan.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undkilled_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_killed-sqf.html#fnc_eh_killed.sqf" target=_parent class=ISymbol>fnc_eh_killed.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undonUserAdminStateChanged_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_onUserAdminStateChanged-sqf.html#fnc_eh_onUserAdminStateChanged.sqf" target=_parent class=ISymbol>fnc_eh_onUserAdminStateChanged.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undprojectileHit_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_projectileHit-sqf.html#fnc_eh_projectileHit.sqf" target=_parent class=ISymbol>fnc_eh_projectileHit.sqf</a></div></div><div class=SRResult id=SR_fnc_undentityMonitors_persqf><div class=IEntry><a href="../files/recorder/fnc_entityMonitors-sqf.html#fnc_entityMonitors.sqf" target=_parent class=ISymbol>fnc_entityMonitors.sqf</a></div></div><div class=SRResult id=SR_fnc_undexportData_persqf><div class=IEntry><a href="../files/recorder/fnc_exportData-sqf.html#fnc_exportData.sqf" target=_parent class=ISymbol>fnc_exportData.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetAmmoMarkerData_persqf><div class=IEntry><a href="../files/recorder/fnc_getAmmoMarkerData-sqf.html#fnc_getAmmoMarkerData.sqf" target=_parent class=ISymbol>fnc_getAmmoMarkerData.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetClass_persqf><div class=IEntry><a href="../files/recorder/fnc_getClass-sqf.html#fnc_getClass.sqf" target=_parent class=ISymbol>fnc_getClass.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetEventWeaponText_persqf><div class=IEntry><a href="../files/recorder/fnc_getEventWeaponText-sqf.html#fnc_getEventWeaponText.sqf" target=_parent class=ISymbol>fnc_getEventWeaponText.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetInstigator_persqf><div class=IEntry><a href="../files/recorder/fnc_getInstigator-sqf.html#fnc_getInstigator.sqf" target=_parent class=ISymbol>fnc_getInstigator.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetUnitType_persqf><div class=IEntry><a href="../files/recorder/fnc_getUnitType-sqf.html#fnc_getUnitType.sqf" target=_parent class=ISymbol>fnc_getUnitType.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetWeaponDisplayData_persqf><div class=IEntry><a href="../files/recorder/fnc_getWeaponDisplayData-sqf.html#fnc_getWeaponDisplayData.sqf" target=_parent class=ISymbol>fnc_getWeaponDisplayData.sqf</a></div></div><div class=SRResult id=SR_fnc_undhandleCustomEvent_persqf><div class=IEntry><a href="../files/recorder/fnc_handleCustomEvent-sqf.html#fnc_handleCustomEvent.sqf" target=_parent class=ISymbol>fnc_handleCustomEvent.sqf</a></div></div><div class=SRResult id=SR_fnc_undhandleMarkers_persqf><div class=IEntry><a href="../files/recorder/fnc_handleMarkers-sqf.html#fnc_handleMarkers.sqf" target=_parent class=ISymbol>fnc_handleMarkers.sqf</a></div></div><div class=SRResult id=SR_fnc_undinit_persqf><div class=IEntry><a href="../files/recorder/fnc_init-sqf.html#fnc_init.sqf" target=_parent class=ISymbol>fnc_init.sqf</a></div></div><div class=SRResult id=SR_fnc_undisKindOfApc_persqf><div class=IEntry><a href="../files/recorder/fnc_isKindOfApc-sqf.html#fnc_isKindOfApc.sqf" target=_parent class=ISymbol>fnc_isKindOfApc.sqf</a></div></div><div class=SRResult id=SR_fnc_undprojectileMonitors_persqf><div class=IEntry><a href="../files/recorder/fnc_projectileMonitors-sqf.html#fnc_projectileMonitors.sqf" target=_parent class=ISymbol>fnc_projectileMonitors.sqf</a></div></div><div class=SRResult id=SR_fnc_undsendData_persqf><div class=IEntry><a href="../files/extension/fnc_sendData-sqf.html#fnc_sendData.sqf" target=_parent class=ISymbol>fnc_sendData.sqf</a></div></div><div class=SRResult id=SR_fnc_undstartRecording_persqf><div class=IEntry><a href="../files/recorder/fnc_startRecording-sqf.html#fnc_startRecording.sqf" target=_parent class=ISymbol>fnc_startRecording.sqf</a></div></div><div class=SRResult id=SR_fnc_undstopRecording_persqf><div class=IEntry><a href="../files/recorder/fnc_stopRecording-sqf.html#fnc_stopRecording.sqf" target=_parent class=ISymbol>fnc_stopRecording.sqf</a></div></div><div class=SRResult id=SR_fnc_undupdateTime_persqf><div class=IEntry><a href="../files/recorder/fnc_updateTime-sqf.html#fnc_updateTime.sqf" target=_parent class=ISymbol>fnc_updateTime.sqf</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FilesS.html b/docs/search/FilesS.html
    new file mode 100644
    index 0000000..c972dbd
    --- /dev/null
    +++ b/docs/search/FilesS.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_script_undcomponent_perhpp><div class=IEntry><a href="javascript:searchResults.Toggle('SR_script_undcomponent_perhpp')" class=ISymbol>script_component.hpp</a><div class=ISubIndex><a href="../files/extension/script_component-hpp.html#script_component.hpp" target=_parent class=IFile>extension\<wbr>script_component.hpp</a><a href="../files/main/script_component-hpp.html#script_component.hpp" target=_parent class=IFile>main\<wbr>script_component.hpp</a><a href="../files/recorder/script_component-hpp.html#script_component.hpp" target=_parent class=IFile>recorder\<wbr>script_component.hpp</a></div></div></div><div class=SRResult id=SR_script_undmacros_perhpp><div class=IEntry><a href="../files/main/script_macros-hpp.html#script_macros.hpp" target=_parent class=ISymbol>script_macros.hpp</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsA.html b/docs/search/FunctionsA.html
    new file mode 100644
    index 0000000..6e3274f
    --- /dev/null
    +++ b/docs/search/FunctionsA.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_aceExplosives><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_aceExplosives-sqf.html#OCAP_recorder_fnc_aceExplosives" target=_parent class=ISymbol>aceExplosives</a></div></div><div class=SRResult id=SR_addEventMission><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_recorder_fnc_addEventMission" target=_parent class=ISymbol>addEventMission</a></div></div><div class=SRResult id=SR_addUnitEventHandlers><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_addUnitEventHandlers-sqf.html#OCAP_recorder_fnc_addUnitEventHandlers" target=_parent class=ISymbol>addUnitEventHandlers</a></div></div><div class=SRResult id=SR_adminUIControl><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_adminUIcontrol-sqf.html#OCAP_recorder_fnc_adminUIControl" target=_parent class=ISymbol>adminUIControl</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsC.html b/docs/search/FunctionsC.html
    new file mode 100644
    index 0000000..8469c35
    --- /dev/null
    +++ b/docs/search/FunctionsC.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_captureLoop><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_captureLoop-sqf.html#OCAP_recorder_fnc_captureLoop" target=_parent class=ISymbol>captureLoop</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsE.html b/docs/search/FunctionsE.html
    new file mode 100644
    index 0000000..5f796b0
    --- /dev/null
    +++ b/docs/search/FunctionsE.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_eh_undconnected><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_connected-sqf.html#OCAP_recorder_fnc_eh_connected" target=_parent class=ISymbol>eh_connected</a></div></div><div class=SRResult id=SR_eh_unddisconnected><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_disconnected-sqf.html#OCAP_recorder_fnc_eh_disconnected" target=_parent class=ISymbol>eh_disconnected</a></div></div><div class=SRResult id=SR_eh_undfiredMan><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_firedMan-sqf.html#OCAP_recorder_fnc_eh_firedMan" target=_parent class=ISymbol>eh_firedMan</a></div></div><div class=SRResult id=SR_eh_undkilled><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_killed-sqf.html#OCAP_recorder_fnc_eh_killed" target=_parent class=ISymbol>eh_killed</a></div></div><div class=SRResult id=SR_eh_undonUserAdminStateChanged><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_onUserAdminStateChanged-sqf.html#OCAP_recorder_fnc_eh_onUserAdminStateChanged" target=_parent class=ISymbol>eh_onUserAdminStateChanged</a></div></div><div class=SRResult id=SR_eh_undprojectileHit><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_projectileHit-sqf.html#OCAP_recorder_fnc_eh_projectileHit" target=_parent class=ISymbol>eh_projectileHit</a></div></div><div class=SRResult id=SR_entityMonitors><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_entityMonitors-sqf.html#OCAP_recorder_fnc_entityMonitors" target=_parent class=ISymbol>entityMonitors</a></div></div><div class=SRResult id=SR_exportData><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_exportData-sqf.html#OCAP_recorder_fnc_exportData" target=_parent class=ISymbol>exportData</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsG.html b/docs/search/FunctionsG.html
    new file mode 100644
    index 0000000..491a410
    --- /dev/null
    +++ b/docs/search/FunctionsG.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_getAmmoMarkerData><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getAmmoMarkerData-sqf.html#OCAP_recorder_fnc_getAmmoMarkerData" target=_parent class=ISymbol>getAmmoMarkerData</a></div></div><div class=SRResult id=SR_getClass><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getClass-sqf.html#OCAP_recorder_fnc_getClass" target=_parent class=ISymbol>getClass</a></div></div><div class=SRResult id=SR_getEventWeaponText><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getEventWeaponText-sqf.html#OCAP_recorder_fnc_getEventWeaponText" target=_parent class=ISymbol>getEventWeaponText</a></div></div><div class=SRResult id=SR_getInstigator><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getInstigator-sqf.html#OCAP_recorder_fnc_getInstigator" target=_parent class=ISymbol>getInstigator</a></div></div><div class=SRResult id=SR_getUnitType><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getUnitType-sqf.html#OCAP_recorder_fnc_getUnitType" target=_parent class=ISymbol>getUnitType</a></div></div><div class=SRResult id=SR_getWeaponDisplayData><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getWeaponDisplayData-sqf.html#OCAP_recorder_fnc_getWeaponDisplayData" target=_parent class=ISymbol>getWeaponDisplayData</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsH.html b/docs/search/FunctionsH.html
    new file mode 100644
    index 0000000..ff7059d
    --- /dev/null
    +++ b/docs/search/FunctionsH.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_handleCustomEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_handleCustomEvent-sqf.html#OCAP_recorder_fnc_handleCustomEvent" target=_parent class=ISymbol>handleCustomEvent</a></div></div><div class=SRResult id=SR_handleMarkers><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_handleMarkers-sqf.html#OCAP_recorder_fnc_handleMarkers" target=_parent class=ISymbol>handleMarkers</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsI.html b/docs/search/FunctionsI.html
    new file mode 100644
    index 0000000..2da2ac7
    --- /dev/null
    +++ b/docs/search/FunctionsI.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_init><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_fnc_init" target=_parent class=ISymbol>init</a></div></div><div class=SRResult id=SR_isKindOfApc><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_isKindOfApc-sqf.html#OCAP_recorder_fnc_isKindOfApc" target=_parent class=ISymbol>isKindOfApc</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsP.html b/docs/search/FunctionsP.html
    new file mode 100644
    index 0000000..6b33e6c
    --- /dev/null
    +++ b/docs/search/FunctionsP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_projectileMonitors><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_projectileMonitors-sqf.html#OCAP_recorder_fnc_projectileMonitors" target=_parent class=ISymbol>projectileMonitors</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsS.html b/docs/search/FunctionsS.html
    new file mode 100644
    index 0000000..86bf492
    --- /dev/null
    +++ b/docs/search/FunctionsS.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_sendData><div class=IEntry><span class=ISymbolPrefix>OCAP_extension_fnc_</span><a href="../files/extension/fnc_sendData-sqf.html#OCAP_extension_fnc_sendData" target=_parent class=ISymbol>sendData</a></div></div><div class=SRResult id=SR_startRecording><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_startRecording-sqf.html#OCAP_recorder_fnc_startRecording" target=_parent class=ISymbol>startRecording</a></div></div><div class=SRResult id=SR_stopRecording><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_stopRecording-sqf.html#OCAP_recorder_fnc_stopRecording" target=_parent class=ISymbol>stopRecording</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/FunctionsU.html b/docs/search/FunctionsU.html
    new file mode 100644
    index 0000000..27bf0df
    --- /dev/null
    +++ b/docs/search/FunctionsU.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_updateTime><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_updateTime-sqf.html#OCAP_recorder_fnc_updateTime" target=_parent class=ISymbol>updateTime</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralA.html b/docs/search/GeneralA.html
    new file mode 100644
    index 0000000..6ceb9a6
    --- /dev/null
    +++ b/docs/search/GeneralA.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_ace_undadvanced_undthrowing_undthrowFiredXEH><div class=IEntry><a href="../files/recorder/fnc_addEventMission-sqf.html#ace_advanced_throwing_throwFiredXEH" target=_parent class=ISymbol>ace_advanced_throwing_throwFiredXEH</a></div></div><div class=SRResult id=SR_ace_undexplosives_undplace><div class=IEntry><a href="../files/recorder/fnc_addEventMission-sqf.html#ace_explosives_place" target=_parent class=ISymbol>ace_explosives_place</a></div></div><div class=SRResult id=SR_aceExplosives><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_aceExplosives-sqf.html#OCAP_recorder_fnc_aceExplosives" target=_parent class=ISymbol>aceExplosives</a></div></div><div class=SRResult id=SR_addDebugBullet><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_eh_firedMan-sqf.html#OCAP_recorder_addDebugBullet" target=_parent class=ISymbol>addDebugBullet</a></div></div><div class=SRResult id=SR_addDebugMagIcon><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_eh_firedMan-sqf.html#OCAP_recorder_addDebugMagIcon" target=_parent class=ISymbol>addDebugMagIcon</a></div></div><div class=SRResult id=SR_addEventMission><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_recorder_fnc_addEventMission" target=_parent class=ISymbol>addEventMission</a></div></div><div class=SRResult id=SR_ADDON><div class=IEntry><a href="../files/main/script_macros-hpp.html#ADDON" target=_parent class=ISymbol>ADDON</a></div></div><div class=SRResult id=SR_addUnitEventHandlers><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_addUnitEventHandlers-sqf.html#OCAP_recorder_fnc_addUnitEventHandlers" target=_parent class=ISymbol>addUnitEventHandlers</a></div></div><div class=SRResult id=SR_administratorList><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/main/XEH_preInit-sqf.html#OCAP_administratorList" target=_parent class=ISymbol>administratorList</a></div></div><div class=SRResult id=SR_adminUIControl><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_adminUIcontrol-sqf.html#OCAP_recorder_fnc_adminUIControl" target=_parent class=ISymbol>adminUIControl</a></div></div><div class=SRResult id=SR_ARR2><div class=IEntry><a href="../files/main/script_macros-hpp.html#ARR2" target=_parent class=ISymbol>ARR2</a></div></div><div class=SRResult id=SR_Auto_minStart_spcSettings><div class=IEntry><a href="../files/recorder/XEH_preInit-sqf.html#Auto-Start_Settings" target=_parent class=ISymbol>Auto-Start Settings</a></div></div><div class=SRResult id=SR_autoStart><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_autoStart" target=_parent class=ISymbol>autoStart</a></div></div><div class=SRResult id=SR2_autoStart><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_autoStart" target=_parent class=ISymbol>autoStart</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralB.html b/docs/search/GeneralB.html
    new file mode 100644
    index 0000000..5e160dc
    --- /dev/null
    +++ b/docs/search/GeneralB.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_BOOL><div class=IEntry><a href="../files/main/script_macros-hpp.html#BOOL" target=_parent class=ISymbol>BOOL</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralC.html b/docs/search/GeneralC.html
    new file mode 100644
    index 0000000..ab1e054
    --- /dev/null
    +++ b/docs/search/GeneralC.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_captureFrameNo><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_captureFrameNo" target=_parent class=ISymbol>captureFrameNo</a></div></div><div class=SRResult id=SR_captureLoop><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_captureLoop-sqf.html#OCAP_recorder_fnc_captureLoop" target=_parent class=ISymbol>captureLoop</a></div></div><div class=SRResult id=SR_CBA_spcEvents><div class=IEntry><a href="javascript:searchResults.Toggle('SR_CBA_spcEvents')" class=ISymbol>CBA Events</a><div class=ISubIndex><a href="../files/recorder/fnc_addEventMission-sqf.html#CBA_Events" target=_parent class=IFile>recorder\<wbr>fnc_addEventMission.sqf</a><a href="../files/recorder/fnc_eh_firedMan-sqf.html#CBA_Events" target=_parent class=IFile>recorder\<wbr>fnc_eh_firedMan.sqf</a><a href="../files/recorder/fnc_handleMarkers-sqf.html#CBA_Events" target=_parent class=IFile>recorder\<wbr>fnc_handleMarkers.sqf</a></div></div></div><div class=SRResult id=SR_CBA_spcListener_spcHandles><div class=IEntry><a href="../files/recorder/fnc_addEventMission-sqf.html#CBA_Listener_Handles" target=_parent class=ISymbol>CBA Listener Handles</a></div></div><div class=SRResult id=SR_CBA_spcSettings><div class=IEntry><a href="javascript:searchResults.Toggle('SR_CBA_spcSettings')" class=ISymbol>CBA Settings</a><div class=ISubIndex><a href="../files/main/XEH_preInit-sqf.html#CBA_Settings" target=_parent class=IFile>main\<wbr>XEH_preInit.sqf</a><a href="../files/recorder/XEH_preInit-sqf.html#CBA_Settings" target=_parent class=IFile>recorder\<wbr>XEH_preInit.sqf</a></div></div></div><div class=SRResult id=SR_COMPONENT><div class=IEntry><a href="javascript:searchResults.Toggle('SR_COMPONENT')" class=ISymbol>COMPONENT</a><div class=ISubIndex><a href="../files/extension/script_component-hpp.html#COMPONENT" target=_parent class=IFile>extension\<wbr>script_component.hpp</a><a href="../files/main/script_component-hpp.html#COMPONENT" target=_parent class=IFile>main\<wbr>script_component.hpp</a><a href="../files/recorder/script_component-hpp.html#COMPONENT" target=_parent class=IFile>recorder\<wbr>script_component.hpp</a></div></div></div><div class=SRResult id=SR_COMPONENT_undBEAUTIFIED><div class=IEntry><a href="javascript:searchResults.Toggle('SR_COMPONENT_undBEAUTIFIED')" class=ISymbol>COMPONENT_BEAUTIFIED</a><div class=ISubIndex><a href="../files/extension/script_component-hpp.html#COMPONENT_BEAUTIFIED" target=_parent class=IFile>extension\<wbr>script_component.hpp</a><a href="../files/main/script_component-hpp.html#COMPONENT_BEAUTIFIED" target=_parent class=IFile>main\<wbr>script_component.hpp</a><a href="../files/recorder/script_component-hpp.html#COMPONENT_BEAUTIFIED" target=_parent class=IFile>recorder\<wbr>script_component.hpp</a></div></div></div><div class=SRResult id=SR_COMPONENT_undNAME><div class=IEntry><a href="../files/main/script_macros-hpp.html#COMPONENT_NAME" target=_parent class=ISymbol>COMPONENT_NAME</a></div></div><div class=SRResult id=SR_Core><div class=IEntry><a href="javascript:searchResults.Toggle('SR_Core')" class=ISymbol>Core</a><div class=ISubIndex><a href="../files/main/XEH_preInit-sqf.html#Core" target=_parent class=IFile>main\<wbr>XEH_preInit.sqf</a><a href="../files/recorder/XEH_preInit-sqf.html#Core" target=_parent class=IFile>recorder\<wbr>XEH_preInit.sqf</a></div></div></div><div class=SRResult id=SR_counter_undsides><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_counter_sides" target=_parent class=ISymbol>counter_sides</a></div></div><div class=SRResult id=SR_counterEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_counterEvent" target=_parent class=ISymbol>counterEvent</a></div></div><div class=SRResult id=SR_counterInit><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_counterInit" target=_parent class=ISymbol>counterInit</a></div></div><div class=SRResult id=SR_customEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_customEvent" target=_parent class=ISymbol>customEvent</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralD.html b/docs/search/GeneralD.html
    new file mode 100644
    index 0000000..b191455
    --- /dev/null
    +++ b/docs/search/GeneralD.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Deleted><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Deleted" target=_parent class=ISymbol>Deleted</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralE.html b/docs/search/GeneralE.html
    new file mode 100644
    index 0000000..f685d9b
    --- /dev/null
    +++ b/docs/search/GeneralE.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_eh_undconnected><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_connected-sqf.html#OCAP_recorder_fnc_eh_connected" target=_parent class=ISymbol>eh_connected</a></div></div><div class=SRResult id=SR_eh_unddisconnected><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_disconnected-sqf.html#OCAP_recorder_fnc_eh_disconnected" target=_parent class=ISymbol>eh_disconnected</a></div></div><div class=SRResult id=SR_eh_undfiredMan><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_firedMan-sqf.html#OCAP_recorder_fnc_eh_firedMan" target=_parent class=ISymbol>eh_firedMan</a></div></div><div class=SRResult id=SR_eh_undkilled><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_killed-sqf.html#OCAP_recorder_fnc_eh_killed" target=_parent class=ISymbol>eh_killed</a></div></div><div class=SRResult id=SR_eh_undonUserAdminStateChanged><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_onUserAdminStateChanged-sqf.html#OCAP_recorder_fnc_eh_onUserAdminStateChanged" target=_parent class=ISymbol>eh_onUserAdminStateChanged</a></div></div><div class=SRResult id=SR_eh_undprojectileHit><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_eh_projectileHit-sqf.html#OCAP_recorder_fnc_eh_projectileHit" target=_parent class=ISymbol>eh_projectileHit</a></div></div><div class=SRResult id=SR_enabled><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/main/XEH_preInit-sqf.html#OCAP_enabled" target=_parent class=ISymbol>enabled</a></div></div><div class=SRResult id=SR_Ended><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_Ended" target=_parent class=ISymbol>Ended</a></div></div><div class=SRResult id=SR_EntityKilled><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_EntityKilled" target=_parent class=ISymbol>EntityKilled</a></div></div><div class=SRResult id=SR_entityMonitors><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_entityMonitors-sqf.html#OCAP_recorder_fnc_entityMonitors" target=_parent class=ISymbol>entityMonitors</a></div></div><div class=SRResult id=SR_entityMonitorsInitialized><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_entityMonitors-sqf.html#OCAP_entityMonitorsInitialized" target=_parent class=ISymbol>entityMonitorsInitialized</a></div></div><div class=SRResult id=SR_EntityRespawned><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_EntityRespawned" target=_parent class=ISymbol>EntityRespawned</a></div></div><div class=SRResult id=SR_Event_spcHandlers><div class=IEntry><a href="javascript:searchResults.Toggle('SR_Event_spcHandlers')" class=ISymbol>Event Handlers</a><div class=ISubIndex><a href="../files/recorder/fnc_addEventMission-sqf.html#Event_Handlers" target=_parent class=IFile>recorder\<wbr>fnc_addEventMission.sqf</a><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Event_Handlers" target=_parent class=IFile>recorder\<wbr>fnc_eh_firedMan.sqf</a><a href="../files/recorder/fnc_handleMarkers-sqf.html#Event_Handlers" target=_parent class=IFile>recorder\<wbr>fnc_handleMarkers.sqf</a></div></div></div><div class=SRResult id=SR_excludeClassFromRecord><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_excludeClassFromRecord" target=_parent class=ISymbol>excludeClassFromRecord</a></div></div><div class=SRResult id=SR_excludeKindFromRecord><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_excludeKindFromRecord" target=_parent class=ISymbol>excludeKindFromRecord</a></div></div><div class=SRResult id=SR_excludeMarkerFromRecord><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_excludeMarkerFromRecord" target=_parent class=ISymbol>excludeMarkerFromRecord</a></div></div><div class=SRResult id=SR_Exclusions><div class=IEntry><a href="../files/recorder/XEH_preInit-sqf.html#Exclusions" target=_parent class=ISymbol>Exclusions</a></div></div><div class=SRResult id=SR_Explode><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Explode" target=_parent class=ISymbol>Explode</a></div></div><div class=SRResult id=SR_exportData><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_exportData" target=_parent class=ISymbol>exportData</a></div></div><div class=SRResult id=SR2_exportData><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_exportData-sqf.html#OCAP_recorder_fnc_exportData" target=_parent class=ISymbol>exportData</a></div></div><div class=SRResult id=SR_Extra_spcTracking><div class=IEntry><a href="../files/recorder/XEH_preInit-sqf.html#Extra_Tracking" target=_parent class=ISymbol>Extra Tracking</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralF.html b/docs/search/GeneralF.html
    new file mode 100644
    index 0000000..5669192
    --- /dev/null
    +++ b/docs/search/GeneralF.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_fnc_undaceExplosives_persqf><div class=IEntry><a href="../files/recorder/fnc_aceExplosives-sqf.html#fnc_aceExplosives.sqf" target=_parent class=ISymbol>fnc_aceExplosives.sqf</a></div></div><div class=SRResult id=SR_fnc_undaddEventMission_persqf><div class=IEntry><a href="../files/recorder/fnc_addEventMission-sqf.html#fnc_addEventMission.sqf" target=_parent class=ISymbol>fnc_addEventMission.sqf</a></div></div><div class=SRResult id=SR_fnc_undaddUnitEventHandlers_persqf><div class=IEntry><a href="../files/recorder/fnc_addUnitEventHandlers-sqf.html#fnc_addUnitEventHandlers.sqf" target=_parent class=ISymbol>fnc_addUnitEventHandlers.sqf</a></div></div><div class=SRResult id=SR_fnc_undadminUIControl_persqf><div class=IEntry><a href="../files/recorder/fnc_adminUIcontrol-sqf.html#fnc_adminUIControl.sqf" target=_parent class=ISymbol>fnc_adminUIControl.sqf</a></div></div><div class=SRResult id=SR_fnc_undcaptureLoop_persqf><div class=IEntry><a href="../files/recorder/fnc_captureLoop-sqf.html#fnc_captureLoop.sqf" target=_parent class=ISymbol>fnc_captureLoop.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undconnected_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_connected-sqf.html#fnc_eh_connected.sqf" target=_parent class=ISymbol>fnc_eh_connected.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_unddisconnected_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_disconnected-sqf.html#fnc_eh_disconnected.sqf" target=_parent class=ISymbol>fnc_eh_disconnected.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undfiredMan_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#fnc_eh_firedMan.sqf" target=_parent class=ISymbol>fnc_eh_firedMan.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undkilled_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_killed-sqf.html#fnc_eh_killed.sqf" target=_parent class=ISymbol>fnc_eh_killed.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undonUserAdminStateChanged_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_onUserAdminStateChanged-sqf.html#fnc_eh_onUserAdminStateChanged.sqf" target=_parent class=ISymbol>fnc_eh_onUserAdminStateChanged.sqf</a></div></div><div class=SRResult id=SR_fnc_undeh_undprojectileHit_persqf><div class=IEntry><a href="../files/recorder/fnc_eh_projectileHit-sqf.html#fnc_eh_projectileHit.sqf" target=_parent class=ISymbol>fnc_eh_projectileHit.sqf</a></div></div><div class=SRResult id=SR_fnc_undentityMonitors_persqf><div class=IEntry><a href="../files/recorder/fnc_entityMonitors-sqf.html#fnc_entityMonitors.sqf" target=_parent class=ISymbol>fnc_entityMonitors.sqf</a></div></div><div class=SRResult id=SR_fnc_undexportData_persqf><div class=IEntry><a href="../files/recorder/fnc_exportData-sqf.html#fnc_exportData.sqf" target=_parent class=ISymbol>fnc_exportData.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetAmmoMarkerData_persqf><div class=IEntry><a href="../files/recorder/fnc_getAmmoMarkerData-sqf.html#fnc_getAmmoMarkerData.sqf" target=_parent class=ISymbol>fnc_getAmmoMarkerData.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetClass_persqf><div class=IEntry><a href="../files/recorder/fnc_getClass-sqf.html#fnc_getClass.sqf" target=_parent class=ISymbol>fnc_getClass.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetEventWeaponText_persqf><div class=IEntry><a href="../files/recorder/fnc_getEventWeaponText-sqf.html#fnc_getEventWeaponText.sqf" target=_parent class=ISymbol>fnc_getEventWeaponText.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetInstigator_persqf><div class=IEntry><a href="../files/recorder/fnc_getInstigator-sqf.html#fnc_getInstigator.sqf" target=_parent class=ISymbol>fnc_getInstigator.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetUnitType_persqf><div class=IEntry><a href="../files/recorder/fnc_getUnitType-sqf.html#fnc_getUnitType.sqf" target=_parent class=ISymbol>fnc_getUnitType.sqf</a></div></div><div class=SRResult id=SR_fnc_undgetWeaponDisplayData_persqf><div class=IEntry><a href="../files/recorder/fnc_getWeaponDisplayData-sqf.html#fnc_getWeaponDisplayData.sqf" target=_parent class=ISymbol>fnc_getWeaponDisplayData.sqf</a></div></div><div class=SRResult id=SR_fnc_undhandleCustomEvent_persqf><div class=IEntry><a href="../files/recorder/fnc_handleCustomEvent-sqf.html#fnc_handleCustomEvent.sqf" target=_parent class=ISymbol>fnc_handleCustomEvent.sqf</a></div></div><div class=SRResult id=SR_fnc_undhandleMarkers_persqf><div class=IEntry><a href="../files/recorder/fnc_handleMarkers-sqf.html#fnc_handleMarkers.sqf" target=_parent class=ISymbol>fnc_handleMarkers.sqf</a></div></div><div class=SRResult id=SR_fnc_undinit_persqf><div class=IEntry><a href="../files/recorder/fnc_init-sqf.html#fnc_init.sqf" target=_parent class=ISymbol>fnc_init.sqf</a></div></div><div class=SRResult id=SR_fnc_undisKindOfApc_persqf><div class=IEntry><a href="../files/recorder/fnc_isKindOfApc-sqf.html#fnc_isKindOfApc.sqf" target=_parent class=ISymbol>fnc_isKindOfApc.sqf</a></div></div><div class=SRResult id=SR_fnc_undprojectileMonitors_persqf><div class=IEntry><a href="../files/recorder/fnc_projectileMonitors-sqf.html#fnc_projectileMonitors.sqf" target=_parent class=ISymbol>fnc_projectileMonitors.sqf</a></div></div><div class=SRResult id=SR_fnc_undsendData_persqf><div class=IEntry><a href="../files/extension/fnc_sendData-sqf.html#fnc_sendData.sqf" target=_parent class=ISymbol>fnc_sendData.sqf</a></div></div><div class=SRResult id=SR_fnc_undstartRecording_persqf><div class=IEntry><a href="../files/recorder/fnc_startRecording-sqf.html#fnc_startRecording.sqf" target=_parent class=ISymbol>fnc_startRecording.sqf</a></div></div><div class=SRResult id=SR_fnc_undstopRecording_persqf><div class=IEntry><a href="../files/recorder/fnc_stopRecording-sqf.html#fnc_stopRecording.sqf" target=_parent class=ISymbol>fnc_stopRecording.sqf</a></div></div><div class=SRResult id=SR_fnc_undupdateTime_persqf><div class=IEntry><a href="../files/recorder/fnc_updateTime-sqf.html#fnc_updateTime.sqf" target=_parent class=ISymbol>fnc_updateTime.sqf</a></div></div><div class=SRResult id=SR_frameCaptureDelay><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_frameCaptureDelay" target=_parent class=ISymbol>frameCaptureDelay</a></div></div><div class=SRResult id=SR2_frameCaptureDelay><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_frameCaptureDelay" target=_parent class=ISymbol>frameCaptureDelay</a></div></div><div class=SRResult id=SR_Functions><div class=IEntry><a href="javascript:searchResults.Toggle('SR_Functions')" class=ISymbol>Functions</a><div class=ISubIndex><a href="../files/extension/fnc_sendData-sqf.html#Functions" target=_parent class=IFile>extension\<wbr>fnc_sendData.sqf</a><a href="../files/recorder/fnc_aceExplosives-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_aceExplosives.sqf</a><a href="../files/recorder/fnc_addEventMission-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_addEventMission.sqf</a><a href="../files/recorder/fnc_addUnitEventHandlers-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_addUnitEventHandlers.sqf</a><a href="../files/recorder/fnc_adminUIcontrol-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_adminUIcontrol.sqf</a><a href="../files/recorder/fnc_captureLoop-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_captureLoop.sqf</a><a href="../files/recorder/fnc_eh_connected-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_eh_connected.sqf</a><a href="../files/recorder/fnc_eh_disconnected-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_eh_disconnected.sqf</a><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_eh_firedMan.sqf</a><a href="../files/recorder/fnc_eh_killed-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_eh_killed.sqf</a><a href="../files/recorder/fnc_eh_onUserAdminStateChanged-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_eh_onUserAdminStateChanged.sqf</a><a href="../files/recorder/fnc_eh_projectileHit-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_eh_projectileHit.sqf</a><a href="../files/recorder/fnc_entityMonitors-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_entityMonitors.sqf</a><a href="../files/recorder/fnc_exportData-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_exportData.sqf</a><a href="../files/recorder/fnc_getAmmoMarkerData-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_getAmmoMarkerData.sqf</a><a href="../files/recorder/fnc_getClass-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_getClass.sqf</a><a href="../files/recorder/fnc_getEventWeaponText-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_getEventWeaponText.sqf</a><a href="../files/recorder/fnc_getInstigator-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_getInstigator.sqf</a><a href="../files/recorder/fnc_getUnitType-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_getUnitType.sqf</a><a href="../files/recorder/fnc_getWeaponDisplayData-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_getWeaponDisplayData.sqf</a><a href="../files/recorder/fnc_handleCustomEvent-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_handleCustomEvent.sqf</a><a href="../files/recorder/fnc_handleMarkers-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_handleMarkers.sqf</a><a href="../files/recorder/fnc_init-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_init.sqf</a><a href="../files/recorder/fnc_isKindOfApc-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_isKindOfApc.sqf</a><a href="../files/recorder/fnc_projectileMonitors-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_projectileMonitors.sqf</a><a href="../files/recorder/fnc_startRecording-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_startRecording.sqf</a><a href="../files/recorder/fnc_stopRecording-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_stopRecording.sqf</a><a href="../files/recorder/fnc_updateTime-sqf.html#Functions" target=_parent class=IFile>recorder\<wbr>fnc_updateTime.sqf</a></div></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralG.html b/docs/search/GeneralG.html
    new file mode 100644
    index 0000000..491a410
    --- /dev/null
    +++ b/docs/search/GeneralG.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_getAmmoMarkerData><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getAmmoMarkerData-sqf.html#OCAP_recorder_fnc_getAmmoMarkerData" target=_parent class=ISymbol>getAmmoMarkerData</a></div></div><div class=SRResult id=SR_getClass><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getClass-sqf.html#OCAP_recorder_fnc_getClass" target=_parent class=ISymbol>getClass</a></div></div><div class=SRResult id=SR_getEventWeaponText><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getEventWeaponText-sqf.html#OCAP_recorder_fnc_getEventWeaponText" target=_parent class=ISymbol>getEventWeaponText</a></div></div><div class=SRResult id=SR_getInstigator><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getInstigator-sqf.html#OCAP_recorder_fnc_getInstigator" target=_parent class=ISymbol>getInstigator</a></div></div><div class=SRResult id=SR_getUnitType><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getUnitType-sqf.html#OCAP_recorder_fnc_getUnitType" target=_parent class=ISymbol>getUnitType</a></div></div><div class=SRResult id=SR_getWeaponDisplayData><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_getWeaponDisplayData-sqf.html#OCAP_recorder_fnc_getWeaponDisplayData" target=_parent class=ISymbol>getWeaponDisplayData</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralH.html b/docs/search/GeneralH.html
    new file mode 100644
    index 0000000..0f75ce0
    --- /dev/null
    +++ b/docs/search/GeneralH.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_handleCustomEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_handleCustomEvent-sqf.html#OCAP_recorder_fnc_handleCustomEvent" target=_parent class=ISymbol>handleCustomEvent</a></div></div><div class=SRResult id=SR_HandleDisconnect><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_HandleDisconnect" target=_parent class=ISymbol>HandleDisconnect</a></div></div><div class=SRResult id=SR_handleMarker><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_handleMarkers-sqf.html#OCAP_handleMarker" target=_parent class=ISymbol>handleMarker</a></div></div><div class=SRResult id=SR_handleMarkers><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_handleMarkers-sqf.html#OCAP_recorder_fnc_handleMarkers" target=_parent class=ISymbol>handleMarkers</a></div></div><div class=SRResult id=SR_hasAdminControls><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_adminUIcontrol-sqf.html#OCAP_hasAdminControls" target=_parent class=ISymbol>hasAdminControls</a></div></div><div class=SRResult id=SR_HitExplosion><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#HitExplosion" target=_parent class=ISymbol>HitExplosion</a></div></div><div class=SRResult id=SR_HitPart><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#HitPart" target=_parent class=ISymbol>HitPart</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralI.html b/docs/search/GeneralI.html
    new file mode 100644
    index 0000000..5c4261b
    --- /dev/null
    +++ b/docs/search/GeneralI.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_init><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_fnc_init" target=_parent class=ISymbol>init</a></div></div><div class=SRResult id=SR_isDebug><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/main/XEH_preInit-sqf.html#OCAP_isDebug" target=_parent class=ISymbol>isDebug</a></div></div><div class=SRResult id=SR_isKindOfApc><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_isKindOfApc-sqf.html#OCAP_recorder_fnc_isKindOfApc" target=_parent class=ISymbol>isKindOfApc</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralL.html b/docs/search/GeneralL.html
    new file mode 100644
    index 0000000..8248985
    --- /dev/null
    +++ b/docs/search/GeneralL.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_lastFired><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_eh_firedMan-sqf.html#OCAP_lastFired" target=_parent class=ISymbol>lastFired</a></div></div><div class=SRResult id=SR_listener_undaceExplosives><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_aceExplosives" target=_parent class=ISymbol>listener_aceExplosives</a></div></div><div class=SRResult id=SR_listener_undaceThrowing><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_aceThrowing" target=_parent class=ISymbol>listener_aceThrowing</a></div></div><div class=SRResult id=SR_listener_undcounterEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_counterEvent" target=_parent class=ISymbol>listener_counterEvent</a></div></div><div class=SRResult id=SR_listener_undcounterInit><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_counterInit" target=_parent class=ISymbol>listener_counterInit</a></div></div><div class=SRResult id=SR_listener_undcustomEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_customEvent" target=_parent class=ISymbol>listener_customEvent</a></div></div><div class=SRResult id=SR_listener_undexportData><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_exportData" target=_parent class=ISymbol>listener_exportData</a></div></div><div class=SRResult id=SR_listener_undmarkers><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_handleMarkers-sqf.html#OCAP_listener_markers" target=_parent class=ISymbol>listener_markers</a></div></div><div class=SRResult id=SR_listener_undpause><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_pause" target=_parent class=ISymbol>listener_pause</a></div></div><div class=SRResult id=SR_listener_undrecord><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_record" target=_parent class=ISymbol>listener_record</a></div></div><div class=SRResult id=SR_liveDebugBullets><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_projectileMonitors-sqf.html#OCAP_recorder_liveDebugBullets" target=_parent class=ISymbol>liveDebugBullets</a></div></div><div class=SRResult id=SR_liveDebugMagIcons><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_projectileMonitors-sqf.html#OCAP_recorder_liveDebugMagIcons" target=_parent class=ISymbol>liveDebugMagIcons</a></div></div><div class=SRResult id=SR_LOG><div class=IEntry><a href="../files/main/script_macros-hpp.html#LOG" target=_parent class=ISymbol>LOG</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralM.html b/docs/search/GeneralM.html
    new file mode 100644
    index 0000000..0dc7bbd
    --- /dev/null
    +++ b/docs/search/GeneralM.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Macros><div class=IEntry><a href="javascript:searchResults.Toggle('SR_Macros')" class=ISymbol>Macros</a><div class=ISubIndex><a href="../files/extension/script_component-hpp.html#Macros" target=_parent class=IFile>extension\<wbr>script_component.hpp</a><a href="../files/main/script_component-hpp.html#Macros" target=_parent class=IFile>main\<wbr>script_component.hpp</a><a href="../files/main/script_macros-hpp.html#Macros" target=_parent class=IFile>main\<wbr>script_macros.hpp</a><a href="../files/recorder/script_component-hpp.html#Macros" target=_parent class=IFile>recorder\<wbr>script_component.hpp</a></div></div></div><div class=SRResult id=SR_MarkerCreated><div class=IEntry><a href="../files/recorder/fnc_handleMarkers-sqf.html#MarkerCreated" target=_parent class=ISymbol>MarkerCreated</a></div></div><div class=SRResult id=SR_MarkerDeleted><div class=IEntry><a href="../files/recorder/fnc_handleMarkers-sqf.html#MarkerDeleted" target=_parent class=ISymbol>MarkerDeleted</a></div></div><div class=SRResult id=SR_MarkerUpdated><div class=IEntry><a href="../files/recorder/fnc_handleMarkers-sqf.html#MarkerUpdated" target=_parent class=ISymbol>MarkerUpdated</a></div></div><div class=SRResult id=SR_minMissionTime><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_minMissionTime" target=_parent class=ISymbol>minMissionTime</a></div></div><div class=SRResult id=SR2_minMissionTime><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_minMissionTime" target=_parent class=ISymbol>minMissionTime</a></div></div><div class=SRResult id=SR_minPlayerCount><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_minPlayerCount" target=_parent class=ISymbol>minPlayerCount</a></div></div><div class=SRResult id=SR_MPEnded><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_MPEnded" target=_parent class=ISymbol>MPEnded</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralN.html b/docs/search/GeneralN.html
    new file mode 100644
    index 0000000..e5e8dbd
    --- /dev/null
    +++ b/docs/search/GeneralN.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_nextId><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_nextId" target=_parent class=ISymbol>nextId</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralO.html b/docs/search/GeneralO.html
    new file mode 100644
    index 0000000..ca3ecb3
    --- /dev/null
    +++ b/docs/search/GeneralO.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_OnUserAdminStateChanged><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_OnUserAdminStateChanged" target=_parent class=ISymbol>OnUserAdminStateChanged</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralP.html b/docs/search/GeneralP.html
    new file mode 100644
    index 0000000..27d90a0
    --- /dev/null
    +++ b/docs/search/GeneralP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_pause><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_pause" target=_parent class=ISymbol>pause</a></div></div><div class=SRResult id=SR_PFHObject><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_captureLoop-sqf.html#OCAP_PFHObject" target=_parent class=ISymbol>PFHObject</a></div></div><div class=SRResult id=SR_PlayerConnected><div class=IEntry><span class=ISymbolPrefix>OCAP_EH_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_EH_PlayerConnected" target=_parent class=ISymbol>PlayerConnected</a></div></div><div class=SRResult id=SR_preferACEUnconscious><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_preferACEUnconscious" target=_parent class=ISymbol>preferACEUnconscious</a></div></div><div class=SRResult id=SR_PREFIX><div class=IEntry><a href="../files/main/script_macros-hpp.html#PREFIX" target=_parent class=ISymbol>PREFIX</a></div></div><div class=SRResult id=SR_projectileMonitors><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_projectileMonitors-sqf.html#OCAP_recorder_fnc_projectileMonitors" target=_parent class=ISymbol>projectileMonitors</a></div></div><div class=SRResult id=SR_Projectiles><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Projectiles" target=_parent class=ISymbol>Projectiles</a></div></div><div class=SRResult id=SR_Projectiles_lpaBullets_rpa><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Projectiles(Bullets)" target=_parent class=ISymbol>Projectiles(Bullets)</a></div></div><div class=SRResult id=SR_Projectiles_lpaNon_minBullets_rpa><div class=IEntry><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Projectiles(Non-Bullets)" target=_parent class=ISymbol>Projectiles(Non-Bullets)</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralR.html b/docs/search/GeneralR.html
    new file mode 100644
    index 0000000..726fc9d
    --- /dev/null
    +++ b/docs/search/GeneralR.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_record><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_record" target=_parent class=ISymbol>record</a></div></div><div class=SRResult id=SR_recording><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_recording" target=_parent class=ISymbol>recording</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralS.html b/docs/search/GeneralS.html
    new file mode 100644
    index 0000000..a646058
    --- /dev/null
    +++ b/docs/search/GeneralS.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Save_slaExport_spcSettings><div class=IEntry><a href="../files/recorder/XEH_preInit-sqf.html#Save/Export_Settings" target=_parent class=ISymbol>Save/<wbr>Export Settings</a></div></div><div class=SRResult id=SR_saveMissionEnded><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_saveMissionEnded" target=_parent class=ISymbol>saveMissionEnded</a></div></div><div class=SRResult id=SR_saveOnEmpty><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_saveOnEmpty" target=_parent class=ISymbol>saveOnEmpty</a></div></div><div class=SRResult id=SR_saveTag><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_saveTag" target=_parent class=ISymbol>saveTag</a></div></div><div class=SRResult id=SR_script_undcomponent_perhpp><div class=IEntry><a href="javascript:searchResults.Toggle('SR_script_undcomponent_perhpp')" class=ISymbol>script_component.hpp</a><div class=ISubIndex><a href="../files/extension/script_component-hpp.html#script_component.hpp" target=_parent class=IFile>extension\<wbr>script_component.hpp</a><a href="../files/main/script_component-hpp.html#script_component.hpp" target=_parent class=IFile>main\<wbr>script_component.hpp</a><a href="../files/recorder/script_component-hpp.html#script_component.hpp" target=_parent class=IFile>recorder\<wbr>script_component.hpp</a></div></div></div><div class=SRResult id=SR_script_undmacros_perhpp><div class=IEntry><a href="../files/main/script_macros-hpp.html#script_macros.hpp" target=_parent class=ISymbol>script_macros.hpp</a></div></div><div class=SRResult id=SR_sendData><div class=IEntry><span class=ISymbolPrefix>OCAP_extension_fnc_</span><a href="../files/extension/fnc_sendData-sqf.html#OCAP_extension_fnc_sendData" target=_parent class=ISymbol>sendData</a></div></div><div class=SRResult id=SR_SHOULDSAVEEVENTS><div class=IEntry><a href="../files/main/script_macros-hpp.html#SHOULDSAVEEVENTS" target=_parent class=ISymbol>SHOULDSAVEEVENTS</a></div></div><div class=SRResult id=SR_startRecording><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_startRecording-sqf.html#OCAP_recorder_fnc_startRecording" target=_parent class=ISymbol>startRecording</a></div></div><div class=SRResult id=SR_stopRecording><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_stopRecording-sqf.html#OCAP_recorder_fnc_stopRecording" target=_parent class=ISymbol>stopRecording</a></div></div><div class=SRResult id=SR_SYSCHAT><div class=IEntry><a href="../files/main/script_macros-hpp.html#SYSCHAT" target=_parent class=ISymbol>SYSCHAT</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralT.html b/docs/search/GeneralT.html
    new file mode 100644
    index 0000000..70ee5ca
    --- /dev/null
    +++ b/docs/search/GeneralT.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_trackedMarkers><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_handleMarkers-sqf.html#OCAP_recorder_trackedMarkers" target=_parent class=ISymbol>trackedMarkers</a></div></div><div class=SRResult id=SR_trackTickets><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_trackTickets" target=_parent class=ISymbol>trackTickets</a></div></div><div class=SRResult id=SR_trackTimeInterval><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_trackTimeInterval" target=_parent class=ISymbol>trackTimeInterval</a></div></div><div class=SRResult id=SR_trackTimes><div class=IEntry><span class=ISymbolPrefix>OCAP_settings_</span><a href="../files/recorder/XEH_preInit-sqf.html#OCAP_settings_trackTimes" target=_parent class=ISymbol>trackTimes</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralU.html b/docs/search/GeneralU.html
    new file mode 100644
    index 0000000..27bf0df
    --- /dev/null
    +++ b/docs/search/GeneralU.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_updateTime><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_fnc_</span><a href="../files/recorder/fnc_updateTime-sqf.html#OCAP_recorder_fnc_updateTime" target=_parent class=ISymbol>updateTime</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/GeneralV.html b/docs/search/GeneralV.html
    new file mode 100644
    index 0000000..30ce1a1
    --- /dev/null
    +++ b/docs/search/GeneralV.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Variables><div class=IEntry><a href="javascript:searchResults.Toggle('SR_Variables')" class=ISymbol>Variables</a><div class=ISubIndex><a href="../files/recorder/fnc_addEventMission-sqf.html#Variables" target=_parent class=IFile>recorder\<wbr>fnc_addEventMission.sqf</a><a href="../files/recorder/fnc_adminUIcontrol-sqf.html#Variables" target=_parent class=IFile>recorder\<wbr>fnc_adminUIcontrol.sqf</a><a href="../files/recorder/fnc_captureLoop-sqf.html#Variables" target=_parent class=IFile>recorder\<wbr>fnc_captureLoop.sqf</a><a href="../files/recorder/fnc_eh_firedMan-sqf.html#Variables" target=_parent class=IFile>recorder\<wbr>fnc_eh_firedMan.sqf</a><a href="../files/recorder/fnc_entityMonitors-sqf.html#Variables" target=_parent class=IFile>recorder\<wbr>fnc_entityMonitors.sqf</a><a href="../files/recorder/fnc_handleMarkers-sqf.html#Variables" target=_parent class=IFile>recorder\<wbr>fnc_handleMarkers.sqf</a><a href="../files/recorder/fnc_init-sqf.html#Variables" target=_parent class=IFile>recorder\<wbr>fnc_init.sqf</a><a href="../files/recorder/fnc_projectileMonitors-sqf.html#Variables" target=_parent class=IFile>recorder\<wbr>fnc_projectileMonitors.sqf</a></div></div></div><div class=SRResult id=SR_version><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_version" target=_parent class=ISymbol>version</a></div></div><div class=SRResult id=SR2_version><div class=IEntry><span class=ISymbolPrefix>OCAP_extension_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_extension_version" target=_parent class=ISymbol>version</a></div></div><div class=SRResult id=SR3_VERSION><div class=IEntry><a href="../files/main/script_macros-hpp.html#VERSION" target=_parent class=ISymbol>VERSION</a></div></div><div class=SRResult id=SR_VERSION_undAR><div class=IEntry><a href="../files/main/script_macros-hpp.html#VERSION_AR" target=_parent class=ISymbol>VERSION_AR</a></div></div><div class=SRResult id=SR_VERSION_undREQUIRED><div class=IEntry><a href="../files/main/script_macros-hpp.html#VERSION_REQUIRED" target=_parent class=ISymbol>VERSION_REQUIRED</a></div></div><div class=SRResult id=SR_VERSION_undSTR><div class=IEntry><a href="../files/main/script_macros-hpp.html#VERSION_STR" target=_parent class=ISymbol>VERSION_STR</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/MacrosA.html b/docs/search/MacrosA.html
    new file mode 100644
    index 0000000..e55ee53
    --- /dev/null
    +++ b/docs/search/MacrosA.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_ADDON><div class=IEntry><a href="../files/main/script_macros-hpp.html#ADDON" target=_parent class=ISymbol>ADDON</a></div></div><div class=SRResult id=SR_ARR2><div class=IEntry><a href="../files/main/script_macros-hpp.html#ARR2" target=_parent class=ISymbol>ARR2</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/MacrosB.html b/docs/search/MacrosB.html
    new file mode 100644
    index 0000000..5e160dc
    --- /dev/null
    +++ b/docs/search/MacrosB.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_BOOL><div class=IEntry><a href="../files/main/script_macros-hpp.html#BOOL" target=_parent class=ISymbol>BOOL</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/MacrosC.html b/docs/search/MacrosC.html
    new file mode 100644
    index 0000000..f11af39
    --- /dev/null
    +++ b/docs/search/MacrosC.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_COMPONENT><div class=IEntry><a href="javascript:searchResults.Toggle('SR_COMPONENT')" class=ISymbol>COMPONENT</a><div class=ISubIndex><a href="../files/extension/script_component-hpp.html#COMPONENT" target=_parent class=IFile>extension\<wbr>script_component.hpp</a><a href="../files/main/script_component-hpp.html#COMPONENT" target=_parent class=IFile>main\<wbr>script_component.hpp</a><a href="../files/recorder/script_component-hpp.html#COMPONENT" target=_parent class=IFile>recorder\<wbr>script_component.hpp</a></div></div></div><div class=SRResult id=SR_COMPONENT_undBEAUTIFIED><div class=IEntry><a href="javascript:searchResults.Toggle('SR_COMPONENT_undBEAUTIFIED')" class=ISymbol>COMPONENT_BEAUTIFIED</a><div class=ISubIndex><a href="../files/extension/script_component-hpp.html#COMPONENT_BEAUTIFIED" target=_parent class=IFile>extension\<wbr>script_component.hpp</a><a href="../files/main/script_component-hpp.html#COMPONENT_BEAUTIFIED" target=_parent class=IFile>main\<wbr>script_component.hpp</a><a href="../files/recorder/script_component-hpp.html#COMPONENT_BEAUTIFIED" target=_parent class=IFile>recorder\<wbr>script_component.hpp</a></div></div></div><div class=SRResult id=SR_COMPONENT_undNAME><div class=IEntry><a href="../files/main/script_macros-hpp.html#COMPONENT_NAME" target=_parent class=ISymbol>COMPONENT_NAME</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/MacrosL.html b/docs/search/MacrosL.html
    new file mode 100644
    index 0000000..8b1106b
    --- /dev/null
    +++ b/docs/search/MacrosL.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_LOG><div class=IEntry><a href="../files/main/script_macros-hpp.html#LOG" target=_parent class=ISymbol>LOG</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/MacrosP.html b/docs/search/MacrosP.html
    new file mode 100644
    index 0000000..5455079
    --- /dev/null
    +++ b/docs/search/MacrosP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_PREFIX><div class=IEntry><a href="../files/main/script_macros-hpp.html#PREFIX" target=_parent class=ISymbol>PREFIX</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/MacrosS.html b/docs/search/MacrosS.html
    new file mode 100644
    index 0000000..b190758
    --- /dev/null
    +++ b/docs/search/MacrosS.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_SHOULDSAVEEVENTS><div class=IEntry><a href="../files/main/script_macros-hpp.html#SHOULDSAVEEVENTS" target=_parent class=ISymbol>SHOULDSAVEEVENTS</a></div></div><div class=SRResult id=SR_SYSCHAT><div class=IEntry><a href="../files/main/script_macros-hpp.html#SYSCHAT" target=_parent class=ISymbol>SYSCHAT</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/MacrosV.html b/docs/search/MacrosV.html
    new file mode 100644
    index 0000000..8545d0c
    --- /dev/null
    +++ b/docs/search/MacrosV.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_VERSION><div class=IEntry><a href="../files/main/script_macros-hpp.html#VERSION" target=_parent class=ISymbol>VERSION</a></div></div><div class=SRResult id=SR_VERSION_undAR><div class=IEntry><a href="../files/main/script_macros-hpp.html#VERSION_AR" target=_parent class=ISymbol>VERSION_AR</a></div></div><div class=SRResult id=SR_VERSION_undREQUIRED><div class=IEntry><a href="../files/main/script_macros-hpp.html#VERSION_REQUIRED" target=_parent class=ISymbol>VERSION_REQUIRED</a></div></div><div class=SRResult id=SR_VERSION_undSTR><div class=IEntry><a href="../files/main/script_macros-hpp.html#VERSION_STR" target=_parent class=ISymbol>VERSION_STR</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/NoResults.html b/docs/search/NoResults.html
    new file mode 100644
    index 0000000..8c72496
    --- /dev/null
    +++ b/docs/search/NoResults.html
    @@ -0,0 +1,15 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=NoMatches>No Matches</div></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesA.html b/docs/search/VariablesA.html
    new file mode 100644
    index 0000000..c2d4197
    --- /dev/null
    +++ b/docs/search/VariablesA.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_autoStart><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_autoStart" target=_parent class=ISymbol>autoStart</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesC.html b/docs/search/VariablesC.html
    new file mode 100644
    index 0000000..a8cf1b8
    --- /dev/null
    +++ b/docs/search/VariablesC.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_captureFrameNo><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_captureFrameNo" target=_parent class=ISymbol>captureFrameNo</a></div></div><div class=SRResult id=SR_CBA_spcListener_spcHandles><div class=IEntry><a href="../files/recorder/fnc_addEventMission-sqf.html#CBA_Listener_Handles" target=_parent class=ISymbol>CBA Listener Handles</a></div></div><div class=SRResult id=SR_counter_undsides><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_counter_sides" target=_parent class=ISymbol>counter_sides</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesE.html b/docs/search/VariablesE.html
    new file mode 100644
    index 0000000..95f50d7
    --- /dev/null
    +++ b/docs/search/VariablesE.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_entityMonitorsInitialized><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_entityMonitors-sqf.html#OCAP_entityMonitorsInitialized" target=_parent class=ISymbol>entityMonitorsInitialized</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesF.html b/docs/search/VariablesF.html
    new file mode 100644
    index 0000000..296f619
    --- /dev/null
    +++ b/docs/search/VariablesF.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_frameCaptureDelay><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_frameCaptureDelay" target=_parent class=ISymbol>frameCaptureDelay</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesH.html b/docs/search/VariablesH.html
    new file mode 100644
    index 0000000..2f627fa
    --- /dev/null
    +++ b/docs/search/VariablesH.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_hasAdminControls><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_adminUIcontrol-sqf.html#OCAP_hasAdminControls" target=_parent class=ISymbol>hasAdminControls</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesL.html b/docs/search/VariablesL.html
    new file mode 100644
    index 0000000..e4738aa
    --- /dev/null
    +++ b/docs/search/VariablesL.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_lastFired><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_eh_firedMan-sqf.html#OCAP_lastFired" target=_parent class=ISymbol>lastFired</a></div></div><div class=SRResult id=SR_listener_undaceExplosives><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_aceExplosives" target=_parent class=ISymbol>listener_aceExplosives</a></div></div><div class=SRResult id=SR_listener_undaceThrowing><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_aceThrowing" target=_parent class=ISymbol>listener_aceThrowing</a></div></div><div class=SRResult id=SR_listener_undcounterEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_counterEvent" target=_parent class=ISymbol>listener_counterEvent</a></div></div><div class=SRResult id=SR_listener_undcounterInit><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_counterInit" target=_parent class=ISymbol>listener_counterInit</a></div></div><div class=SRResult id=SR_listener_undcustomEvent><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_customEvent" target=_parent class=ISymbol>listener_customEvent</a></div></div><div class=SRResult id=SR_listener_undexportData><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_exportData" target=_parent class=ISymbol>listener_exportData</a></div></div><div class=SRResult id=SR_listener_undmarkers><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_handleMarkers-sqf.html#OCAP_listener_markers" target=_parent class=ISymbol>listener_markers</a></div></div><div class=SRResult id=SR_listener_undpause><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_pause" target=_parent class=ISymbol>listener_pause</a></div></div><div class=SRResult id=SR_listener_undrecord><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_addEventMission-sqf.html#OCAP_listener_record" target=_parent class=ISymbol>listener_record</a></div></div><div class=SRResult id=SR_liveDebugBullets><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_projectileMonitors-sqf.html#OCAP_recorder_liveDebugBullets" target=_parent class=ISymbol>liveDebugBullets</a></div></div><div class=SRResult id=SR_liveDebugMagIcons><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_projectileMonitors-sqf.html#OCAP_recorder_liveDebugMagIcons" target=_parent class=ISymbol>liveDebugMagIcons</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesM.html b/docs/search/VariablesM.html
    new file mode 100644
    index 0000000..359cdbc
    --- /dev/null
    +++ b/docs/search/VariablesM.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_minMissionTime><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_minMissionTime" target=_parent class=ISymbol>minMissionTime</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesN.html b/docs/search/VariablesN.html
    new file mode 100644
    index 0000000..e5e8dbd
    --- /dev/null
    +++ b/docs/search/VariablesN.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_nextId><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_nextId" target=_parent class=ISymbol>nextId</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesP.html b/docs/search/VariablesP.html
    new file mode 100644
    index 0000000..03e9a32
    --- /dev/null
    +++ b/docs/search/VariablesP.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_PFHObject><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_captureLoop-sqf.html#OCAP_PFHObject" target=_parent class=ISymbol>PFHObject</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesR.html b/docs/search/VariablesR.html
    new file mode 100644
    index 0000000..1d01ef7
    --- /dev/null
    +++ b/docs/search/VariablesR.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_recording><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_recorder_recording" target=_parent class=ISymbol>recording</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesT.html b/docs/search/VariablesT.html
    new file mode 100644
    index 0000000..c71baa6
    --- /dev/null
    +++ b/docs/search/VariablesT.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_trackedMarkers><div class=IEntry><span class=ISymbolPrefix>OCAP_recorder_</span><a href="../files/recorder/fnc_handleMarkers-sqf.html#OCAP_recorder_trackedMarkers" target=_parent class=ISymbol>trackedMarkers</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/search/VariablesV.html b/docs/search/VariablesV.html
    new file mode 100644
    index 0000000..465cc3f
    --- /dev/null
    +++ b/docs/search/VariablesV.html
    @@ -0,0 +1,20 @@
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    +
    +<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
    +if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
    +
    +<!--  Generated by Natural Docs, version 1.52 -->
    +<!--  http://www.naturaldocs.org  -->
    +
    +<!-- saved from url=(0026)http://www.naturaldocs.org -->
    +
    +
    +
    +
    +<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_version><div class=IEntry><span class=ISymbolPrefix>OCAP_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_version" target=_parent class=ISymbol>version</a></div></div><div class=SRResult id=SR2_version><div class=IEntry><span class=ISymbolPrefix>OCAP_extension_</span><a href="../files/recorder/fnc_init-sqf.html#OCAP_extension_version" target=_parent class=ISymbol>version</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
    +document.getElementById("Loading").style.display="none";
    +document.getElementById("NoMatches").style.display="none";
    +var searchResults = new SearchResults("searchResults", "HTML");
    +searchResults.Search();
    +--></script></div><script language=JavaScript><!--
    +if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
    \ No newline at end of file
    diff --git a/docs/styles/main.css b/docs/styles/main.css
    new file mode 100644
    index 0000000..b769e5f
    --- /dev/null
    +++ b/docs/styles/main.css
    @@ -0,0 +1,828 @@
    +/*
    +   IMPORTANT: If you're editing this file in the output directory of one of
    +   your projects, your changes will be overwritten the next time you run
    +   Natural Docs.  Instead, copy this file to your project directory, make your
    +   changes, and you can use it with -s.  Even better would be to make a CSS
    +   file in your project directory with only your changes, which you can then
    +   use with -s [original style] [your changes].
    +
    +   On the other hand, if you're editing this file in the Natural Docs styles
    +   directory, the changes will automatically be applied to all your projects
    +   that use this style the next time Natural Docs is run on them.
    +
    +   This file is part of Natural Docs, which is Copyright  2003-2010 Greg Valure.
    +   Natural Docs is licensed under version 3 of the GNU Affero General Public
    +   License (AGPL).  Refer to License.txt for the complete details.
    +
    +   This file may be distributed with documentation files generated by Natural Docs.
    +   Such documentation is not covered by Natural Docs' copyright and licensing,
    +   and may have its own copyright and distribution terms as decided by its author.
    +*/
    +
    +body {
    +    font: 10pt Verdana, Arial, sans-serif;
    +    color: #000000;
    +    margin: 0; padding: 0;
    +    }
    +
    +.ContentPage,
    +.IndexPage,
    +.FramedMenuPage {
    +    background-color: #E8E8E8;
    +    }
    +.FramedContentPage,
    +.FramedIndexPage,
    +.FramedSearchResultsPage,
    +.PopupSearchResultsPage {
    +    background-color: #FFFFFF;
    +    }
    +
    +
    +a:link,
    +a:visited { color: #900000; text-decoration: none }
    +a:hover { color: #900000; text-decoration: underline }
    +a:active { color: #FF0000; text-decoration: underline }
    +
    +td {
    +    vertical-align: top }
    +
    +img { border: 0;  }
    +
    +
    +/*
    +    Comment out this line to use web-style paragraphs (blank line between
    +    paragraphs, no indent) instead of print-style paragraphs (no blank line,
    +    indented.)
    +*/
    +p {
    +    text-indent: 5ex; margin: 0 }
    +
    +
    +/*  Opera doesn't break with just wbr, but will if you add this.  */
    +.Opera wbr:after {
    +	content: "\00200B";
    +	}
    +
    +
    +/*  Blockquotes are used as containers for things that may need to scroll.  */
    +blockquote {
    +    padding: 0;
    +    margin: 0;
    +    overflow: auto;
    +    }
    +
    +
    +.Firefox1 blockquote {
    +    padding-bottom: .5em;
    +    }
    +
    +/*  Turn off scrolling when printing.  */
    +@media print {
    +    blockquote {
    +        overflow: visible;
    +        }
    +    .IE blockquote {
    +        width: auto;
    +        }
    +    }
    +
    +
    +
    +#Menu {
    +    font-size: 9pt;
    +    padding: 10px 0 0 0;
    +    }
    +.ContentPage #Menu,
    +.IndexPage #Menu {
    +    position: absolute;
    +    top: 0;
    +    left: 0;
    +    width: 31ex;
    +    overflow: hidden;
    +    }
    +.ContentPage .Firefox #Menu,
    +.IndexPage .Firefox #Menu {
    +    width: 27ex;
    +    }
    +
    +
    +    .MTitle {
    +        font-size: 16pt; font-weight: bold; font-variant: small-caps;
    +        text-align: center;
    +        padding: 5px 10px 15px 10px;
    +        border-bottom: 1px dotted #000000;
    +        margin-bottom: 15px }
    +
    +    .MSubTitle {
    +        font-size: 9pt; font-weight: normal; font-variant: normal;
    +        margin-top: 1ex; margin-bottom: 5px }
    +
    +
    +    .MEntry a:link,
    +    .MEntry a:hover,
    +    .MEntry a:visited { color: #606060; margin-right: 0 }
    +    .MEntry a:active { color: #A00000; margin-right: 0 }
    +
    +
    +    .MGroup {
    +        font-variant: small-caps; font-weight: bold;
    +        margin: 1em 0 1em 10px;
    +        }
    +
    +    .MGroupContent {
    +        font-variant: normal; font-weight: normal }
    +
    +    .MGroup a:link,
    +    .MGroup a:hover,
    +    .MGroup a:visited { color: #545454; margin-right: 10px }
    +    .MGroup a:active { color: #A00000; margin-right: 10px }
    +
    +
    +    .MFile,
    +    .MText,
    +    .MLink,
    +    .MIndex {
    +        padding: 1px 17px 2px 10px;
    +        margin: .25em 0 .25em 0;
    +        }
    +
    +    .MText {
    +        font-size: 8pt; font-style: italic }
    +
    +    .MLink {
    +        font-style: italic }
    +
    +    #MSelected {
    +        color: #000000; background-color: #FFFFFF;
    +        /*  Replace padding with border.  */
    +        padding: 0 10px 0 10px;
    +        border-width: 1px 2px 2px 0; border-style: solid; border-color: #000000;
    +        margin-right: 5px;
    +        }
    +
    +    /*  Close off the left side when its in a group.  */
    +    .MGroup #MSelected {
    +        padding-left: 9px; border-left-width: 1px }
    +
    +    /*  A treat for Mozilla users.  Blatantly non-standard.  Will be replaced with CSS 3 attributes when finalized/supported.  */
    +    .Firefox #MSelected {
    +        -moz-border-radius-topright: 10px;
    +        -moz-border-radius-bottomright: 10px }
    +    .Firefox .MGroup #MSelected {
    +        -moz-border-radius-topleft: 10px;
    +        -moz-border-radius-bottomleft: 10px }
    +
    +
    +    #MSearchPanel {
    +        padding: 0px 6px;
    +        margin: .25em 0;
    +        }
    +
    +
    +    #MSearchField {
    +        font: italic 9pt Verdana, sans-serif;
    +        color: #606060;
    +        background-color: #E8E8E8;
    +        border: none;
    +        padding: 2px 4px;
    +        width: 100%;
    +        }
    +    /* Only Opera gets it right. */
    +    .Firefox #MSearchField,
    +    .IE #MSearchField,
    +    .Safari #MSearchField {
    +        width: 94%;
    +        }
    +    .Opera9 #MSearchField,
    +    .Konqueror #MSearchField {
    +        width: 97%;
    +        }
    +    .FramedMenuPage .Firefox #MSearchField,
    +    .FramedMenuPage .Safari #MSearchField,
    +    .FramedMenuPage .Konqueror #MSearchField {
    +        width: 98%;
    +        }
    +
    +    /* Firefox doesn't do this right in frames without #MSearchPanel added on.
    +        It's presence doesn't hurt anything other browsers. */
    +    #MSearchPanel.MSearchPanelInactive:hover #MSearchField {
    +        background-color: #FFFFFF;
    +        border: 1px solid #C0C0C0;
    +        padding: 1px 3px;
    +        }
    +    .MSearchPanelActive #MSearchField {
    +        background-color: #FFFFFF;
    +        border: 1px solid #C0C0C0;
    +        font-style: normal;
    +        padding: 1px 3px;
    +        }
    +
    +    #MSearchType {
    +        visibility: hidden;
    +        font: 8pt Verdana, sans-serif;
    +        width: 98%;
    +        padding: 0;
    +        border: 1px solid #C0C0C0;
    +        }
    +    .MSearchPanelActive #MSearchType,
    +    /*  As mentioned above, Firefox doesn't do this right in frames without #MSearchPanel added on. */
    +    #MSearchPanel.MSearchPanelInactive:hover #MSearchType,
    +    #MSearchType:focus {
    +        visibility: visible;
    +        color: #606060;
    +        }
    +    #MSearchType option#MSearchEverything {
    +        font-weight: bold;
    +        }
    +
    +    .Opera8 .MSearchPanelInactive:hover,
    +    .Opera8 .MSearchPanelActive {
    +        margin-left: -1px;
    +        }
    +
    +
    +    iframe#MSearchResults {
    +        width: 60ex;
    +        height: 15em;
    +        }
    +    #MSearchResultsWindow {
    +        display: none;
    +        position: absolute;
    +        left: 0; top: 0;
    +        border: 1px solid #000000;
    +        background-color: #E8E8E8;
    +        }
    +    #MSearchResultsWindowClose {
    +        font-weight: bold;
    +        font-size: 8pt;
    +        display: block;
    +        padding: 2px 5px;
    +        }
    +    #MSearchResultsWindowClose:link,
    +    #MSearchResultsWindowClose:visited {
    +        color: #000000;
    +        text-decoration: none;
    +        }
    +    #MSearchResultsWindowClose:active,
    +    #MSearchResultsWindowClose:hover {
    +        color: #800000;
    +        text-decoration: none;
    +        background-color: #F4F4F4;
    +        }
    +
    +
    +
    +
    +#Content {
    +    padding-bottom: 15px;
    +    }
    +
    +.ContentPage #Content {
    +    border-width: 0 0 1px 1px;
    +    border-style: solid;
    +    border-color: #000000;
    +    background-color: #FFFFFF;
    +    font-size: 9pt;  /* To make 31ex match the menu's 31ex. */
    +    margin-left: 31ex;
    +    }
    +.ContentPage .Firefox #Content {
    +    margin-left: 27ex;
    +    }
    +
    +
    +
    +    .CTopic {
    +        font-size: 10pt;
    +        margin-bottom: 3em;
    +        }
    +
    +
    +    .CTitle {
    +        font-size: 12pt; font-weight: bold;
    +        border-width: 0 0 1px 0; border-style: solid; border-color: #A0A0A0;
    +        margin: 0 15px .5em 15px }
    +
    +    .CGroup .CTitle {
    +        font-size: 16pt; font-variant: small-caps;
    +        padding-left: 15px; padding-right: 15px;
    +        border-width: 0 0 2px 0; border-color: #000000;
    +        margin-left: 0; margin-right: 0 }
    +
    +    .CClass .CTitle,
    +    .CInterface .CTitle,
    +    .CDatabase .CTitle,
    +    .CDatabaseTable .CTitle,
    +    .CSection .CTitle {
    +        font-size: 18pt;
    +        color: #FFFFFF; background-color: #A0A0A0;
    +        padding: 10px 15px 10px 15px;
    +        border-width: 2px 0; border-color: #000000;
    +        margin-left: 0; margin-right: 0 }
    +
    +    #MainTopic .CTitle {
    +        font-size: 20pt;
    +        color: #FFFFFF; background-color: #7070C0;
    +        padding: 10px 15px 10px 15px;
    +        border-width: 0 0 3px 0; border-color: #000000;
    +        margin-left: 0; margin-right: 0 }
    +
    +    .CBody {
    +        margin-left: 15px; margin-right: 15px }
    +
    +
    +    .CToolTip {
    +        position: absolute; visibility: hidden;
    +        left: 0; top: 0;
    +        background-color: #FFFFE0;
    +        padding: 5px;
    +        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #000000;
    +        font-size: 8pt;
    +        }
    +
    +    .Opera .CToolTip {
    +        max-width: 98%;
    +        }
    +
    +    /*  Scrollbars would be useless.  */
    +    .CToolTip blockquote {
    +        overflow: hidden;
    +        }
    +    .IE6 .CToolTip blockquote {
    +        overflow: visible;
    +        }
    +
    +    .CHeading {
    +        font-weight: bold; font-size: 10pt;
    +        margin: 1.5em 0 .5em 0;
    +        }
    +
    +    .CBody pre {
    +        font: 10pt "Courier New", Courier, monospace;
    +	    background-color: #FCFCFC;
    +	    margin: 1em 35px;
    +	    padding: 10px 15px 10px 10px;
    +	    border-color: #E0E0E0 #E0E0E0 #E0E0E0 #E4E4E4;
    +	    border-width: 1px 1px 1px 6px;
    +	    border-style: dashed dashed dashed solid;
    +        }
    +
    +    .CBody ul {
    +        /*  I don't know why CBody's margin doesn't apply, but it's consistent across browsers so whatever.
    +             Reapply it here as padding.  */
    +        padding-left: 15px; padding-right: 15px;
    +        margin: .5em 5ex .5em 5ex;
    +        }
    +
    +    .CDescriptionList {
    +        margin: .5em 5ex 0 5ex }
    +
    +        .CDLEntry {
    +            font: 10pt "Courier New", Courier, monospace; color: #808080;
    +            padding-bottom: .25em;
    +            white-space: nowrap }
    +
    +        .CDLDescription {
    +            font-size: 10pt;  /*  For browsers that don't inherit correctly, like Opera 5.  */
    +            padding-bottom: .5em; padding-left: 5ex }
    +
    +
    +    .CTopic img {
    +        text-align: center;
    +        display: block;
    +        margin: 1em auto;
    +        }
    +    .CImageCaption {
    +        font-variant: small-caps;
    +        font-size: 8pt;
    +        color: #808080;
    +        text-align: center;
    +        position: relative;
    +        top: 1em;
    +        }
    +
    +    .CImageLink {
    +        color: #808080;
    +        font-style: italic;
    +        }
    +    a.CImageLink:link,
    +    a.CImageLink:visited,
    +    a.CImageLink:hover { color: #808080 }
    +
    +
    +
    +
    +
    +.Prototype {
    +    font: 10pt "Courier New", Courier, monospace;
    +    padding: 5px 3ex;
    +    border-width: 1px; border-style: solid;
    +    margin: 0 5ex 1.5em 5ex;
    +    }
    +
    +    .Prototype td {
    +        font-size: 10pt;
    +        }
    +
    +    .PDefaultValue,
    +    .PDefaultValuePrefix,
    +    .PTypePrefix {
    +        color: #8F8F8F;
    +        }
    +    .PTypePrefix {
    +        text-align: right;
    +        }
    +    .PAfterParameters {
    +        vertical-align: bottom;
    +        }
    +
    +    .IE .Prototype table {
    +        padding: 0;
    +        }
    +
    +    .CFunction .Prototype {
    +        background-color: #F4F4F4; border-color: #D0D0D0 }
    +    .CProperty .Prototype {
    +        background-color: #F4F4FF; border-color: #C0C0E8 }
    +    .CVariable .Prototype {
    +        background-color: #FFFFF0; border-color: #E0E0A0 }
    +
    +    .CClass .Prototype {
    +        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0;
    +        background-color: #F4F4F4;
    +        }
    +    .CInterface .Prototype {
    +        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0D0;
    +        background-color: #F4F4FF;
    +        }
    +
    +    .CDatabaseIndex .Prototype,
    +    .CConstant .Prototype {
    +        background-color: #D0D0D0; border-color: #000000 }
    +    .CType .Prototype,
    +    .CEnumeration .Prototype {
    +        background-color: #FAF0F0; border-color: #E0B0B0;
    +        }
    +    .CDatabaseTrigger .Prototype,
    +    .CEvent .Prototype,
    +    .CDelegate .Prototype {
    +        background-color: #F0FCF0; border-color: #B8E4B8 }
    +
    +    .CToolTip .Prototype {
    +        margin: 0 0 .5em 0;
    +        white-space: nowrap;
    +        }
    +
    +
    +
    +
    +
    +.Summary {
    +    margin: 1.5em 5ex 0 5ex }
    +
    +    .STitle {
    +        font-size: 12pt; font-weight: bold;
    +        margin-bottom: .5em }
    +
    +
    +    .SBorder {
    +        background-color: #FFFFF0;
    +        padding: 15px;
    +        border: 1px solid #C0C060 }
    +
    +    /* In a frame IE 6 will make them too long unless you set the width to 100%.  Without frames it will be correct without a width
    +        or slightly too long (but not enough to scroll) with a width.  This arbitrary weirdness simply astounds me.  IE 7 has the same
    +        problem with frames, haven't tested it without.  */
    +    .FramedContentPage .IE .SBorder {
    +        width: 100% }
    +
    +    /*  A treat for Mozilla users.  Blatantly non-standard.  Will be replaced with CSS 3 attributes when finalized/supported.  */
    +    .Firefox .SBorder {
    +        -moz-border-radius: 20px }
    +
    +
    +    .STable {
    +        font-size: 9pt; width: 100% }
    +
    +    .SEntry {
    +        width: 30% }
    +    .SDescription {
    +        width: 70% }
    +
    +
    +    .SMarked {
    +        background-color: #F8F8D8 }
    +
    +    .SDescription { padding-left: 2ex }
    +    .SIndent1 .SEntry { padding-left: 1.5ex }   .SIndent1 .SDescription { padding-left: 3.5ex }
    +    .SIndent2 .SEntry { padding-left: 3.0ex }   .SIndent2 .SDescription { padding-left: 5.0ex }
    +    .SIndent3 .SEntry { padding-left: 4.5ex }   .SIndent3 .SDescription { padding-left: 6.5ex }
    +    .SIndent4 .SEntry { padding-left: 6.0ex }   .SIndent4 .SDescription { padding-left: 8.0ex }
    +    .SIndent5 .SEntry { padding-left: 7.5ex }   .SIndent5 .SDescription { padding-left: 9.5ex }
    +
    +    .SDescription a { color: #800000}
    +    .SDescription a:active { color: #A00000 }
    +
    +    .SGroup td {
    +        padding-top: .5em; padding-bottom: .25em }
    +
    +    .SGroup .SEntry {
    +        font-weight: bold; font-variant: small-caps }
    +
    +    .SGroup .SEntry a { color: #800000 }
    +    .SGroup .SEntry a:active { color: #F00000 }
    +
    +
    +    .SMain td,
    +    .SClass td,
    +    .SDatabase td,
    +    .SDatabaseTable td,
    +    .SSection td {
    +        font-size: 10pt;
    +        padding-bottom: .25em }
    +
    +    .SClass td,
    +    .SDatabase td,
    +    .SDatabaseTable td,
    +    .SSection td {
    +        padding-top: 1em }
    +
    +    .SMain .SEntry,
    +    .SClass .SEntry,
    +    .SDatabase .SEntry,
    +    .SDatabaseTable .SEntry,
    +    .SSection .SEntry {
    +        font-weight: bold;
    +        }
    +
    +    .SMain .SEntry a,
    +    .SClass .SEntry a,
    +    .SDatabase .SEntry a,
    +    .SDatabaseTable .SEntry a,
    +    .SSection .SEntry a { color: #000000 }
    +
    +    .SMain .SEntry a:active,
    +    .SClass .SEntry a:active,
    +    .SDatabase .SEntry a:active,
    +    .SDatabaseTable .SEntry a:active,
    +    .SSection .SEntry a:active { color: #A00000 }
    +
    +
    +
    +
    +
    +.ClassHierarchy {
    +    margin: 0 15px 1em 15px }
    +
    +    .CHEntry {
    +        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0;
    +        margin-bottom: 3px;
    +        padding: 2px 2ex;
    +        font-size: 10pt;
    +        background-color: #F4F4F4; color: #606060;
    +        }
    +
    +    .Firefox .CHEntry {
    +        -moz-border-radius: 4px;
    +        }
    +
    +    .CHCurrent .CHEntry {
    +        font-weight: bold;
    +        border-color: #000000;
    +        color: #000000;
    +        }
    +
    +    .CHChildNote .CHEntry {
    +        font-style: italic;
    +        font-size: 8pt;
    +        }
    +
    +    .CHIndent {
    +        margin-left: 3ex;
    +        }
    +
    +    .CHEntry a:link,
    +    .CHEntry a:visited,
    +    .CHEntry a:hover {
    +        color: #606060;
    +        }
    +    .CHEntry a:active {
    +        color: #800000;
    +        }
    +
    +
    +
    +
    +
    +#Index {
    +    background-color: #FFFFFF;
    +    }
    +
    +/*  As opposed to .PopupSearchResultsPage #Index  */
    +.IndexPage #Index,
    +.FramedIndexPage #Index,
    +.FramedSearchResultsPage #Index {
    +    padding: 15px;
    +    }
    +
    +.IndexPage #Index {
    +    border-width: 0 0 1px 1px;
    +    border-style: solid;
    +    border-color: #000000;
    +    font-size: 9pt;  /* To make 27ex match the menu's 27ex. */
    +    margin-left: 27ex;
    +    }
    +
    +
    +    .IPageTitle {
    +        font-size: 20pt; font-weight: bold;
    +        color: #FFFFFF; background-color: #7070C0;
    +        padding: 10px 15px 10px 15px;
    +        border-width: 0 0 3px 0; border-color: #000000; border-style: solid;
    +        margin: -15px -15px 0 -15px }
    +
    +    .FramedSearchResultsPage .IPageTitle {
    +        margin-bottom: 15px;
    +        }
    +
    +    .INavigationBar {
    +        font-size: 10pt;
    +        text-align: center;
    +        background-color: #FFFFF0;
    +        padding: 5px;
    +        border-bottom: solid 1px black;
    +        margin: 0 -15px 15px -15px;
    +        }
    +
    +    .INavigationBar a {
    +        font-weight: bold }
    +
    +    .IHeading {
    +        font-size: 16pt; font-weight: bold;
    +        padding: 2.5em 0 .5em 0;
    +        text-align: center;
    +        width: 3.5ex;
    +        }
    +    #IFirstHeading {
    +        padding-top: 0;
    +        }
    +
    +    .IEntry {
    +        font-size: 10pt;
    +        padding-left: 1ex;
    +        }
    +    .PopupSearchResultsPage .IEntry {
    +        font-size: 8pt;
    +        padding: 1px 5px;
    +        }
    +    .PopupSearchResultsPage .Opera9 .IEntry,
    +    .FramedSearchResultsPage .Opera9 .IEntry {
    +        text-align: left;
    +        }
    +    .FramedSearchResultsPage .IEntry {
    +        padding: 0;
    +        }
    +
    +    .ISubIndex {
    +        padding-left: 3ex; padding-bottom: .5em }
    +    .PopupSearchResultsPage .ISubIndex {
    +        display: none;
    +        }
    +
    +    /*  While it may cause some entries to look like links when they aren't, I found it's much easier to read the
    +         index if everything's the same color.  */
    +    .ISymbol {
    +        font-weight: bold; color: #900000  }
    +
    +    .IndexPage .ISymbolPrefix,
    +    .FramedIndexPage .ISymbolPrefix {
    +        font-size: 10pt;
    +        text-align: right;
    +        color: #C47C7C;
    +        background-color: #F8F8F8;
    +        border-right: 3px solid #E0E0E0;
    +        border-left: 1px solid #E0E0E0;
    +        padding: 0 1px 0 2px;
    +        }
    +    .PopupSearchResultsPage .ISymbolPrefix,
    +    .FramedSearchResultsPage .ISymbolPrefix {
    +        color: #900000;
    +        }
    +    .PopupSearchResultsPage .ISymbolPrefix {
    +        font-size: 8pt;
    +        }
    +
    +    .IndexPage #IFirstSymbolPrefix,
    +    .FramedIndexPage #IFirstSymbolPrefix {
    +        border-top: 1px solid #E0E0E0;
    +        }
    +    .IndexPage #ILastSymbolPrefix,
    +    .FramedIndexPage #ILastSymbolPrefix {
    +        border-bottom: 1px solid #E0E0E0;
    +        }
    +    .IndexPage #IOnlySymbolPrefix,
    +    .FramedIndexPage #IOnlySymbolPrefix {
    +        border-top: 1px solid #E0E0E0;
    +        border-bottom: 1px solid #E0E0E0;
    +        }
    +
    +    a.IParent,
    +    a.IFile {
    +        display: block;
    +        }
    +
    +    .PopupSearchResultsPage .SRStatus {
    +        padding: 2px 5px;
    +        font-size: 8pt;
    +        font-style: italic;
    +        }
    +    .FramedSearchResultsPage .SRStatus {
    +        font-size: 10pt;
    +        font-style: italic;
    +        }
    +
    +    .SRResult {
    +        display: none;
    +        }
    +
    +
    +
    +#Footer {
    +    font-size: 8pt;
    +    color: #989898;
    +    text-align: right;
    +    }
    +
    +#Footer p {
    +    text-indent: 0;
    +    margin-bottom: .5em;
    +    }
    +
    +.ContentPage #Footer,
    +.IndexPage #Footer {
    +    text-align: right;
    +    margin: 2px;
    +    }
    +
    +.FramedMenuPage #Footer {
    +    text-align: center;
    +    margin: 5em 10px 10px 10px;
    +    padding-top: 1em;
    +    border-top: 1px solid #C8C8C8;
    +    }
    +
    +    #Footer a:link,
    +    #Footer a:hover,
    +    #Footer a:visited { color: #989898 }
    +    #Footer a:active { color: #A00000 }
    +
    +
    +
    +.prettyprint .kwd { color: #800000; }  /* keywords */
    +
    +    .prettyprint.PDefaultValue .kwd,
    +    .prettyprint.PDefaultValuePrefix .kwd,
    +    .prettyprint.PTypePrefix .kwd {
    +        color: #C88F8F;
    +        }
    +
    +.prettyprint .com { color: #008000; }  /* comments */
    +
    +    .prettyprint.PDefaultValue .com,
    +    .prettyprint.PDefaultValuePrefix .com,
    +    .prettyprint.PTypePrefix .com {
    +        color: #8FC88F;
    +        }
    +
    +.prettyprint .str { color: #0000B0; }  /* strings */
    +.prettyprint .lit { color: #0000B0; }  /* literals */
    +
    +    .prettyprint.PDefaultValue .str,
    +    .prettyprint.PDefaultValuePrefix .str,
    +    .prettyprint.PTypePrefix .str,
    +    .prettyprint.PDefaultValue .lit,
    +    .prettyprint.PDefaultValuePrefix .lit,
    +    .prettyprint.PTypePrefix .lit {
    +        color: #8F8FC0;
    +        }
    +
    +.prettyprint .typ { color: #000000; }  /* types */
    +.prettyprint .pun { color: #000000; }  /* punctuation */
    +.prettyprint .pln { color: #000000; }  /* punctuation */
    +
    +    .prettyprint.PDefaultValue .typ,
    +    .prettyprint.PDefaultValuePrefix .typ,
    +    .prettyprint.PTypePrefix .typ,
    +    .prettyprint.PDefaultValue .pun,
    +    .prettyprint.PDefaultValuePrefix .pun,
    +    .prettyprint.PTypePrefix .pun,
    +    .prettyprint.PDefaultValue .pln,
    +    .prettyprint.PDefaultValuePrefix .pln,
    +    .prettyprint.PTypePrefix .pln {
    +        color: #8F8F8F;
    +        }
    +
    +.prettyprint .tag { color: #008; }
    +.prettyprint .atn { color: #606; }
    +.prettyprint .atv { color: #080; }
    +.prettyprint .dec { color: #606; }
    +
    diff --git a/addons/@ocap/licence.txt b/licence.txt
    similarity index 100%
    rename from addons/@ocap/licence.txt
    rename to licence.txt
    diff --git a/addons/@ocap/logo_ocap.paa b/logo_ocap.paa
    similarity index 100%
    rename from addons/@ocap/logo_ocap.paa
    rename to logo_ocap.paa
    diff --git a/addons/@ocap/mod.cpp b/mod.cpp
    similarity index 82%
    rename from addons/@ocap/mod.cpp
    rename to mod.cpp
    index 4a2a884..a61cd6a 100644
    --- a/addons/@ocap/mod.cpp
    +++ b/mod.cpp
    @@ -4,8 +4,8 @@ picture			= "logo_ocap.paa";								// Picture displayed from the expansions men
     //logo			= "\Samples_F\Data_01\Logos\logo.paa";			// Logo displayed in the main menu
     //logoOver		= "\Samples_F\Data_01\Logos\logoOver.paa";		// When the mouse is over, in the main menu
     actionName		= "Github";										// Text displayed on the "website" button
    -action			= "https://github.com/OCAPv2";					// Website URL, that can accessed from the expansions menu
    -tooltipOwned	= "Operation Capture and Playback v2";			// Tool tip displayed when the mouse is left over, in the main menu
    +action			= "https://github.com/OCAP2/OCAP";					// Website URL, that can accessed from the expansions menu
    +tooltipOwned	= "Operation Capture and Playback 2";			// Tool tip displayed when the mouse is left over, in the main menu
     
     // Color used for DLC stripes and backgrounds (RGBA)
     dlcColor[] =
    diff --git a/userconfig/ocap/config.hpp b/userconfig/ocap/config.hpp
    deleted file mode 100644
    index af88688..0000000
    --- a/userconfig/ocap/config.hpp
    +++ /dev/null
    @@ -1,12 +0,0 @@
    -ocap_autoStart = true; // Automatically start OCAP recordings at session start.
    -ocap_minPlayerCount = 15; // recording will only begin if this many players are in the server
    -ocap_minMissionTime = 20; // missions must last at least this many minutes to be saved
    -ocap_frameCaptureDelay = 1;
    -ocap_saveMissionEnded = true; // automatically save mission with default settings on the "MPEnded" event handler trigger
    -ocap_preferACEUnconscious = true; // if true, ACE3 medical unconscious state will be used. if false, will check vanilla A3 system
    -ocap_excludeClassFromRecord = ["ACE_friesAnchorBar", "GroundWeaponHolder", "WeaponHolderSimulated"]; // excludes specific class names from recordings
    -ocap_excludeKindFromRecord = []; // use isKindOf checking to exclude one or more hierarchies of objects from recording
    -ocap_excludeMarkerFromRecord = ["SystemMarker_"]; // excludes markers with any of these strings in their markerName
    -ocap_trackTimes = false; // continously track times -- set true for missions with accelerated or skipped time
    -ocap_trackTimeInterval = 10; // track time every X capture frame
    -ocap_isDebug = false; // extra logging messages
    diff --git a/x/ocap/.editorconfig b/x/ocap/.editorconfig
    new file mode 100644
    index 0000000..1b9210f
    --- /dev/null
    +++ b/x/ocap/.editorconfig
    @@ -0,0 +1,13 @@
    +# EditorConfig is awesome: http://EditorConfig.org
    +
    +# top-most EditorConfig file
    +root = true
    +
    +# every file
    +[*]
    +indent_style = space
    +indent_size = 2
    +end_of_line = lf
    +charset = utf-8
    +trim_trailing_whitespace = true
    +insert_final_newline = true
    diff --git a/x/ocap/.gitignore b/x/ocap/.gitignore
    new file mode 100644
    index 0000000..ecbbd4e
    --- /dev/null
    +++ b/x/ocap/.gitignore
    @@ -0,0 +1,3 @@
    +*.pbo
    +
    +*.bak
    diff --git a/x/ocap/addons/extension/XEH_postInit.sqf b/x/ocap/addons/extension/XEH_postInit.sqf
    new file mode 100644
    index 0000000..19f1494
    --- /dev/null
    +++ b/x/ocap/addons/extension/XEH_postInit.sqf
    @@ -0,0 +1,3 @@
    +#include "script_component.hpp"
    +
    +ADDON = true;
    diff --git a/x/ocap/addons/extension/XEH_preInit.sqf b/x/ocap/addons/extension/XEH_preInit.sqf
    new file mode 100644
    index 0000000..44484b5
    --- /dev/null
    +++ b/x/ocap/addons/extension/XEH_preInit.sqf
    @@ -0,0 +1,4 @@
    +#include "script_component.hpp"
    +#include "XEH_prep.sqf"
    +
    +ADDON = true;
    diff --git a/x/ocap/addons/extension/XEH_prep.sqf b/x/ocap/addons/extension/XEH_prep.sqf
    new file mode 100644
    index 0000000..728a456
    --- /dev/null
    +++ b/x/ocap/addons/extension/XEH_prep.sqf
    @@ -0,0 +1,3 @@
    +#include "script_component.hpp"
    +
    +PREP(sendData);
    diff --git a/x/ocap/addons/extension/config.cpp b/x/ocap/addons/extension/config.cpp
    new file mode 100644
    index 0000000..bab61ad
    --- /dev/null
    +++ b/x/ocap/addons/extension/config.cpp
    @@ -0,0 +1,32 @@
    +#define _ARMA_
    +#include "script_component.hpp"
    +
    +class CfgPatches
    +{
    +  class ADDON
    +  {
    +
    +    name = COMPONENT_NAME;
    +    author = "Dell, Zealot, Kurt, IndigoFox, Fank";
    +    authors[] = {"Dell", "Zealot", "Kurt", "IndigoFox", "Fank"};
    +    url = "https://github.com/OCAP2/OCAP";
    +    VERSION_CONFIG;
    +    requiredAddons[] = {"A3_Functions_F","cba_main","cba_xeh","ocap_main"};
    +    units[] = {};
    +    weapons[] = {};
    +  };
    +};
    +
    +class Extended_PreInit_EventHandlers {
    +  class ADDON {
    +    // This will be executed once in 3DEN, main menu and before briefing has started for every mission
    +    init = QUOTE( call COMPILE_FILE(XEH_preInit) );
    +  };
    +};
    +
    +class Extended_PostInit_EventHandlers {
    +  class ADDON {
    +    // This will be executed once for each mission, once the mission has started
    +    init = QUOTE( call COMPILE_FILE(XEH_postInit) );
    +  };
    +};
    diff --git a/addons/@ocap/addons/ocap/functions/fn_extension.sqf b/x/ocap/addons/extension/fnc_sendData.sqf
    similarity index 74%
    rename from addons/@ocap/addons/ocap/functions/fn_extension.sqf
    rename to x/ocap/addons/extension/fnc_sendData.sqf
    index aacf12b..bb096b7 100644
    --- a/addons/@ocap/addons/ocap/functions/fn_extension.sqf
    +++ b/x/ocap/addons/extension/fnc_sendData.sqf
    @@ -1,5 +1,7 @@
     /* ----------------------------------------------------------------------------
    -Script: ocap_fnc_extension
    +FILE: fnc_sendData.sqf
    +
    +FUNCTION: OCAP_extension_fnc_sendData
     
     Description:
     	Manages raw extension calls and returns values / logs errors where relevant.
    @@ -12,9 +14,7 @@ Returns:
     	Depends
     
     Examples:
    -	--- Code
    -	[":VERSION", []] call ocap_fnc_extension;
    -	---
    +	> [":VERSION", []] call EFUNC(extension,sendData);
     
     Public:
     	No
    @@ -22,6 +22,7 @@ Public:
     Author:
     	Dell, Zealot
     ---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
     
     params ["_command","_args"];
     
    @@ -32,7 +33,7 @@ private _res = _dllName callExtension [_command, _args];
     _res params ["_result","_returnCode","_errorCode"];
     
     if (_errorCode != 0 || _returnCode != 0) then {
    -	diag_log ["fnc_callextension_zlt.sqf: Error: ", _result, _returnCode, _errorCode, _command, _args];
    +  textLogFormat ["Error when calling extension: %1", [_result, _returnCode, _errorCode, _command, _args]];
     };
     
     if (
    diff --git a/x/ocap/addons/extension/script_component.hpp b/x/ocap/addons/extension/script_component.hpp
    new file mode 100644
    index 0000000..648d608
    --- /dev/null
    +++ b/x/ocap/addons/extension/script_component.hpp
    @@ -0,0 +1,8 @@
    +// HEADER: script_component.hpp
    +
    +// DEFINE: COMPONENT
    +#define COMPONENT extension
    +// DEFINE: COMPONENT_BEAUTIFIED
    +#define COMPONENT_BEAUTIFIED Extension
    +
    +#include "\x\ocap\addons\main\script_macros.hpp"
    diff --git a/x/ocap/addons/main/XEH_postInit.sqf b/x/ocap/addons/main/XEH_postInit.sqf
    new file mode 100644
    index 0000000..528902a
    --- /dev/null
    +++ b/x/ocap/addons/main/XEH_postInit.sqf
    @@ -0,0 +1,9 @@
    +#include "script_component.hpp"
    +
    +// During postInit, we'll remoteExec these settings onto clients so vars are synchronized and modifiable during a mission.
    +{
    +  _x remoteExec ["CBA_fnc_addSetting", [0, -2] select isServer, true];
    +} forEach GVAR(allSettings);
    +
    +
    +ADDON = true;
    diff --git a/x/ocap/addons/main/XEH_preInit.sqf b/x/ocap/addons/main/XEH_preInit.sqf
    new file mode 100644
    index 0000000..5696df1
    --- /dev/null
    +++ b/x/ocap/addons/main/XEH_preInit.sqf
    @@ -0,0 +1,120 @@
    +// FILE: CBA Settings
    +
    +#include "script_component.hpp"
    +#include "XEH_prep.sqf"
    +
    +
    +// This PreInit creates the settings on the server, only so that the global vars will be registered and synchronized with clients.
    +
    +GVAR(allSettings) = [
    +  // Section: Core
    +
    +  /*
    +    CBA Setting: OCAP_enabled
    +    Description:
    +      Turns on or off most recording functionality. Will not reset anything from existing session, will just stop recording most new data. Note: For record/pause switching, use the CBA events! Default: true
    +
    +    Setting Name:
    +      Recording Enabled
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QGVARMAIN(enabled),
    +    "CHECKBOX", // setting type
    +    [
    +      "Recording Enabled", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Turns on or off most recording functionality. Will not reset anything from existing session, will just stop recording most new data. Note: For record/pause switching, use the CBA events! Default: true"
    +    ],
    +    [COMPONENT_NAME, "Core"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    true, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_isDebug
    +    Description:
    +      Enables increased logging of addon actions. Default: false
    +
    +    Setting Name:
    +      Debug Mode
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QGVARMAIN(isDebug),
    +    "CHECKBOX", // setting type
    +    [
    +      "Debug Mode", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Enables increased logging of addon actions. Default: false"
    +    ],
    +    [COMPONENT_NAME, "Core"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    false, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_enabledAdministratorUI
    +    Description:
    +      Turns on or off the Administrator UI in the briefing diary. Default: true
    +
    +    Setting Name:
    +      Administrator UI Enabled
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QGVARMAIN(enabledAdministratorUI),
    +    "CHECKBOX", // setting type
    +    [
    +      "Administrator UI Enabled", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Turns on or off the Administrator UI in the briefing diary. Default: true"
    +    ],
    +    [COMPONENT_NAME, "Core"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    true, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_administratorList
    +    Description:
    +      An array or server-visible variable referencing one that is a list of playerUIDs. Additional briefing diary or UI elements may be available for more accessible control over OCAP's features. Takes effect on player server connection. Format: [] OR myAdminPUIDs | Default: []
    +
    +    Setting Name:
    +      Administrators
    +
    +    Value Type:
    +      Stringified Array
    +
    +    Example:
    +      > "['76561198000000000', '76561198000000001']"
    +  */
    +  [
    +    QGVARMAIN(administratorList),
    +    "EDITBOX", // setting type
    +    [
    +      "Administrators", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "An array or server-visible variable referencing one that is a list of playerUIDs. Additional briefing diary or UI elements may be available for more accessible control over OCAP's features. Takes effect on player server connection. Format: [] OR myAdminPUIDs | Default: []"
    +    ],
    +    [COMPONENT_NAME, "Core"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    "[]", // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ]
    +];
    +
    +{
    +  _x call CBA_fnc_addSetting;
    +} forEach GVAR(allSettings);
    +
    +ADDON = true;
    diff --git a/x/ocap/addons/main/XEH_prep.sqf b/x/ocap/addons/main/XEH_prep.sqf
    new file mode 100644
    index 0000000..421c54b
    --- /dev/null
    +++ b/x/ocap/addons/main/XEH_prep.sqf
    @@ -0,0 +1 @@
    +#include "script_component.hpp"
    diff --git a/x/ocap/addons/main/config.cpp b/x/ocap/addons/main/config.cpp
    new file mode 100644
    index 0000000..f0ff80a
    --- /dev/null
    +++ b/x/ocap/addons/main/config.cpp
    @@ -0,0 +1,32 @@
    +#define _ARMA_
    +#include "script_component.hpp"
    +
    +class CfgPatches
    +{
    +  class ADDON
    +  {
    +
    +    name = COMPONENT_NAME;
    +    author = "Dell, Zealot, Kurt, IndigoFox, Fank";
    +    authors[] = {"Dell", "Zealot", "Kurt", "IndigoFox", "Fank"};
    +    url = "https://github.com/OCAP2/OCAP";
    +    VERSION_CONFIG;
    +    requiredAddons[] = {"A3_Functions_F","cba_main","cba_xeh"};
    +    units[] = {};
    +    weapons[] = {};
    +  };
    +};
    +
    +class Extended_PreInit_EventHandlers {
    +  class ADDON {
    +    // This will be executed once in 3DEN, main menu and before briefing has started for every mission
    +    init = QUOTE( call COMPILE_FILE(XEH_preInit) );
    +  };
    +};
    +
    +class Extended_PostInit_EventHandlers {
    +  class ADDON {
    +    // This will be executed once for each mission, once the mission has started
    +    init = QUOTE( call COMPILE_FILE(XEH_postInit) );
    +  };
    +};
    diff --git a/x/ocap/addons/main/script_component.hpp b/x/ocap/addons/main/script_component.hpp
    new file mode 100644
    index 0000000..a277cac
    --- /dev/null
    +++ b/x/ocap/addons/main/script_component.hpp
    @@ -0,0 +1,8 @@
    +// HEADER: script_component.hpp
    +
    +// DEFINE: COMPONENT
    +#define COMPONENT main
    +// DEFINE: COMPONENT_BEAUTIFIED
    +#define COMPONENT_BEAUTIFIED Main
    +
    +#include "script_macros.hpp"
    diff --git a/x/ocap/addons/main/script_macros.hpp b/x/ocap/addons/main/script_macros.hpp
    new file mode 100644
    index 0000000..75bbdc8
    --- /dev/null
    +++ b/x/ocap/addons/main/script_macros.hpp
    @@ -0,0 +1,62 @@
    +// HEADER: script_macros.hpp
    +// Defines macros imported to other functions
    +
    +// DEFINE: PREFIX
    +#define PREFIX OCAP
    +
    +#ifdef COMPONENT_BEAUTIFIED
    +  // DEFINE: COMPONENT_NAME
    +  #define COMPONENT_NAME QUOTE(PREFIX - COMPONENT_BEAUTIFIED)
    +#else
    +  #define COMPONENT_NAME QUOTE(PREFIX - COMPONENT)
    +#endif
    +
    +// DEFINE: ADDON
    +// <PREFIX>_<COMPONENT>
    +
    +// The current version of OCAP.
    +
    +// DEFINE: VERSION
    +#define VERSION 2.0
    +
    +// DEFINE: VERSION_STR
    +#define VERSION_STR 2.0.0
    +
    +// DEFINE: VERSION_AR
    +#define VERSION_AR 2,0,0
    +
    +// DEFINE: VERSION_REQUIRED
    +#define VERSION_REQUIRED 2.10
    +
    +// MACRO: LOG
    +// Used for logging messages to the extension (ocap-ext log file).
    +#define OCAPEXTLOG(_args) [":LOG:", _args] call EFUNC(extension,sendData)
    +
    +// MACRO: SYSCHAT
    +// Used for debug purposes to send a string to all clients with interfaces.
    +#define SYSCHAT remoteExec ["systemChat", [0, -2] select isDedicated]
    +
    +// MACRO: SHOULDSAVEEVENTS
    +// Used to determine if events should currently be saved based on <OCAP_recorder_recording> and <OCAP_recorder_startTime>.
    +#define SHOULDSAVEEVENTS ((missionNamespace getVariable [QGVAR(recording), false]) && missionNamespace getVariable [QGVAR(startTime), -1] > -1)
    +
    +#define DEBUG_MODE_NORMAL
    +// #define DEBUG_MODE_FULL
    +
    +// DEFINE: BOOL
    +// Forces a true/false return of input.
    +#define BOOL(_cond) ([0,1] select (_cond))
    +
    +// DEFINE: ARR2
    +// Resolves arguments to array, used for entries to <LOG> that requires array input.
    +#define ARR2(_arg1, _arg2) [_arg1, _arg2]
    +#define ARR3(_arg1, _arg2, _arg3) [_arg1, _arg2, _arg3]
    +#define ARR4(_arg1, _arg2, _arg3, _arg4) [_arg1, _arg2, _arg3, _arg4]
    +#define ARR5(_arg1, _arg2, _arg3, _arg4, _arg5) [_arg1, _arg2, _arg3, _arg4, _arg5]
    +#define ARR6(_arg1, _arg2, _arg3, _arg4, _arg5, _arg6) [_arg1, _arg2, _arg3, _arg4, _arg5, _arg6]
    +
    +
    +#include "\x\cba\addons\main\script_macros_common.hpp"
    +#include "\x\cba\addons\xeh\script_xeh.hpp"
    +
    +
    diff --git a/x/ocap/addons/recorder/XEH_postInit.sqf b/x/ocap/addons/recorder/XEH_postInit.sqf
    new file mode 100644
    index 0000000..176765f
    --- /dev/null
    +++ b/x/ocap/addons/recorder/XEH_postInit.sqf
    @@ -0,0 +1,11 @@
    +#include "script_component.hpp"
    +
    +{
    +  _x remoteExec ["CBA_fnc_addSetting", [0, -2] select isServer, true];
    +} forEach GVAR(allSettings);
    +
    +if (!is3DEN) then {
    +  call FUNC(init);
    +};
    +
    +ADDON = true;
    diff --git a/x/ocap/addons/recorder/XEH_preInit.sqf b/x/ocap/addons/recorder/XEH_preInit.sqf
    new file mode 100644
    index 0000000..78a6e31
    --- /dev/null
    +++ b/x/ocap/addons/recorder/XEH_preInit.sqf
    @@ -0,0 +1,415 @@
    +// FILE: CBA Settings
    +
    +#include "script_component.hpp"
    +#include "XEH_prep.sqf"
    +
    +GVAR(allSettings) = [
    +  // Section: Auto-Start Settings
    +
    +  /*
    +    CBA Setting: OCAP_settings_autoStart
    +    Description:
    +      Automatically start OCAP recordings at session start. Default: true
    +
    +    Setting Name:
    +      Auto Start Recording
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QEGVAR(settings,autoStart),
    +    "CHECKBOX", // setting type
    +    [
    +      "Auto Start Recording", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Automatically start OCAP recordings at session start. Default: true"
    +    ],
    +    [COMPONENT_NAME, "Auto-start Settings"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    true, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    true // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_minPlayerCount
    +    Description:
    +      Auto-start will begin once this player count is reached. Default: 15
    +
    +    Setting Name:
    +      Minimum Player Count
    +
    +    Value Type:
    +      Number
    +  */
    +  [
    +    QEGVAR(settings,minPlayerCount),
    +    "SLIDER", // setting type
    +    [
    +      "Minimum Player Count", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Auto-start will begin once this player count is reached. Default: 15"
    +    ],
    +    [COMPONENT_NAME, "Auto-start Settings"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    [
    +        1, // min
    +        150, // max
    +        15, // default
    +        0, // trailing decimals
    +        false // percentage
    +    ], // data for this setting: [min, max, default, number of shown trailing decimals]
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +
    +  // Section: Core
    +
    +  /*
    +    CBA Setting: OCAP_settings_frameCaptureDelay
    +    Description:
    +      Positioning, medical status, and crew states of units and vehicles will be captured every X amount of seconds. Default: 1
    +
    +    Setting Name:
    +      Frame Capture Delay
    +
    +    Value Type:
    +      Number
    +  */
    +  [
    +    QEGVAR(settings,frameCaptureDelay),
    +    "SLIDER", // setting type
    +    [
    +      "Frame Capture Delay", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Positioning, medical status, and crew states of units and vehicles will be captured every X amount of seconds. Default: 1"
    +    ],
    +    [COMPONENT_NAME, "Core"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    [
    +        0.30, // min
    +        10, // max
    +        1, // default
    +        2, // trailing decimals
    +        false // percentage
    +    ], // data for this setting: [min, max, default, number of shown trailing decimals]
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    true // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_preferACEUnconscious
    +    Description:
    +      If true, will check ACE3 medical status on units. If false, or ACE3 isn't loaded, fall back to vanilla. Default: true
    +
    +    Setting Name:
    +      Use ACE3 Medical
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QEGVAR(settings,preferACEUnconscious),
    +    "CHECKBOX", // setting type
    +    [
    +      "Use ACE3 Medical", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "If true, will check ACE3 medical status on units. If false, or ACE3 isn't loaded, fall back to vanilla. Default: true"
    +    ],
    +    [COMPONENT_NAME, "Core"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    true, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +
    +
    +
    +
    +  // Section: Exclusions
    +
    +  /*
    +    CBA Setting: OCAP_settings_excludeClassFromRecord
    +    Description:
    +      Array of object classnames that should be excluded from recording. Use single quotes! Default: ['ACE_friesAnchorBar', 'WeaponHolderSimulated']
    +
    +    Setting Name:
    +      Classnames to Exclude
    +
    +    Value Type:
    +      Stringified Array
    +
    +    Example:
    +      > "['ACE_friesAnchorBar']"
    +  */
    +  [
    +    QEGVAR(settings,excludeClassFromRecord),
    +    "EDITBOX", // setting type
    +    [
    +      "Classnames to Exclude", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Array of object classnames that should be excluded from recording. Use single quotes! Default: ['ACE_friesAnchorBar', 'WeaponHolderSimulated']"
    +    ],
    +    [COMPONENT_NAME, "Exclusions"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    "['ACE_friesAnchorBar']", // default string value
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_excludeKindFromRecord
    +    Description:
    +      Array of classnames which, along with all child classes, should be excluded from recording. Use single quotes! Default: []
    +
    +    Setting Name:
    +      Object KindOfs to Exclude
    +
    +    Value Type:
    +      Stringified Array
    +
    +    Example:
    +      > "['WeaponHolder']"
    +  */
    +  [
    +    QEGVAR(settings,excludeKindFromRecord),
    +    "EDITBOX", // setting type
    +    [
    +      "Object KindOfs to Exclude", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Array of classnames which, along with all child classes, should be excluded from recording. Use single quotes! Default: []"
    +    ],
    +    [COMPONENT_NAME, "Exclusions"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    "['WeaponHolder']", // default string value
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_excludeMarkerFromRecord
    +    Description:
    +      Array of prefixes. Any markers matching these prefixes will be excluded from recording. Use single quotes! Default: ['SystemMarker_','ACE_BFT_']
    +
    +    Setting Name:
    +      Marker Prefixes To Exclude
    +
    +    Value Type:
    +      Stringified Array
    +
    +    Example:
    +      > "['SystemMarker_','ACE_BFT_']"
    +  */
    +  [
    +    QEGVAR(settings,excludeMarkerFromRecord),
    +    "EDITBOX", // setting type
    +    [
    +      "Marker Prefixes to Exclude", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Array of prefixes. Any markers matching these prefixes will be excluded from recording. Use single quotes! Default: ['SystemMarker_','ACE_BFT_']"
    +    ],
    +    [COMPONENT_NAME, "Exclusions"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    "['SystemMarker_','ACE_BFT_']", // default string value
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +
    +
    +
    +  // Section: Extra Tracking
    +
    +  /*
    +    CBA Setting: OCAP_settings_trackTickets
    +    Description:
    +      Will track respawn ticket counts for missionNamespace and each playable faction every 30th frame. Default: true
    +
    +    Setting Name:
    +      Enable Ticket Tracking
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QEGVAR(settings,trackTickets),
    +    "CHECKBOX", // setting type
    +    [
    +      "Enable Ticket Tracking", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Will track respawn ticket counts for missionNamespace and each playable faction every 30th frame. Default: true"
    +    ],
    +    [COMPONENT_NAME, "Extra Tracking"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    true, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_trackTimes
    +    Description:
    +      Will continuously track in-game world time during a mission. Useful for accelerated/skipped time scenarios. Default: false
    +
    +    Setting Name:
    +      Enable Mission Time Tracking
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QEGVAR(settings,trackTimes),
    +    "CHECKBOX", // setting type
    +    [
    +      "Enable Mission Time Tracking", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Will continuously track in-game world time during a mission. Useful for accelerated/skipped time scenarios. Default: false"
    +    ],
    +    [COMPONENT_NAME, "Extra Tracking"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    false, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_trackTimeInterval
    +    Description:
    +      If <OCAP_settings_trackTimes> is enabled, it will be checked every X capture frames. Default: 10
    +
    +    Setting Name:
    +      Mission Time Tracking Interval
    +
    +    Value Type:
    +      Number
    +  */
    +  [
    +    QEGVAR(settings,trackTimeInterval),
    +    "SLIDER", // setting type
    +    [
    +      "Mission Time Tracking Interval", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "If time tracking is enabled, it will be checked every X capture frames. Default: 10"
    +    ],
    +    [COMPONENT_NAME, "Extra Tracking"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    [
    +        5, // min
    +        25, // max
    +        10, // default
    +        0, // trailing decimals
    +        false // percentage
    +    ], // data for this setting: [min, max, default, number of shown trailing decimals]
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +
    +
    +  // Section: Save/Export Settings
    +
    +  /*
    +    CBA Setting: OCAP_settings_saveTag
    +    Description:
    +      If not overriden by the <OCAP_exportData> CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions.
    +
    +    Setting Name:
    +      Mission Type Tag
    +
    +    Value Type:
    +      String
    +  */
    +  [
    +    QEGVAR(settings,saveTag),
    +    "EDITBOX", // setting type
    +    [
    +      "Mission Type Tag", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "If not overriden by the exportData CBA event or if a mission is auto-saved, this will be used to categorize and filter the recording in the database and web list of missions."
    +    ],
    +    [COMPONENT_NAME, "Save/Export Settings"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    "TvT", // default string value
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_saveMissionEnded
    +    Description:
    +      If true, automatically save and export the mission when the MPEnded event fires. Default: true
    +
    +    Setting Name:
    +      Auto-save on MPEnded Event
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QEGVAR(settings,saveMissionEnded),
    +    "CHECKBOX", // setting type
    +    [
    +      "Auto-save on MPEnded Event", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "If true, automatically save and export the mission when the MPEnded event fires. Default: true"
    +    ],
    +    [COMPONENT_NAME, "Save/Export Settings"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    true, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_saveOnEmpty
    +    Description:
    +      Will automatically save recording when there are 0 players on the server and existing data accounts for more time than the minimum save duration setting. Default: true
    +
    +    Setting Name:
    +      Auto-Save When No Players
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QEGVAR(settings,saveOnEmpty),
    +    "CHECKBOX", // setting type
    +    [
    +      "Auto-Save When No Players", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "Will automatically save recording when there are 0 players on the server and existing data accounts for more time than the minimum save duration setting. Default: true"
    +    ],
    +    [COMPONENT_NAME, "Save/Export Settings"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    true, // default enabled
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    false // requires restart to apply
    +  ],
    +
    +  /*
    +    CBA Setting: OCAP_settings_minMissionTime
    +    Description:
    +      A recording must be at least this long (in minutes) to auto-save. Calling an <OCAP_exportData> CBA server event will override this restriction. Default: 20
    +
    +    Setting Name:
    +      Required Duration to Sav
    +
    +    Value Type:
    +      Boolean
    +  */
    +  [
    +    QEGVAR(settings,minMissionTime),
    +    "SLIDER", // setting type
    +    [
    +      "Required Duration to Save", // Pretty name shown inside the ingame settings menu. Can be stringtable entry.
    +      "A recording must be at least this long (in minutes) to auto-save. Calling an 'ocap_exportData' CBA server event will override this restriction. Default: 20"
    +    ],
    +    [COMPONENT_NAME, "Save/Export Settings"], // Pretty name of the category where the setting can be found. Can be stringtable entry.
    +    [
    +        1, // min
    +        120, // max
    +        20, // default
    +        0, // trailing decimals
    +        false // percentage
    +    ], // data for this setting: [min, max, default, number of shown trailing decimals]
    +    true, // "_isGlobal" flag. Set this to true to always have this setting synchronized between all clients in multiplayer
    +    {}, // function that will be executed once on mission start and every time the setting is changed.
    +    true // requires restart to apply
    +  ]
    +];
    +
    +{
    +  _x call CBA_fnc_addSetting;
    +} forEach GVAR(allSettings);
    +
    +ADDON = true;
    diff --git a/x/ocap/addons/recorder/XEH_prep.sqf b/x/ocap/addons/recorder/XEH_prep.sqf
    new file mode 100644
    index 0000000..6019b7d
    --- /dev/null
    +++ b/x/ocap/addons/recorder/XEH_prep.sqf
    @@ -0,0 +1,38 @@
    +#include "script_component.hpp"
    +
    +PREP(init);
    +
    +PREP(updateTime);
    +
    +PREP(startRecording);
    +PREP(stopRecording);
    +PREP(captureLoop);
    +PREP(isKindOfApc);
    +PREP(getClass);
    +PREP(getUnitType);
    +
    +PREP(addEventMission);
    +PREP(handleCustomEvent);
    +PREP(handleMarkers);
    +PREP(addUnitEventHandlers);
    +
    +PREP(eh_connected);
    +PREP(eh_disconnected);
    +PREP(eh_onUserAdminStateChanged);
    +PREP(adminUIcontrol);
    +
    +PREP(eh_firedMan);
    +// PREP(eh_hit);
    +PREP(eh_projectileHit);
    +PREP(eh_killed);
    +PREP(getInstigator);
    +PREP(getEventWeaponText);
    +PREP(getAmmoMarkerData);
    +PREP(getWeaponDisplayData);
    +
    +PREP(projectileMonitors);
    +PREP(entityMonitors);
    +
    +PREP(aceExplosives);
    +
    +PREP(exportData);
    diff --git a/x/ocap/addons/recorder/config.cpp b/x/ocap/addons/recorder/config.cpp
    new file mode 100644
    index 0000000..dffc8b3
    --- /dev/null
    +++ b/x/ocap/addons/recorder/config.cpp
    @@ -0,0 +1,32 @@
    +#define _ARMA_
    +#include "script_component.hpp"
    +
    +class CfgPatches
    +{
    +  class ADDON
    +  {
    +
    +    name = COMPONENT_NAME;
    +    author = "Dell, Zealot, Kurt, IndigoFox, Fank";
    +    authors[] = {"Dell", "Zealot", "Kurt", "IndigoFox", "Fank"};
    +    url = "https://github.com/OCAP2/OCAP";
    +    VERSION_CONFIG;
    +    requiredAddons[] = {"A3_Functions_F","cba_main","cba_xeh","ocap_main","ocap_extension"};
    +    units[] = {};
    +    weapons[] = {};
    +  };
    +};
    +
    +class Extended_PreInit_EventHandlers {
    +  class ADDON {
    +    // This will be executed once in 3DEN, main menu and before briefing has started for every mission
    +    init = QUOTE( call COMPILE_FILE(XEH_preInit) );
    +  };
    +};
    +
    +class Extended_PostInit_EventHandlers {
    +  class ADDON {
    +    // This will be executed once for each mission, once the mission has started
    +    init = QUOTE( call COMPILE_FILE(XEH_postInit) );
    +  };
    +};
    diff --git a/x/ocap/addons/recorder/fnc_aceExplosives.sqf b/x/ocap/addons/recorder/fnc_aceExplosives.sqf
    new file mode 100644
    index 0000000..1d2d500
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_aceExplosives.sqf
    @@ -0,0 +1,112 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_aceExplosives.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_aceExplosives
    +
    +Description:
    +  Adds marker on the mine's position to the recording timeline.
    +  Then waits until the explosive is null (exploded) and indicates it with a 10-frame long red X before removing the marker.
    +
    +  Called by <ace_explosives_place> CBA listener.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > call FUNC(aceExplosives);
    +
    +Notes:
    +  Example of emitting event from ACE3 code:
    +  > [QGVAR(place), [_explosive, _dir, _pitch, _unit]] call CBA_fnc_globalEvent;
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +if (!SHOULDSAVEEVENTS) exitWith {};
    +
    +params ["_explosive", "_dir", "_pitch", "_unit"];
    +
    +private _int = random(2000);
    +
    +_explType = typeOf _explosive;
    +_explosiveMag = getText(configFile >> "CfgAmmo" >> _explType >> "defaultMagazine");
    +_explosiveDisp = getText(configFile >> "CfgMagazines" >> _explosiveMag >> "displayName");
    +_explosivePic = getText(configFile >> "CfgMagazines" >> _explosiveMag >> "picture");
    +
    +_placedPos = getPosASL _explosive;
    +_unit addOwnedMine _explosive;
    +
    +_markTextLocal = format["%1", _explosiveDisp];
    +_markName = format["%1#%2/%3", QGVARMAIN(mine), _int, _placedPos];
    +_markColor = "ColorRed";
    +_markerType = "Minefield";
    +
    +
    +// Signals creation of a Minefield (triangle) marker on the timeline at the location the explosive was armed.
    +[QGVARMAIN(handleMarker), [
    +  "CREATED", _markName, _unit, _placedPos, _markerType, "ICON", [1,1], 0, "Solid", "ColorRed", 1, _markTextLocal, true
    +]] call CBA_fnc_localEvent;
    +
    +if (GVARMAIN(isDebug)) then {
    +  // add to map draw array
    +  private _debugArr = [_explosive, _explosivePic, format["%1 %2 - %3", str side group _unit, name _unit, _markTextLocal], [side group _unit] call BIS_fnc_sideColor];
    +  GVAR(liveDebugMagIcons) pushBack _debugArr;
    +  publicVariable QGVAR(liveDebugMagIcons);
    +};
    +
    +
    +[{isNull (_this#0)}, { // wait until the mine is null (exploded), and mark this for playback
    +
    +  params ["_explosive", "_explosiveDisp", "_unit", "_placedPos", "_markName", "_int"];
    +
    +  // set unit who placed's lastFired var as the explosive so kills are registered to the explosive
    +  _unit setVariable [
    +    QGVARMAIN(lastFired),
    +    _explosiveDisp
    +  ];
    +
    +  // remove previous marker
    +  if (GVARMAIN(isDebug)) then {
    +    format["Removed explosive placed marker, %1, %2", _markName, _explosiveDisp] SYSCHAT;
    +    OCAPEXTLOG(ARR3("Removed explosive placed marker", _markName, _explosiveDisp));
    +  };
    +
    +
    +  // Signals removal of the Minefield (triangle) marker when the explosive is null (exploded).
    +  [QGVARMAIN(handleMarker), ["DELETED", _markName]] call CBA_fnc_localEvent;
    +
    +  _markTextLocal = format["%1", _explosiveDisp];
    +  _markName = format["Detonation#%1", _int];
    +  _markColor = "ColorRed";
    +  _markerType = "waypoint";
    +
    +  if (GVARMAIN(isDebug)) then {
    +    format["Created explosive explosion marker, %1, %2", _markName, _explosiveDisp] SYSCHAT;
    +    OCAPEXTLOG(ARR3("Created explosive explosion marker", _markName, _explosiveDisp));
    +  };
    +
    +
    +  // Signals creation of a Waypoint (X) marker on the timeline at the location the explosive detonated.
    +  [QGVARMAIN(handleMarker), [
    +    "CREATED", _markName, _unit, _placedPos, _markerType, "ICON", [1,1], 0, "Solid", "ColorRed", 1, _markTextLocal, true
    +  ]] call CBA_fnc_localEvent;
    +
    +
    +  [{
    +    params ["_markName", "_explosiveDisp"];
    +    if (GVARMAIN(isDebug)) then {
    +      format["Removed explosive explosion marker, %1, %2", _markName, _explosiveDisp] SYSCHAT;
    +      OCAPEXTLOG(ARR3("Removed explosive explosion marker", _markName, _explosiveDisp));
    +    };
    +    [QGVARMAIN(handleMarker), ["DELETED", _markName]] call CBA_fnc_localEvent;
    +  }, [_markName, _explosiveDisp], GVAR(captureFrameNo) * 10] call CBA_fnc_waitAndExecute;
    +
    +}, [_explosive, _explosiveDisp, _unit, _placedPos, _markName, _int]] call CBA_fnc_waitUntilAndExecute;
    diff --git a/x/ocap/addons/recorder/fnc_addEventMission.sqf b/x/ocap/addons/recorder/fnc_addEventMission.sqf
    new file mode 100644
    index 0000000..e245dac
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_addEventMission.sqf
    @@ -0,0 +1,298 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_addEventMission.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_addEventMission
    +
    +Description:
    +  Used for applying mission event handlers. Applied during initialization of OCAP in <OCAP_recorder_fnc_init>.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > call FUNC(addEventMission);
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox, Dell
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +// Section: Event Handlers
    +
    +if (isNil QEGVAR(EH,HandleDisconnect)) then {
    +  // Event Handler: OCAP_EH_HandleDisconnect
    +  // Fired when a player leaves the mission by returning to lobby or disconnecting. Calls <OCAP_recorder_fnc_eh_disconnected>.
    +  EGVAR(EH,HandleDisconnect) = addMissionEventHandler["HandleDisconnect", {
    +    _this call FUNC(eh_disconnected);
    +    false; // ensure we're not overriding disabledAI and persisting an AI unit to replace the player's
    +  }];
    +  OCAPEXTLOG(["Initialized HandleDisconnect EH"]);
    +};
    +
    +if (isNil QEGVAR(EH,PlayerConnected)) then {
    +  // Event Handler: OCAP_EH_PlayerConnected
    +  // Handle for the "PlayerConnected" mission event handler. Fired when a player joins the mission from lobby and appears in the world. Calls <OCAP_recorder_fnc_eh_connected>.
    +  EGVAR(EH,PlayerConnected) = addMissionEventHandler["PlayerConnected", {
    +    _this call FUNC(eh_connected);
    +  }];
    +  OCAPEXTLOG(["Initialized PlayerConnected EH"]);
    +};
    +
    +if (isNil QEGVAR(EH,OnUserAdminStateChanged)) then {
    +  // Event Handler: OCAP_EH_OnUserAdminStateChanged
    +  // Handle for the "OnUserAdminStateChange" mission event handler. Fired when a player's admin status changes. Calls <OCAP_recorder_fnc_eh_onUserAdminStateChanged>.
    +  EGVAR(EH,OnUserAdminStateChanged) = addMissionEventHandler ["OnUserAdminStateChanged", {
    +    _this call FUNC(eh_onUserAdminStateChanged);
    +  }];
    +  OCAPEXTLOG(["Initialized OnUserAdminStateChanged EH"]);
    +};
    +
    +if (isNil QEGVAR(EH,EntityKilled)) then {
    +  // Event Handler: OCAP_EH_EntityKilled
    +  // Handle for the "EntityKilled" mission event handler. Fired when an entity is killed. Calls <OCAP_recorder_fnc_eh_killed>.
    +  EGVAR(EH,EntityKilled) = addMissionEventHandler ["EntityKilled", {
    +    _this call FUNC(eh_killed);
    +  }];
    +  OCAPEXTLOG(["Initialized EntityKilled EH"]);
    +};
    +
    +if (isNil QEGVAR(EH,EntityRespawned)) then {
    +  // Event Handler: OCAP_EH_EntityRespawned
    +  // Handle for the "EntityRespawned" mission event handler. Fired when an entity is respawned. Sets new body to not-killed and calls <OCAP_recorder_fnc_addUnitEventHandlers> on it. Then excludes corpse from further capture.
    +  EGVAR(EH,EntityRespawned) = addMissionEventHandler ["EntityRespawned", {
    +    params ["_entity", "_corpse"];
    +
    +    // Reset unit back to normal
    +    _entity setvariable [QGVARMAIN(isKilled), false];
    +
    +    // Stop tracking old unit
    +    if (_corpse getVariable [QGVARMAIN(isInitialized), false]) then {
    +      _corpse setVariable [QGVARMAIN(exclude), true];
    +
    +      [_entity, true] spawn FUNC(addUnitEventHandlers);
    +    };
    +  }];
    +  OCAPEXTLOG(["Initialized EntityRespawned EH"]);
    +};
    +
    +
    +if (isNil QEGVAR(EH,MPEnded)) then {
    +  // Event Handler: OCAP_EH_MPEnded
    +  // Handle for the "MPEnded" mission event handler. Fired on the MPEnded mission event. This is used to automatically save and export if <OCAP_settings_saveMissionEnded> is true and <OCAP_settings_minMissionTime> was reached.
    +  EGVAR(EH,MPEnded) = addMissionEventHandler ["MPEnded", {
    +    if (EGVAR(settings,saveMissionEnded) && (GVAR(captureFrameNo) * GVAR(frameCaptureDelay)) >= GVAR(minMissionTime)) then {
    +      ["Mission ended automatically"] call FUNC(exportData);
    +    };
    +  }];
    +  OCAPEXTLOG(["Initialized MPEnded EH"]);
    +};
    +
    +if (isNil QEGVAR(EH,Ended)) then {
    +  // Event Handler: OCAP_EH_Ended
    +  // Handle for the "Ended" mission event handler. Fired on the singleplayer Ended mission event. This is used to automatically save and export if <OCAP_settings_saveMissionEnded> is true and <OCAP_settings_minMissionTime> was reached. Kept in just in case this event triggers.
    +  EGVAR(EH,Ended) = addMissionEventHandler ["Ended", {
    +    if (EGVAR(settings,saveMissionEnded) && (GVAR(captureFrameNo) * GVAR(frameCaptureDelay)) >= GVAR(minMissionTime)) then {
    +      ["Mission ended automatically"] call FUNC(exportData);
    +    };
    +  }];
    +  OCAPEXTLOG(["Initialized Ended EH"]);
    +};
    +
    +
    +// Add event saving markers
    +if (isNil QEGVAR(listener,markers)) then {
    +  call FUNC(handleMarkers);
    +};
    +
    +
    +
    +// Section: CBA Events
    +
    +/*
    +  Variables: CBA Listener Handles
    +
    +  OCAP_listener_aceThrowing - Handle for <ace_advanced_throwing_throwFiredXEH> listener.
    +  OCAP_listener_aceExplosives - Handle for <ace_explosives_place> listener.
    +  OCAP_listener_customEvent - Handle for <OCAP_customEvent> listener.
    +  OCAP_listener_counterInit - Handle for <OCAP_counterInit> listener.
    +  OCAP_listener_counterEvent - Handle for <OCAP_counterEvent> listener.
    +  OCAP_counter_sides - Sides that are tracked by the custom counter system. [Array]
    +  OCAP_listener_record - Handle for <OCAP_record> listener.
    +  OCAP_listener_pause - Handle for <OCAP_pause> listener.
    +  OCAP_listener_exportData - Handle for <OCAP_exportData> listener.
    +*/
    +
    +
    +if (isClass (configFile >> "CfgPatches" >> "ace_advanced_throwing")) then {
    +  if (isNil QEGVAR(listener,aceThrowing)) then {
    +    /*
    +      CBA Event: ace_advanced_throwing_throwFiredXEH
    +      Fired when a throwable is primed. This is a global event the server will handle and forward to <OCAP_recorder_fnc_eh_firedMan>. Created only if PBO "ace_advanced_throwing" is loaded.
    +    */
    +    EGVAR(listener,aceThrowing) = ["ace_advanced_throwing_throwFiredXEH", {
    +      _this call FUNC(eh_firedMan)
    +    }] call CBA_fnc_addEventHandler;
    +    OCAPEXTLOG(["Initialized ACE Throwing listener"]);
    +  };
    +};
    +
    +if (isClass (configFile >> "CfgPatches" >> "ace_explosives")) then {
    +  if (isNil QEGVAR(listener,aceExplosives)) then {
    +    /*
    +      CBA Event: ace_explosives_place
    +      Event listener for ACE3 global event indicating a mine has been placed and armed. Calls <OCAP_recorder_fnc_aceExplosives> when triggered. Created only if PBO "ace_explosives" is loaded.
    +    */
    +    EGVAR(listener,aceExplosives) = ["ace_explosives_place", {
    +      call FUNC(aceExplosives);
    +    }] call CBA_fnc_addEventHandler;
    +    OCAPEXTLOG(["Initialized ACE Explosives listener"]);
    +  };
    +};
    +
    +
    +/*
    +  CBA Event: OCAP_customEvent
    +  Description:
    +    Event listener for custom event text to be added to the timeline. Calls <OCAP_recorder_fnc_handleCustomEvent> when triggered.
    +
    +  Parameters:
    +    0 - Event name [String]
    +    1 - Event data [Array]
    +      1.0 - Always "generalEvent" [String]
    +      1.1 - Custom event text [String]
    +
    +  Example:
    +    > ["OCAP_customEvent", ["generalEvent", "The warehouse has been secured!"]] call CBA_fnc_serverEvent;
    +    > [QGVARMAIN(customEvent), ["generalEvent", "The warehouse has been secured!"]] call CBA_fnc_serverEvent;
    +
    +*/
    +if (isNil QEGVAR(listener,customEvent)) then {
    +  EGVAR(listener,customEvent) = [QGVARMAIN(customEvent), {
    +    _this call FUNC(handleCustomEvent);
    +  }] call CBA_fnc_addEventHandler;
    +  OCAPEXTLOG(["Initialized customEvent listener"]);
    +};
    +
    +/*
    +  CBA Event: OCAP_counterInit
    +  Description:
    +    Meant for use in custom tracking of points or score between two sides. Separate from BIS_fnc_respawnTickets. Initializes the system. Calls <OCAP_recorder_fnc_counterInit> when triggered.
    +
    +  Parameters:
    +    0 - Event name [String]
    +    1 - Key/value for one or more sides [Array]
    +      1.0 - Pair [Array]
    +        1.0.0 - Side <SIDE>
    +        1.0.1 - Initial value [Number]
    +
    +  Example:
    +    (start code)
    +    ["OCAP_counterInit", [
    +      [west, 0],
    +      [east, 0]
    +    ]] call CBA_fnc_serverEvent;
    +
    +    [QGVARMAIN(counterInit), [
    +      [west, 0],
    +      [east, 0]
    +    ]] call CBA_fnc_serverEvent;
    +    (end code)
    +*/
    +if (isNil QEGVAR(listener,counterInit)) then {
    +  EGVAR(listener,counterInit) = [QGVARMAIN(counterInit), {
    +    EGVAR(counter,sides) = _this apply {_x#0};
    +    [QGVARMAIN(customEvent), ["counterInit", EGVAR(counter,sides)]] call CBA_fnc_localEvent;
    +    {
    +      [QGVARMAIN(counterEvent), _x] call CBA_fnc_serverEvent;
    +    } forEach _this;
    +    [_thisType, _thisId] call CBA_fnc_removeEventHandler;
    +  }] call CBA_fnc_addEventHandlerArgs;
    +  OCAPEXTLOG(["Initialized counterInit listener"]);
    +};
    +
    +/*
    +  CBA Event: OCAP_counterEvent
    +  Description:
    +    Meant for use in custom tracking of points or score between two sides. Separate from BIS_fnc_respawnTickets. Updates the system. Calls <OCAP_recorder_fnc_counterEvent> when triggered.
    +
    +  Parameters:
    +    0 - Event name [String]
    +    1 - Event data [Array]
    +      1.0 - Side <SIDE>
    +      1.1 - Value to set [Number]
    +
    +  Example:
    +    > ["OCAP_counterEvent", [west, 1]] call CBA_fnc_serverEvent;
    +*/
    +if (isNil QEGVAR(listener,counterEvent)) then {
    +  EGVAR(listener,counterEvent) = [QGVARMAIN(counterEvent), {
    +    if (isNil QEGVAR(counter,sides)) exitWith {};
    +    if (typeName (_this#0) != "SIDE") exitWith {};
    +    if !((_this#0) in EGVAR(counter,sides)) exitWith {};
    +
    +    private _scores = [];
    +    {
    +      if ((_this#0) isEqualTo _x) then {_scores pushBack (_this#1)};
    +    } forEach EGVAR(counter,sides);
    +    [QGVARMAIN(customEvent), ["counterSet", _scores]] call CBA_fnc_localEvent;
    +  }] call CBA_fnc_addEventHandler;
    +  OCAPEXTLOG(["Initialized counterEvent listener"]);
    +};
    +
    +/*
    +  CBA Event: OCAP_record
    +  Description:
    +    Used to start or resume recording. Calls <OCAP_recorder_fnc_startRecording> when triggered.
    +
    +  Example:
    +    > ["OCAP_record"] call CBA_fnc_serverEvent;
    +*/
    +if (isNil QEGVAR(listener,record)) then {
    +  EGVAR(listener,record) = [QGVARMAIN(record), {
    +    call FUNC(startRecording);
    +  }] call CBA_fnc_addEventHandler;
    +  OCAPEXTLOG(["Initialized record listener"]);
    +};
    +
    +/*
    +  CBA Event: OCAP_pause
    +  Description:
    +    Used to pause recording. Calls <OCAP_recorder_fnc_stopRecording> when triggered.
    +
    +  Example:
    +    > ["OCAP_pause"] call CBA_fnc_serverEvent;
    +*/
    +if (isNil QEGVAR(listener,pause)) then {
    +  EGVAR(listener,pause) = [QGVARMAIN(pause), {
    +    call FUNC(stopRecording);
    +  }] call CBA_fnc_addEventHandler;
    +  OCAPEXTLOG(["Initialized pause listener"]);
    +};
    +
    +/*
    +  CBA Event: OCAP_exportData
    +  Description:
    +    Used to stop recording & signal the extension to save and upload it to the web component. Calls <OCAP_recorder_fnc_exportData> when triggered.
    +
    +    *Will always bypass <OCAP_settings_minMissionTime>*.
    +
    +  Parameters:
    +    0 - Event name [String]
    +    1 - Event data [Array]
    +      1.0 - (optional) Winning side <SIDE>
    +      1.1 - (optional) Message describing mission end [String]
    +      1.2 - (optional) Custom save tag (overrides <OCAP_settings_saveTag>) [String]
    +*/
    +if (isNil QEGVAR(listener,exportData)) then {
    +  EGVAR(listener,exportData) = [QGVARMAIN(exportData), {
    +    _this set [3, true];
    +    _this call FUNC(exportData);
    +  }] call CBA_fnc_addEventHandler;
    +  OCAPEXTLOG(["Initialized exportData listener"]);
    +};
    diff --git a/x/ocap/addons/recorder/fnc_addUnitEventHandlers.sqf b/x/ocap/addons/recorder/fnc_addUnitEventHandlers.sqf
    new file mode 100644
    index 0000000..0b7199e
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_addUnitEventHandlers.sqf
    @@ -0,0 +1,43 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_addUnitEventHandlers.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_addUnitEventHandlers
    +
    +Description:
    +  Used for applying unit-specific event handlers to units during initialization. These event handlers will trigger on the server.
    +
    +  Applied during initialization of a unit in <OCAP_recorder_fnc_captureLoop>.
    +
    +  Note: Hit tracking moved to projectile EHs in <OCAP_recorder_fnc_eh_firedMan>
    +
    +Parameters:
    +  _entity - Object to apply event handlers to. [Object]
    +  _respawn - Determines if unit is initialized for the first time, or has respawned and does not need certain handlers reapplied. [[Bool], default: false]
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > [_unit] spawn FUNC(addUnitEventHandlers);
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox, Fank
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +params ["_entity", ["_respawn", false]];
    +
    +
    +// FIREDMAN
    +// Set a serverside variable on the unit with a value of the handle of the FiredMan EH placed on that unit.
    +if ((_entity call BIS_fnc_objectType) # 0 == "Soldier") then {
    +  if (isNil {_entity getVariable QGVARMAIN(FiredManEH)}) then {
    +    _entity setVariable [
    +      QGVARMAIN(FiredManEH),
    +      _entity addEventHandler ["FiredMan", { _this call FUNC(eh_firedMan); }]
    +    ];
    +  };
    +};
    diff --git a/x/ocap/addons/recorder/fnc_adminUIcontrol.sqf b/x/ocap/addons/recorder/fnc_adminUIcontrol.sqf
    new file mode 100644
    index 0000000..8d09436
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_adminUIcontrol.sqf
    @@ -0,0 +1,156 @@
    +/*
    +	  FILE: fnc_adminUIControl.sqf
    +
    +	  FUNCTION: OCAP_recorder_fnc_adminUIControl
    +
    +	  Description:
    +	    Runs checks to determine if a player should have the administrative diary entry added or removed upon joining the mission or logging in/out as admin.
    +
    +	    - <OCAP_recorder_fnc_eh_connected> at mission start to determine if a player is in <OCAP_administratorList>
    +	    - <OCAP_recorder_fnc_eh_onUserAdminStateChanged> to add/remove when a player logs in or out as admin on the server
    +
    +	  Parameters:
    +	    _PID - PlayerID indicating unique network client on the server [String]
    +	    _event - Event that triggered this call [[String], one of: "connect", "login", "logout"]
    +
    +	  Returns:
    +	    Nothing
    +
    +	  Examples:
    +	    > ["1234567890", "connect"] call FUNC(adminUIControl);
    +
    +	  Public:
    +	    No
    +
    +	  Author:
    +	    IndigoFox
    +*/
    +
    +#include "script_component.hpp"
    +
    +if (!GVARMAIN(enabledAdministratorUI)) exitWith {};
    +
    +params [
    +	"_PID",
    +	["_event", "", [""]]
    +];
    +
    +if (isNil "_PID") exitWith {};
    +
    +private _userInfo = getUserInfo _PID;
    +if (_userInfo isEqualTo []) exitWith {};
    +_userInfo params ["_playerID", "_owner", "_playerUID"];
    +_unit = _userInfo select 10;
    +
    +_fnc_addControls = {
    +	params ["_owner", "_unit"];
    +	  // add controls to diary entry
    +	{
    +		[{
    +			getClientStateNumber > 9 && !isNull player
    +		}, {
    +			player createDiarySubject [
    +				QEGVAR(diary,adminControls_subject),
    +				"OCAP Admin",
    +				"\A3\ui_f\data\igui\cfg\simpleTasks\types\interact_ca.paa"
    +			];
    +
    +			EGVAR(diary,adminControls_record) = player createDiaryRecord [
    +				QEGVAR(diary,adminControls_subject),
    +				[
    +					"Controls",
    +					format[
    +						"<br/>These controls can be used to Start Recording, Pause Recording, and Save/Export the Recording. On the backend, these use the corresponding CBA server events that can be found in the documentation. Because of this, they override the default minimum duration required to save, so be aware that clicking ""Stop and Export Recording"" will save and upload your current recording regardless of its duration.<br/><br/><execute expression='[""%1""] call CBA_fnc_serverEvent;
    +						'>Start/Resume Recording</execute><br/><execute expression='[""%2""] call CBA_fnc_serverEvent;'>Pause Recording</execute><br/><execute expression='[""%3""] call CBA_fnc_serverEvent;'>Stop and Export Recording</execute>",
    +						QGVARMAIN(record),
    +						QGVARMAIN(pause),
    +						QGVARMAIN(exportData)
    +					]
    +				]
    +			];
    +		}] call CBA_fnc_waitUntilAndExecute;
    +	} remoteExec ["call", _owner];
    +
    +	  // set variable on unit
    +	_unit setVariable [QGVARMAIN(hasAdminControls), true];
    +};
    +
    +_fnc_removeControls = {
    +	params ["_owner", "_unit"];
    +	{
    +		player removeDiarySubject QEGVAR(diary,adminControls_subject);
    +		player setVariable [QGVARMAIN(hasAdminControls), false, 2];
    +	} remoteExec ["call", _owner];
    +
    +	  // Variable: OCAP_hasAdminControls
    +	  // Applied on units processed in <OCAP_recorder_fnc_adminUIControl>. Indicates whether or not they have the administrative diary entry available. Server missionNamespace only.
    +	_unit setVariable [QGVARMAIN(hasAdminControls), false];
    +};
    +
    +// check if admin
    +private _adminUIDs = missionNamespace getVariable [QGVARMAIN(administratorList), nil];
    +
    +if (isNil "_adminUIDs") exitWith {
    +	// At this point, no adminUIDs are defined in missionNamespace or in CBA settings
    +	WARNING("Failed to parse administrator list setting. Please check its value!");
    +
    +	switch (_event) do {
    +		case "connect": {
    +			// A player just joined the mission and no admin list exists - skip
    +		};
    +		case "login": {
    +			// A player just logged in so add controls if they don't already have them
    +			if !(_unit getVariable [QGVARMAIN(hasAdminControls), false]) then {
    +				[_owner, _unit] call _fnc_addControls;
    +				if (GVARMAIN(isDebug)) then {
    +					format["%1 was granted OCAP control by logging in as admin", name _unit] SYSCHAT;
    +				};
    +			};
    +		};
    +		case "logout": {
    +			// A player just logged out so remove controls if they have them
    +			if (_unit getVariable [QGVARMAIN(hasAdminControls), false]) then {
    +				[_owner, _unit] call _fnc_removeControls;
    +				if (GVARMAIN(isDebug)) then {
    +					format["%1 had their admin controls removed due to logging out from admin", name _unit] SYSCHAT;
    +				};
    +			};
    +		};
    +		default {};
    +	};
    +};
    +
    +// admin list is defined, so we check if the player is listed by playerUID
    +private _inAdminList = _playerUID in _adminUIDs;
    +
    +switch (_event) do {
    +	case "connect": {
    +		// A player just joined the mission
    +		    // if they are an admin, we add the diary entry
    +		if (_inAdminList) then {
    +			[_owner, _unit] call _fnc_addControls;
    +			if (GVARMAIN(isDebug)) then {
    +				format["%1 was granted OCAP control due to being in the administratorList", name _unit] SYSCHAT;
    +			};
    +		};
    +	};
    +	case "login": {
    +		// A player just logged in so add controls if they don't already have them
    +		if !(_unit getVariable [QGVARMAIN(hasAdminControls), false]) then {
    +			[_owner, _unit] call _fnc_addControls;
    +			if (GVARMAIN(isDebug)) then {
    +				format["%1 was granted OCAP control by logging in as admin", name _unit] SYSCHAT;
    +			};
    +		};
    +	};
    +	case "logout": {
    +		// A player just logged out so remove controls if they have them
    +		if (_unit getVariable [QGVARMAIN(hasAdminControls), false]) then {
    +			[_owner, _unit] call _fnc_removeControls;
    +			if (GVARMAIN(isDebug)) then {
    +				format["%1 had their admin controls removed due to logging out from admin", name _unit] SYSCHAT;
    +			};
    +		};
    +	};
    +	default {};
    +};
    diff --git a/x/ocap/addons/recorder/fnc_captureLoop.sqf b/x/ocap/addons/recorder/fnc_captureLoop.sqf
    new file mode 100644
    index 0000000..05086a9
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_captureLoop.sqf
    @@ -0,0 +1,208 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_captureLoop.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_captureLoop
    +
    +Description:
    +
    +  This function is run unscheduled and creates a CBA PerFrameHandler object, a logic object which executes code every specified interval (<OCAP_settings_frameCaptureDelay>) while a condition (<SHOULDSAVEEVENTS>) is true.
    +
    +  Iterates through units and vehicles, declares they exist, and conditionally sends their information to the extension to populate recording data.
    +
    +  This is the core processing loop that determines when new units enter the world, all the details about them, classifies which to exclude, and determines their health/life status. It has both unit and vehicle tracking.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  >  call FUNC(captureLoop);
    +
    +Public:
    +  No
    +
    +Author:
    +  Dell, Zealot, IndigoFox, Fank
    +---------------------------------------------------------------------------- */
    +
    +#include "script_component.hpp"
    +
    +if (!isNil QGVAR(PFHObject)) then {
    +  [GVAR(PFHObject)] call CBA_fnc_deletePerFrameHandlerObject;
    +  GVAR(PFHObject) = nil;
    +};
    +if (isNil QGVAR(startTime)) then {
    +  GVAR(startTime) = time;
    +  OCAPEXTLOG(ARR3(__FILE__, QGVAR(recording) + " started, time:", GVAR(startTime)));
    +  LOG(ARR3(__FILE__, QGVAR(recording) + " started, time:", GVAR(startTime)));
    +};
    +
    +// Variable: OCAP_PFHObject
    +// The CBA PerFrameHandler object that is created and used to run the capture loop.
    +GVAR(PFHObject) = [
    +  {
    +    private _loopStart = diag_tickTime;
    +
    +    if (GVAR(captureFrameNo) == 10 || (GVAR(captureFrameNo) > 10 && EGVAR(settings,trackTimes) && GVAR(captureFrameNo) % EGVAR(settings,trackTimeInterval) == 0)) then {
    +      [] call FUNC(updateTime);
    +    };
    +
    +    // every 15 frames of recording check respawn ticket state of each of three sides
    +    if (GVAR(captureFrameNo) % (30 / GVAR(frameCaptureDelay)) == 0 && EGVAR(settings,trackTickets)) then {
    +      private _scores = [];
    +      {
    +        _scores pushBack ([_x] call BIS_fnc_respawnTickets);
    +      } forEach [missionNamespace, east, west, independent];
    +      [QGVARMAIN(customEvent), ["respawnTickets", _scores]] call CBA_fnc_localEvent;
    +    };
    +
    +    // update diary record every 320 frames
    +    if (GVAR(captureFrameNo) % (320 / GVAR(frameCaptureDelay)) == 0) then {
    +      publicVariable QGVAR(captureFrameNo);
    +      {
    +        player createDiaryRecord [
    +          "OCAPInfo",
    +          [
    +            "Status",
    +            ("<font color='#CCCCCC'>Capture frame: " + str (missionNamespace getVariable [QGVAR(captureFrameNo), "[not yet received]"]) + "</font>")
    +          ]
    +        ];
    +      } remoteExec ["call", 0, false];
    +    };
    +
    +    {
    +      if !(_x getVariable [QGVARMAIN(isInitialized), false]) then {
    +        if (
    +          _x isKindOf "Logic"
    +        ) exitWith {
    +          _x setVariable [QGVARMAIN(exclude), true, true];
    +          _x setVariable [QGVARMAIN(isInitialized), true, true];
    +        };
    +        _x setVariable [QGVARMAIN(id), GVAR(nextId)];
    +        [":NEW:UNIT:", [
    +          GVAR(captureFrameNo), //1
    +          GVAR(nextId), //2
    +          name _x, //3
    +          groupID (group _x), //4
    +          str side group _x, //5
    +          BOOL(isPlayer _x), //6
    +          roleDescription _x // 7
    +        ]] call EFUNC(extension,sendData);
    +        [_x] spawn FUNC(addUnitEventHandlers);
    +        GVAR(nextId) = GVAR(nextId) + 1;
    +        _x setVariable [QGVARMAIN(isInitialized), true, true];
    +      };
    +      if !(_x getVariable [QGVARMAIN(exclude), false]) then {
    +        private _unitRole = _x getVariable [QGVARMAIN(unitType), ""];
    +        if (GVAR(captureFrameNo) % 10 == 0 || _unitRole == "") then {
    +          _unitRole = [_x] call FUNC(getUnitType);
    +          _x setVariable [QGVARMAIN(unitType), _unitRole];
    +        };
    +
    +        private _lifeState = 0;
    +        if (alive _x) then {
    +          if (EGVAR(settings,preferACEUnconscious) && !isNil "ace_common_fnc_isAwake") then {
    +            _lifeState = if ([_x] call ace_common_fnc_isAwake) then {1} else {2};
    +          } else {
    +            _lifeState = if (lifeState _x isEqualTo "INCAPACITATED") then {2} else {1};
    +          };
    +        };
    +
    +        _pos = getPosASL _x;
    +
    +        _unitData = [
    +          (_x getVariable QGVARMAIN(id)), //1
    +          _pos, //2
    +          round getDir _x, //3
    +          _lifeState, //4
    +          BOOL(!((vehicle _x) isEqualTo _x)),  //5
    +          if (alive _x) then {name _x} else {""}, //6
    +          BOOL(isPlayer _x), //7
    +          _unitRole //8
    +        ];
    +
    +        if (_x getVariable ["unitData", []] isNotEqualTo _unitData) then {
    +          [":UPDATE:UNIT:", _unitData] call EFUNC(extension,sendData);
    +        };
    +        _x setVariable [QGVARMAIN(unitData), _unitData];
    +      };
    +      false
    +    } count (allUnits + allDeadMen);
    +
    +    {
    +      if !(_x getVariable [QGVARMAIN(isInitialized), false]) then {
    +        _vehType = typeOf _x;
    +        _class = _vehType call FUNC(getClass);
    +        private _toExcludeKind = false;
    +        if (count (parseSimpleArray EGVAR(settings,excludeKindFromRecord)) > 0) then {
    +          private _vic = _x;
    +          {
    +            if (_vic isKindOf _x) exitWith {
    +              _toExcludeKind = true;
    +            };
    +          } forEach (parseSimpleArray EGVAR(settings,excludeKindFromRecord));
    +        };
    +        private _toExcludeClass = false;
    +        if (count (parseSimpleArray EGVAR(settings,excludeClassFromRecord)) > 0) then {
    +          {
    +            if (typeOf _vic == _x) exitWith {
    +              _toExcludeClass = true;
    +            };
    +          } forEach (parseSimpleArray EGVAR(settings,excludeClassFromRecord));
    +        };
    +        if ((_class isEqualTo "unknown") || _toExcludeKind || _toExcludeClass) exitWith {
    +          LOG(ARR2("WARNING: vehicle is defined as 'unknown' or exclude:", _vehType));
    +          _x setVariable [QGVARMAIN(isInitialized), true, true];
    +          _x setVariable [QGVARMAIN(exclude), true, true];
    +        };
    +
    +        _x setVariable [QGVARMAIN(id), GVAR(nextId)];
    +        [":NEW:VEH:", [
    +          GVAR(captureFrameNo), //1
    +          GVAR(nextId), //2
    +          _class, //3
    +          getText (configFile >> "CfgVehicles" >> _vehType >> "displayName") //4
    +        ]] call EFUNC(extension,sendData);
    +        [_x] spawn FUNC(addUnitEventHandlers);
    +        GVAR(nextId) = GVAR(nextId) + 1;
    +        _x setVariable [QGVARMAIN(vehicleClass), _class];
    +        _x setVariable [QGVARMAIN(isInitialized), true, true];
    +      };
    +      if !(_x getVariable [QGVARMAIN(exclude), false]) then {
    +        private _crew = [];
    +        {
    +          if (_x getVariable [QGVARMAIN(isInitialized), false]) then {
    +            _crew pushBack (_x getVariable QGVARMAIN(id));
    +          }; false
    +        } count (crew _x);
    +        _pos = getPosASL _x;
    +        [":UPDATE:VEH:", [
    +          (_x getVariable QGVARMAIN(id)), //1
    +          _pos, //2
    +          round getDir _x, //3
    +          BOOL(alive _x), //4
    +          _crew, //5
    +          GVAR(captureFrameNo) // 6
    +        ]] call EFUNC(extension,sendData);
    +      };
    +      false
    +    } count vehicles;
    +
    +    if (GVARMAIN(isDebug)) then {
    +      private _logStr = format["Frame %1 processed in %2ms", GVAR(captureFrameNo), diag_tickTime - _loopStart];
    +      OCAPEXTLOG([_logStr]);
    +      _logStr SYSCHAT;
    +    };
    +
    +    GVAR(captureFrameNo) = GVAR(captureFrameNo) + 1;
    +    publicVariable QGVAR(captureFrameNo);
    +  },
    +  GVAR(frameCaptureDelay), // delay
    +  [], // args
    +  {}, // code, executed when added
    +  {}, // code, executed when removed
    +  {SHOULDSAVEEVENTS}, // if true, execute PFH cycle
    +  {false} // if true, delete object
    +] call CBA_fnc_createPerFrameHandlerObject;
    diff --git a/x/ocap/addons/recorder/fnc_eh_connected.sqf b/x/ocap/addons/recorder/fnc_eh_connected.sqf
    new file mode 100644
    index 0000000..a24aeb1
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_eh_connected.sqf
    @@ -0,0 +1,40 @@
    +/*
    +  FILE: fnc_eh_connected.sqf
    +
    +  FUNCTION: OCAP_recorder_fnc_eh_connected
    +
    +  Description:
    +
    +    This function uses the <OCAP_EH_Connected> event handler to log "connected" events to the timeline.
    +
    +    It also calls <OCAP_recorder_fnc_adminUIControl> to apply the admin UI if the player is in <OCAP_administratorList>.
    +
    +  Parameters:
    +    See the wiki for details. <https://community.bistudio.com/wiki/Arma_3:_Mission_Event_Handlers#PlayerConnected>
    +
    +  Returns:
    +    Nothing
    +
    +  Examples:
    +    > call FUNC(eh_connected);
    +
    +  Public:
    +    No
    +
    +  Author:
    +    IndigoFox
    +*/
    +
    +#include "script_component.hpp"
    +params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"];
    +
    +// skip for server 'connected' message
    +if (_owner isEqualTo 2) exitWith {};
    +
    +// log to timeline
    +[":EVENT:",
    +  [GVAR(captureFrameNo), "connected", _this select 2]
    +] call EFUNC(extension,sendData);
    +
    +// trigger admin control check for all connecting players
    +[_idstr, "connect"] call FUNC(adminUIcontrol);
    diff --git a/x/ocap/addons/recorder/fnc_eh_disconnected.sqf b/x/ocap/addons/recorder/fnc_eh_disconnected.sqf
    new file mode 100644
    index 0000000..7bf993f
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_eh_disconnected.sqf
    @@ -0,0 +1,38 @@
    +/*
    +  FILE: fnc_eh_disconnected.sqf
    +
    +  FUNCTION: OCAP_recorder_fnc_eh_disconnected
    +
    +  Description:
    +
    +    This function uses the <OCAP_EH_HandleDisconnect> event handler to log "disconnected" events to the timeline. It will exclude any body left over from further recording.
    +
    +  Parameters:
    +    See the wiki for details. <https://community.bistudio.com/wiki/Arma_3:_Mission_Event_Handlers#HandleDisconnect>
    +
    +  Returns:
    +    False [Bool]
    +
    +  Examples:
    +    > call FUNC(eh_disconnected);
    +
    +  Public:
    +    No
    +
    +  Author:
    +    IndigoFox
    +*/
    +
    +#include "script_component.hpp"
    +
    +params ["_unit", "_id", "_uid", "_name"];
    +
    +[":EVENT:",
    +	[GVAR(captureFrameNo), "disconnected", _name]
    +] call EFUNC(extension,sendData);
    +
    +if (_unit getVariable [QGVARMAIN(isInitialized), false]) then {
    +	_unit setVariable [QGVARMAIN(exclude), true];
    +};
    +
    +false;
    diff --git a/x/ocap/addons/recorder/fnc_eh_firedMan.sqf b/x/ocap/addons/recorder/fnc_eh_firedMan.sqf
    new file mode 100644
    index 0000000..03ad786
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_eh_firedMan.sqf
    @@ -0,0 +1,343 @@
    +/* ----------------------------------------------------------------------------
    +	FILE: fnc_eh_firedMan.sqf
    +
    +	FUNCTION: OCAP_recorder_fnc_eh_firedMan
    +
    +	Description:
    +	  Tracks bullet and non-bullet projectiles. This is the code triggered when a unit firing is detected by the "FiredMan" Event Handler applied to units during <OCAP_recorder_fnc_addUnitEventHandlers>.
    +
    +	Parameters:
    +	  _firer - Unit the event handler is assigned to (the instigator) [Object]
    +	  _weapon - Fired weapon [String]
    +	  _muzzle - Muzzle that was used [String]
    +	  _mode - Current mode of the fired weapon [String]
    +	  _ammo - className of ammo used [String]
    +	  _magazine - className of magazine used [String]
    +	  _projectile - Object of the projectile that was shot out [Object]
    +	  _vehicle - if weapon is vehicle weapon, otherwise objNull [Object]
    +
    +	Returns:
    +	  Nothing
    +
    +	Examples:
    +	  > [_firer, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile, _vehicle] call FUNC(eh_firedMan);
    +
    +	Public:
    +	  No
    +
    +	Author:
    +	  IndigoFox, Dell
    +
    +---------------------------------------------------------------------------- */
    +
    +/*
    +	  Variable: OCAP_lastFired
    +	  Indicates a formatted string of the last weapon and magazine type fired by the unit. Used for logging hits/kills. Applied to a firing unit.
    +*/
    +
    +/*
    +	  Event Handlers: Projectiles (Bullets)
    +	  Deleted - Makes extension call to draw a fire-line between the firer and the final destination.
    +	  Explode - Makes extension call to draw a fire-line between the firer and the final destination.
    +	  HitPart - Triggered when a projectile hits a part of a unit. Calls <OCAP_recorder_fnc_eh_projectileHit>.
    +	  HitExplosion - Triggered when a projectile explodes and damages a part of a unit. Calls <OCAP_recorder_fnc_eh_projectileHit>.
    +
    +	  Event Handlers: Projectiles (Non-Bullets)
    +	  Deleted - Triggered when a non-bullet projectile is deleted. Updates marker position, then removes it 3 frames later.
    +	  Explode - Triggered when a non-bullet projectile explodes. Updates marker position, then removes it 3 frames later.
    +	  HitPart - Triggered when a projectile hits a part of a unit. Calls <OCAP_recorder_fnc_eh_projectileHit>.
    +	  HitExplosion - Triggered when a projectile explodes and damages a part of a unit. Calls <OCAP_recorder_fnc_eh_projectileHit>.
    +*/
    +
    +/*
    +	  CBA Events: Projectiles
    +	  OCAP_recorder_addDebugBullet - Triggered when a bullet is fired and the debug mode is enabled. Shares recent bullet data to all clients.
    +	  OCAP_recorder_addDebugMagIcon - Triggered when a non-bullet projectile is fired and the debug mode is enabled. Shares recent data to all clients.
    +*/
    +
    +#include "script_component.hpp"
    +
    +if (!SHOULDSAVEEVENTS) exitWith {};
    +
    +params ["_firer", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle"];
    +
    +private _initialProjPos = getPosASL _projectile;
    +if (getPos _firer distance _initialProjPos > 50 || vehicle _firer isKindOf "Air") then {
    +	// if projectile in unscheduled environment is > 50m from FiredMan then likely remote controlled
    +	  // we should find the actual firing entity
    +	private _nearest = [_initialProjPos, allUnits select {
    +		!isPlayer _x
    +	}, 75] call CBA_fnc_getNearest;
    +	if (count _nearest > 0) then {
    +		_firer = _nearest#0;
    +	};
    +};
    +
    +// missionNamespace getVariable ["bis_fnc_moduleRemoteControl_unit", _firer];
    +// _unit getVariable ["BIS_fnc_moduleRemoteControl_owner", objNull];
    +
    +// not sent in ACE Throwing events
    +if (isNil "_vehicle") then {
    +	_vehicle = objNull
    +};
    +if (!isNull _vehicle) then {
    +	_projectile setShotParents [_vehicle, _firer];
    +} else {
    +	_projectile setShotParents [_firer, _firer];
    +};
    +
    +private _frame = GVAR(captureFrameNo);
    +
    +private _firerId = (_firer getVariable [QGVARMAIN(id), -1]);
    +if (_firerId == -1) exitWith {};
    +
    +// set the firer's lastFired var as this weapon, so subsequent kills are logged accurately
    +([_weapon, _muzzle, _magazine, _ammo] call FUNC(getWeaponDisplayData)) params ["_muzzleDisp", "_magDisp"];
    +
    +private _wepString = "";
    +if (!isNull _vehicle) then {
    +	_wepString = format["%1 [%2]", (configOf _vehicle) call BIS_fnc_displayName, _wepString];
    +} else {
    +	_wepString = format["%1 [%2]", _muzzleDisp, _magDisp];
    +};
    +
    +_firer setVariable [QGVARMAIN(lastFired), _wepString];
    +(vehicle _firer) setVariable [QGVARMAIN(lastFired), _wepString];
    +
    +// _ammoSimType
    +// "ShotGrenade" // M67
    +// "ShotRocket" // S-8
    +// "ShotMissile" // R-27
    +// "ShotShell" // VOG-17M, HE40mm
    +// "ShotMine" // Satchel charge
    +// "ShotIlluminating" // 40mm_green Flare
    +// "ShotSmokeX"; // M18 Smoke
    +// "ShotCM" // Plane flares
    +// "ShotSubmunition" // Hind minigun, cluster artillery
    +_ammoSimType = getText(configFile >> "CfgAmmo" >> _ammo >> "simulation");
    +
    +// Save marker data to projectile namespace for EH later
    +_projectile setVariable [QGVAR(firer), _firer];
    +_projectile setVariable [QGVAR(firerId), _firerId];
    +
    +// Track hit events for all projectile types
    +_projectile addEventHandler ["HitPart", {
    +	params ["_projectile", "_hitEntity", "_projectileOwner", "_pos", "_velocity", "_normal", "_component", "_radius", "_surfaceType"];
    +	[_hitEntity, _projectileOwner] call FUNC(eh_projectileHit);
    +}];
    +
    +_projectile addEventHandler ["HitExplosion", {
    +	params ["_projectile", "_hitEntity", "_projectileOwner", "_hitThings"];
    +	[_hitEntity, _projectileOwner] call FUNC(eh_projectileHit);
    +}];
    +
    +// BULLET PROJECTILES
    +
    +if (_ammoSimType isEqualTo "shotBullet") exitWith {
    +	// Bullet projectiles
    +	_projectile addEventHandler ["Deleted", {
    +		params ["_projectile"];
    +		_firer = _projectile getVariable [QGVAR(firer), objNull];
    +		_firerId = _projectile getVariable [QGVAR(firerId), -1];
    +		_projectilePos = getPosASL _projectile;
    +
    +		[":FIRED:", [
    +			_firerId,
    +			GVAR(captureFrameNo),
    +			_projectilePos
    +		]] call EFUNC(extension,sendData);
    +
    +		if (GVARMAIN(isDebug)) then {
    +			OCAPEXTLOG(ARR4("FIRED EVENT: BULLET", GVAR(captureFrameNo), _firerId, str _projectilePos));
    +
    +			      // add to clients' map draw array
    +			private _debugArr = [getPosASL _firer, _projectilePos, [side group _firer] call BIS_fnc_sideColor, cba_missionTime];
    +			[QGVAR(addDebugBullet), _debugArr] call CBA_fnc_globalEvent;
    +		};
    +	}];
    +	_projectile addEventHandler ["Explode", {
    +		params ["_projectile", "_pos", "_velocity"];
    +		_firer = _projectile getVariable [QGVAR(firer), objNull];
    +		_firerId = _projectile getVariable [QGVAR(firerId), -1];
    +		_projectilePos = getPosASL _projectile;
    +
    +		[":FIRED:", [
    +			_firerId,
    +			GVAR(captureFrameNo),
    +			_projectilePos
    +		]] call EFUNC(extension,sendData);
    +
    +		if (GVARMAIN(isDebug)) then {
    +			OCAPEXTLOG(ARR4("FIRED EVENT: BULLET", GVAR(captureFrameNo), _firerId, str _projectilePos));
    +
    +			      // add to clients' map draw array
    +			private _debugArr = [getPosASL _firer, _projectilePos, [side group _firer] call BIS_fnc_sideColor, cba_missionTime];
    +			[QGVAR(addDebugBullet), _debugArr] call CBA_fnc_globalEvent;
    +		};
    +	}];
    +};
    +
    +// ALL OTHER PROJECTILES
    +
    +// get data for marker
    +([_weapon, _muzzle, _ammo, _magazine, _projectile, _vehicle, _ammoSimType] call FUNC(getAmmoMarkerData)) params ["_markTextLocal", "_markName", "_markColor", "_markerType"];
    +private _magIcon = getText(configFile >> "CfgMagazines" >> _magazine >> "picture");
    +_projectile setVariable [QGVAR(markName), _markName];
    +
    +// MAKE MARKER for PLAYBACK
    +_firerPos = getPosASL _firer;
    +[QGVARMAIN(handleMarker), ["CREATED", _markName, _firer, _firerPos, _markerType, "ICON", [1, 1], getDirVisual _firer, "Solid", _markColor, 1, _markTextLocal, true]] call CBA_fnc_localEvent;
    +
    +// move marker, then delete marker, when projectile is deleted or explodes
    +_projectile addEventHandler ["Deleted", {
    +	params ["_projectile"];
    +	_markName = _projectile getVariable QGVAR(markName);
    +	_firer = _projectile getVariable QGVAR(firer);
    +	[QGVARMAIN(handleMarker), ["UPDATED", _markName, _firer, getPosASL _projectile, "", "", "", getDir _projectile, "", "", 1]] call CBA_fnc_localEvent;
    +	[{
    +		[QGVARMAIN(handleMarker), ["DELETED", _this]] call CBA_fnc_localEvent;
    +	}, _markName, GVAR(frameCaptureDelay) * 3] call CBA_fnc_waitAndExecute;
    +}];
    +
    +_projectile addEventHandler ["Explode", {
    +	params ["_projectile", "_pos", "_velocity"];
    +	_markName = _projectile getVariable QGVAR(markName);
    +	_firer = _projectile getVariable QGVAR(firer);
    +	[QGVARMAIN(handleMarker), ["UPDATED", _markName, _firer, _pos, "", "", "", getDir _projectile, "", "", 1]] call CBA_fnc_localEvent;
    +	[{
    +		[QGVARMAIN(handleMarker), ["DELETED", _this]] call CBA_fnc_localEvent;
    +	}, _markName, GVAR(frameCaptureDelay) * 3] call CBA_fnc_waitAndExecute;
    +}];
    +
    +// Add to debug
    +if (GVARMAIN(isDebug)) then {
    +	// add to map draw array
    +	private _debugArr = [_projectile, _magIcon, format["%1 %2 - %3", str side group _firer, name _firer, _markTextLocal], [side group _firer] call BIS_fnc_sideColor];
    +	[QGVAR(addDebugMagIcon), _debugArr] call CBA_fnc_globalEvent;
    +};
    +
    +switch (true) do {
    +	case (_ammoSimType in ["shotGrenade", "shotIlluminating", "shotMine", "shotSmokeX", "shotCM"]): {
    +		GVAR(liveGrenades) pushBack [_projectile, _wepString, _firer, getPosASL _projectile, _markName, _markTextLocal, _ammoSimType];
    +	};
    +
    +	default {
    +		// case (_ammoSimType in ["shotMissile", "shotRocket", "shotShell", "shotSubmunitions"]):
    +		GVAR(liveMissiles) pushBack [_projectile, _wepString, _firer, getPosASL _projectile, _markName, _markTextLocal];
    +
    +		if (_ammoSimType isEqualTo "shotSubmunitions") then {
    +			_projectile setVariable [QGVAR(markerData), ([_weapon, _muzzle, _ammo, _magazine, _projectile, _vehicle, _ammoSimType] call FUNC(getAmmoMarkerData))];
    +			_projectile setVariable [QGVAR(EHData), [_this, _subTypes, _magazine, _wepString, _firer, _firerId, _firerPos, _frame, _ammoSimType, _subTypesAmmoSimType]];
    +
    +			            // for every submunition split process here
    +			_projectile addEventHandler ["SubmunitionCreated", {
    +				params ["_projectile", "_submunitionProjectile", "_pos", "_velocity"];
    +				(_projectile getVariable [QGVAR(markerData), []]) params ["_markTextLocal", "_markName", "_markColor", "_markerType"];
    +				(_projectile getVariable [QGVAR(EHData), []]) params ["_EHData", "_subTypes", "_magazine", "_wepString", "_firer", "_firerId", "_firerPos", "_frame", "_ammoSimType", "_subTypesAmmoSimType"];
    +
    +				                // Save marker data to projectile namespace for EH later
    +				_submunitionProjectile setVariable [QGVAR(firer), _firer];
    +				_submunitionProjectile setVariable [QGVAR(firerId), _firerId];
    +				_submunitionProjectile setVariable [QGVAR(markName), _markName];
    +
    +				private _magIcon = getText(configFile >> "CfgMagazines" >> _magazine >> "picture");
    +
    +				                // then get data of submunition to determine how to track it
    +				private _ammoSimType = getText(configFile >> "CfgAmmo" >> (typeOf _submunitionProjectile) >> "simulation");
    +
    +				_submunitionProjectile addEventHandler ["HitPart", {
    +					// Track hit events for all projectile types
    +					params ["_projectile", "_hitEntity", "_projectileOwner", "_pos", "_velocity", "_normal", "_component", "_radius", "_surfaceType"];
    +					[_hitEntity, _projectileOwner] call FUNC(eh_projectileHit);
    +				}];
    +
    +				_submunitionProjectile addEventHandler ["HitExplosion", {
    +					params ["_projectile", "_hitEntity", "_projectileOwner", "_hitThings"];
    +					[_hitEntity, _projectileOwner] call FUNC(eh_projectileHit);
    +				}];
    +
    +				if (_ammoSimType isEqualTo "shotBullet") exitWith {
    +					// Bullet projectiles
    +					_submunitionProjectile addEventHandler ["Deleted", {
    +						params ["_projectile"];
    +						_firer = _projectile getVariable [QGVAR(firer), objNull];
    +						_firerId = _projectile getVariable [QGVAR(firerId), -1];
    +						_projectilePos = getPosASL _projectile;
    +
    +						[":FIRED:", [
    +							_firerId,
    +							GVAR(captureFrameNo),
    +							_projectilePos
    +						]] call EFUNC(extension,sendData);
    +
    +						if (GVARMAIN(isDebug)) then {
    +							// add to clients' map draw array
    +							OCAPEXTLOG(ARR4("FIRED EVENT: BULLET", GVAR(captureFrameNo), _firerId, str _projectilePos));
    +
    +							private _debugArr = [getPosASL _firer, _projectilePos, [side group _firer] call BIS_fnc_sideColor, cba_missionTime];
    +							[QGVAR(addDebugBullet), _debugArr] call CBA_fnc_globalEvent;
    +						};
    +					}];
    +					_submunitionProjectile addEventHandler ["Explode", {
    +						params ["_projectile"];
    +						_firer = _projectile getVariable [QGVAR(firer), objNull];
    +						_firerId = _projectile getVariable [QGVAR(firerId), -1];
    +						_projectilePos = getPosASL _projectile;
    +
    +						[":FIRED:", [
    +							_firerId,
    +							GVAR(captureFrameNo),
    +							_projectilePos
    +						]] call EFUNC(extension,sendData);
    +
    +						if (GVARMAIN(isDebug)) then {
    +							// add to clients' map draw array
    +							OCAPEXTLOG(ARR4("FIRED EVENT: BULLET", GVAR(captureFrameNo), _firerId, str _projectilePos));
    +							private _debugArr = [getPosASL _firer, _projectilePos, [side group _firer] call BIS_fnc_sideColor, cba_missionTime];
    +							[QGVAR(addDebugBullet), _debugArr] call CBA_fnc_globalEvent;
    +						};
    +					}];
    +				};
    +
    +				_submunitionProjectile addEventHandler ["Deleted", {
    +					// move marker, then delete marker, when projectile is deleted or explodes
    +					params ["_projectile"];
    +					_markName = _projectile getVariable QGVAR(markName);
    +					_firer = _projectile getVariable QGVAR(firer);
    +					[QGVARMAIN(handleMarker), ["UPDATED", _markName, _firer, getPosASL _projectile, "", "", "", getDir _projectile, "", "", 1]] call CBA_fnc_localEvent;
    +					[{
    +						[QGVARMAIN(handleMarker), ["DELETED", _this]] call CBA_fnc_localEvent;
    +					}, _markName, GVAR(frameCaptureDelay) * 3] call CBA_fnc_waitAndExecute;
    +				}];
    +
    +				_projectile addEventHandler ["Explode", {
    +					params ["_projectile", "_pos", "_velocity"];
    +					_markName = _projectile getVariable QGVAR(markName);
    +					_firer = _projectile getVariable QGVAR(firer);
    +					[QGVARMAIN(handleMarker), ["UPDATED", _markName, _firer, _pos, "", "", "", getDir _projectile, "", "", 1]] call CBA_fnc_localEvent;
    +					[{
    +						[QGVARMAIN(handleMarker), ["DELETED", _this]] call CBA_fnc_localEvent;
    +					}, _markName, GVAR(frameCaptureDelay) * 3] call CBA_fnc_waitAndExecute;
    +				}];
    +
    +				if (GVARMAIN(isDebug)) then {
    +					// Add to debug
    +					// add to map draw array
    +					private _debugArr = [_projectile, _magIcon, format["%1 %2 - %3", str side group _firer, name _firer, _markTextLocal], [side group _firer] call BIS_fnc_sideColor];
    +					[QGVAR(addDebugMagIcon), _debugArr] call CBA_fnc_globalEvent;
    +				};
    +
    +				switch (true) do {
    +					case (_ammoSimType in ["shotGrenade", "shotIlluminating", "shotMine", "shotSmokeX", "shotCM"]): {
    +						GVAR(liveGrenades) pushBack [_submunitionProjectile, _wepString, _firer, getPosASL _submunitionProjectile, _markName, _markTextLocal, _ammoSimType];
    +					};
    +
    +					default {
    +						// case (_ammoSimType in ["shotMissile", "shotRocket", "shotShell", "shotSubmunitions"]):
    +						GVAR(liveMissiles) pushBack [_submunitionProjectile, _wepString, _firer, getPosASL _submunitionProjectile, _markName, _markTextLocal];
    +					};
    +				};
    +			}];
    +		};
    +	};
    +};
    diff --git a/x/ocap/addons/recorder/fnc_eh_killed.sqf b/x/ocap/addons/recorder/fnc_eh_killed.sqf
    new file mode 100644
    index 0000000..5c88806
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_eh_killed.sqf
    @@ -0,0 +1,96 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_eh_killed.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_eh_killed
    +
    +Description:
    +  Tracks when a unit is killed. This is the code triggered by the <OCAP_EH_EntityKilled> mission event handler.
    +
    +Parameters:
    +  _unit - Object the event handler is assigned to. [Object]
    +  _killer - Object that killed the unit. [Object]
    +  _instigator - Person who pulled the trigger. [Object]
    +  _useEffects - same as useEffects in setDamage alt syntax. [Bool]
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > call FUNC(eh_killed);
    +
    +Public:
    +  No
    +
    +Author:
    +  Dell, IndigoFox, Fank
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +if (!SHOULDSAVEEVENTS) exitWith {};
    +
    +params ["_victim", "_killer", "_instigator"];
    +
    +if !(_victim getvariable [QGVARMAIN(isKilled),false]) then {
    +  _victim setvariable [QGVARMAIN(isKilled),true];
    +
    +  [_victim, _killer, _instigator] spawn {
    +    params ["_victim", "_killer", "_instigator"];
    +
    +    private _killedFrame = GVAR(captureFrameNo);
    +
    +    // allow some time for last-fired variable on killer to be updated
    +    // namely for explosives, shells, grenades explosions, which are updated on impact
    +    sleep GVAR(frameCaptureDelay);
    +
    +    if (_killer == _victim && owner _victim != 2 && EGVAR(settings,preferACEUnconscious) && isClass(configFile >> "CfgPatches" >> "ace_medical_status")) then {
    +      private _time = diag_tickTime;
    +      [_victim, {
    +        _this setVariable ["ace_medical_lastDamageSource", (_this getVariable "ace_medical_lastDamageSource"), 2];
    +      }] remoteExec ["call", _victim];
    +      waitUntil {diag_tickTime - _time > 10 || !(isNil {_victim getVariable "ace_medical_lastDamageSource"})};
    +      _killer = _victim getVariable ["ace_medical_lastDamageSource", _killer];
    +    } else {
    +      _killer
    +    };
    +
    +    if (isNull _instigator) then {
    +      _instigator = [_victim, _killer] call FUNC(getInstigator);
    +    };
    +
    +    // [GVAR(captureFrameNo), "killed", _victimId, ["null"], -1];
    +    private _victimId = _victim getVariable [QGVARMAIN(id), -1];
    +    if (_victimId == -1) exitWith {};
    +    private _eventData = [_killedFrame, "killed", _victimId, ["null"], -1];
    +
    +    if (!isNull _instigator) then {
    +      _killerId = _instigator getVariable [QGVARMAIN(id), -1];
    +      if (_killerId == -1) exitWith {};
    +
    +      private _killerInfo = [];
    +      // if (_instigator isKindOf "CAManBase") then {
    +        _killerInfo = [
    +          _killerId,
    +          ([_instigator] call FUNC(getEventWeaponText))
    +        ];
    +      // } else {
    +      //   _killerInfo = [_killerId];
    +      // };
    +
    +      _eventData = [
    +        _killedFrame,
    +        "killed",
    +        _victimId,
    +        _killerInfo,
    +        round(_instigator distance _victim)
    +      ];
    +
    +      if (GVARMAIN(isDebug)) then {
    +        OCAPEXTLOG(ARR4("KILLED EVENT", _killedFrame, _victimId, _killerId));
    +      };
    +    };
    +
    +
    +
    +    [":EVENT:", _eventData] call EFUNC(extension,sendData);
    +  };
    +};
    diff --git a/x/ocap/addons/recorder/fnc_eh_onUserAdminStateChanged.sqf b/x/ocap/addons/recorder/fnc_eh_onUserAdminStateChanged.sqf
    new file mode 100644
    index 0000000..19e0b3f
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_eh_onUserAdminStateChanged.sqf
    @@ -0,0 +1,37 @@
    +/* ----------------------------------------------------------------------------
    +	FILE: fnc_eh_onUserAdminStateChanged.sqf
    +
    +	FUNCTION: OCAP_recorder_fnc_eh_onUserAdminStateChanged
    +
    +	Description:
    +	  Uses <OCAP_EH_OnUserAdminStateChanged> to detect when someone is has logged in or out of the server and calls <OCAP_recorder_fnc_adminUIControl> to update the admin UI.
    +
    +	Parameters:
    +	  _networkId - The network ID of the player who has logged in or out of the server [String]
    +	  _loggedIn - Whether the player has logged in or out as admin [Boolean]
    +	  _votedIn - Whether the player has been voted in or out of admin [Boolean]
    +
    +	Returns:
    +	  Nothing
    +
    +	Examples:
    +	  > call FUNC(eh_onUserAdminStateChanged);
    +
    +	Public:
    +	  No
    +
    +	Author:
    +	  IndigoFox
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +params ["_networkId", "_loggedIn", "_votedIn"];
    +
    +if (_loggedIn && !_votedIn) exitWith {
    +	// if user has become admin by logging, not voting, trigger control addition check
    +	[_networkId, "login"] call FUNC(adminUIcontrol);
    +};
    +if (!_loggedIn) then {
    +	// if user has logged out, trigger admin control removal
    +	[_networkId, "logout"] call FUNC(adminUIcontrol);
    +};
    diff --git a/x/ocap/addons/recorder/fnc_eh_projectileHit.sqf b/x/ocap/addons/recorder/fnc_eh_projectileHit.sqf
    new file mode 100644
    index 0000000..7706346
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_eh_projectileHit.sqf
    @@ -0,0 +1,58 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_eh_projectileHit.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_eh_projectileHit
    +
    +Description:
    +  Tracks when a unit is hit/takes damage and saves to the timeline. This is called by projectile event handlers in <OCAP_recorder_fnc_eh_firedMan>.
    +
    +Parameters:
    +  _unit - Object that took damage [Object]
    +  _shooter - Object that caused the damage [Object]
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > [_hitEntity, _projectileOwner] call FUNC(eh_projectileHit);
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox, Fank
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +if (!SHOULDSAVEEVENTS) exitWith {};
    +
    +params ["_unit", "_shooter"];
    +
    +private _hitFrame = GVAR(captureFrameNo);
    +
    +_unitID = _unit getVariable [QGVARMAIN(id), -1];
    +if (_unitID == -1) exitWith {};
    +_shooterID = _shooter getVariable [QGVARMAIN(id), -1];
    +if (_shooterID == -1) exitWith {};
    +
    +private _distanceInfo = 0;
    +_distanceInfo = round (_shooter distance _unit);
    +
    +_causedByInfo = [
    +  _shooterID,
    +  ([_shooter] call FUNC(getEventWeaponText))
    +];
    +
    +private _eventData = [
    +  _hitFrame, // Frame number
    +  "hit", // event type
    +  _unitID, // hit unit ID
    +  _causedByInfo, // event info
    +  _distanceInfo // distance
    +];
    +
    +[":EVENT:", _eventData] call EFUNC(extension,sendData);
    +
    +if (GVARMAIN(isDebug)) then {
    +  OCAPEXTLOG(ARR4("HIT EVENT", _hitFrame, _unitID, _causedById));
    +};
    diff --git a/x/ocap/addons/recorder/fnc_entityMonitors.sqf b/x/ocap/addons/recorder/fnc_entityMonitors.sqf
    new file mode 100644
    index 0000000..3d87ab1
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_entityMonitors.sqf
    @@ -0,0 +1,72 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_entityMonitors.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_entityMonitors
    +
    +Description:
    +  While debug mode is enabled, this function will render 2D icons and text representing all entities that have been initialized by OCAP and are not being excluded from the recording.
    +
    +  This is useful for debugging and verifying that the correct entities are being recorded (see <OCAP_settings_excludeClassFromRecord> and <OCAP_settings_excludeKindFromRecord>.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > [_hitEntity, _projectileOwner] call FUNC(eh_projectileHit);
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +// DEBUG draws on clients
    +{
    +  if (!hasInterface) exitWith {};
    +  [] spawn {
    +    waitUntil {!isNull (findDisplay 12)};
    +    disableSerialization;
    +    (findDisplay 12 displayCtrl 51) ctrlAddEventHandler ["Draw", {
    +      if (GVARMAIN(isDebug)) then {
    +        _sizeInMeters = 2.5;
    +        _iconSize = (_sizeInMeters * 0.15) * 10^(abs log (ctrlMapScale (_this#0)));
    +        {
    +          (_this#0) drawIcon [
    +            (_x call {
    +              if (_this call CBA_fnc_isPerson) then {
    +                getText(configFile >> "CfgVehicleIcons" >> (getText((configOf _this) >> "icon")))
    +              } else {
    +                getText((configOf _this) >> "icon")
    +              };
    +            }),
    +            [side group _x] call BIS_fnc_sideColor,
    +            getPos _x,
    +            _iconSize,
    +            _iconSize,
    +            getDir _x,
    +            (_x call {
    +              if (_this call CBA_fnc_isPerson) then {name _this} else {getText(configOf _this >> "displayName")}
    +            }),
    +            1,
    +            0.02,
    +            "TahomaB",
    +            "center"
    +          ];
    +        } forEach ((allUnits + vehicles) select {
    +          _x getVariable [QGVARMAIN(isInitialized), false] &&
    +          !(_x getVariable [QGVARMAIN(exclude), false]) &&
    +          not (!alive _x || isNull _x || objectParent _x isNotEqualTo objNull)
    +        });
    +      };
    +    }];
    +  };
    +} remoteExec ["call", [0, -2] select isDedicated, true];
    +
    +// Variable: OCAP_entityMonitorsInitialized
    +// This variable on the server indicates whether or not the entity monitors have been initialized for all clients + JIP.
    +GVAR(entityMonitorsInitialized) = true;
    diff --git a/x/ocap/addons/recorder/fnc_exportData.sqf b/x/ocap/addons/recorder/fnc_exportData.sqf
    new file mode 100644
    index 0000000..8eeac10
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_exportData.sqf
    @@ -0,0 +1,171 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_exportData.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_exportData
    +
    +Description:
    +  This function facilitates the actual endMission and save events in the extension, prompting it to pack the mission and upload it to the web component.
    +
    +  Called directly, it is subject to the <OCAP_settings_minMissionTime> setting, and will not export if the mission is not long enough. It can also be called using <OCAP_listener_exportData> to bypass this check.
    +
    +  When <OCAP_settings_saveMissionEnded> is true, this function will be called automatically when the mission ends.
    +
    +  When <OCAP_settings_saveOnEmpty> is true, this function will execute when the last player leaves the mission (to lobby or when disconnecting).
    +
    +  <OCAP_settings_saveTag> is used to tag the mission with a custom string, which can be used to identify the mission in the web component.
    +
    +Parameters:
    +  _side - The winning side [optional, Side]
    +  _message - A custom description of how the victory was achieved [optional, String]
    +  _tag - A custom tag to override that which is defined in userconfig.hpp that will make it filterable in web [optional, String]
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  (start code)
    +  // "Mission ended"
    +  [] call FUNC(exportData);
    +
    +  // "BLUFOR Win."
    +  [west] call FUNC(exportData);
    +
    +  // "OPFOR Win. OPFOR controlled all sectors!
    +  [east, "OPFOR controlled all sectors!"] call FUNC(exportData);
    +
    +  // "Independent Win. INDFOR stole the intel!"
    +  // Mission is saved under filterable "SnatchAndGrab" tag on web
    +  [independent, "INDFOR stole the intel!", "SnatchAndGrab"] call FUNC(exportData);
    +
    +  ["OCAP_exportData", west] call CBA_fnc_serverEvent;
    +  (end code)
    +
    +Public:
    +  No
    +
    +Author:
    +  Dell, Zealot, IndigoFox, TyroneMF
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +params ["_side", "_message", "_tag", ["_overrideLimits", false, [false]]];
    +// overrideLimits will bypass any restriction checks, in case someone wants to save a mission even if doesn't meet their usual criteria
    +
    +
    +if (isNil QGVAR(startTime)) exitWith {
    +  // if recording hasn't started, there's nothing to save
    +  LOG(["Export data call received, but recording of this session hasn't yet started."]);
    +
    +  {
    +    [{!isNull player}, {
    +      player createDiaryRecord [
    +        "OCAPInfo",
    +        [
    +          "Status",
    +          "<font color='#33FF33'>OCAP was asked to save, but recording hasn't started yet.</font>"
    +        ], taskNull, "", false
    +      ];
    +      player setDiarySubjectPicture [
    +        "OCAPInfo",
    +        "\A3\ui_f\data\igui\cfg\simpleTasks\types\use_ca.paa"
    +      ];
    +    }] call CBA_fnc_waitUntilAndExecute;
    +  } remoteExecCall ["call", 0, true];
    +};
    +
    +
    +_elapsedTime = time - GVAR(startTime);
    +_frameTimeDuration = (GVAR(frameCaptureDelay) * GVAR(captureFrameNo)) / 60;
    +TRACE_7("Save attempted. Elapsed Time =", _elapsedTime," Frame Count * Delay Duration =", _frameTimeDuration," delta =", _elapsedTime - _frameTimeDuration);
    +
    +
    +if (_frameTimeDuration < GVAR(minMissionTime) && !_overrideLimits) exitWith {
    +  // if the total duration in minutes is not met based on how many frames have been recorded & the frame capture delay,
    +  // then we won't save, but will continue recording in case admins want to save once that threshold is met.
    +  // allow this restriction to be overriden
    +  LOG("Save attempted, but the minimum recording duration hasn't been met. Not saving, continuing to record.");
    +  ["OCAP attempted to save, but the minimum recording duration hasn't been met. Recording will continue.", 1, [1, 1, 1, 1]] remoteExecCall ["CBA_fnc_notify", [0, -2] select isDedicated];
    +  {
    +    player createDiaryRecord [
    +      "OCAPInfo",
    +      [
    +        "Status",
    +        (
    +          "<font color='#FFFF33'>OCAP capture of " + briefingName + " has not yet reached the minimum duration to save it. Recording will continue.</font>"
    +        )
    +      ]
    +    ];
    +    player setDiarySubjectPicture [
    +      "OCAPInfo",
    +      "\A3\ui_f\data\igui\cfg\simpleTasks\types\danger_ca.paa"
    +    ];
    +  } remoteExec ["call", 0, false];
    +};
    +
    +
    +call FUNC(stopRecording);
    +private _endFrameNumber = GVAR(captureFrameNo);
    +
    +if (!isNil QGVAR(PFHObject)) then {
    +  [GVAR(PFHObject)] call CBA_fnc_deletePerFrameHandlerObject;
    +  GVAR(PFHObject) = nil;
    +};
    +
    +if (isNil "_side") then {
    +  [":EVENT:", [_endFrameNumber, "endMission", ["", "Mission ended"]]] call EFUNC(extension,sendData);
    +};
    +if (isNil "_side" && !isNil "_message") then {
    +  [":EVENT:", [_endFrameNumber, "endMission", ["", _message]]] call EFUNC(extension,sendData);
    +};
    +if (!isNil "_side" && isNil "_message") then {
    +  [":EVENT:", [_endFrameNumber, "endMission", ["", _side]]] call EFUNC(extension,sendData);
    +};
    +if (!isNil "_side" && !isNil "_message") then {
    +  private _sideString = str(_side);
    +  if (_side == sideUnknown) then { _sideString = "" };
    +  [":EVENT:", [_endFrameNumber, "endMission", [_sideString, _message]]] call EFUNC(extension,sendData);
    +};
    +
    +
    +if (!isNil "_tag") then {
    +  [":SAVE:", [worldName, GVAR(missionName), getMissionConfigValue ["author", ""], GVAR(frameCaptureDelay), _endFrameNumber, _tag]] call EFUNC(extension,sendData);
    +  OCAPEXTLOG(ARR4("Saved recording of mission", GVAR(missionName), "with tag", _tag));
    +} else {// default tag to configured setting
    +  [":SAVE:", [worldName, GVAR(missionName), getMissionConfigValue ["author", ""], GVAR(frameCaptureDelay), _endFrameNumber, EGVAR(settings,saveTag)]] call EFUNC(extension,sendData);
    +  OCAPEXTLOG(ARR3("Saved recording of mission", GVAR(missionName), "with default tag"));
    +};
    +
    +
    +// notify players that the recording was saved with a 2 second delay to ensure the "stopped recording" entries populate first
    +[format["OCAP saved %1 frames successfully", _endFrameNumber], 1, [1, 1, 1, 1]] remoteExec ["CBA_fnc_notify", [0, -2] select isDedicated];
    +[[GVAR(missionName), GVAR(captureFrameNo)], {
    +  params ["_missionName", "_endFrame"];
    +
    +  player setDiarySubjectPicture [
    +    "OCAPInfo",
    +    "\A3\ui_f\data\igui\cfg\simpleTasks\types\upload_ca.paa"
    +  ];
    +  player createDiaryRecord [
    +    "OCAPInfo",
    +    [
    +      "Status",
    +      format[
    +        "<font color='#33FF33'>OCAP capture of %1 has been exported with %2 frames saved.</font><br/><br/>Upload results have been logged.",
    +        _missionName,
    +        _endFrame
    +      ]
    +    ]
    +  ];
    +}] remoteExec ["call", [0, -2] select isDedicated, true];
    +
    +// reset vars in case a new recording is started
    +GVAR(captureFrameNo) = 0;
    +publicVariable QGVAR(captureFrameNo);
    +GVAR(startTime) = nil;
    +{
    +  _x setVariable [QGVARMAIN(isInitialized), nil];
    +  _x setVariable [QGVARMAIN(exclude), nil];
    +  _x setVariable [QGVARMAIN(id), nil];
    +  _x setVariable [QGVARMAIN(unitType), nil];
    +} count (allUnits + allDeadMen + vehicles);
    +GVAR(nextId) = 0;
    diff --git a/x/ocap/addons/recorder/fnc_getAmmoMarkerData.sqf b/x/ocap/addons/recorder/fnc_getAmmoMarkerData.sqf
    new file mode 100644
    index 0000000..361ee4c
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_getAmmoMarkerData.sqf
    @@ -0,0 +1,87 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_getAmmoMarkerData.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_getAmmoMarkerData
    +
    +Description:
    +  This function will intake information from <OCAP_EH_FiredMan> and return data used to format a marker for entry into the timeline.
    +
    +Parameters:
    +  _weapon - The weapon used [String]
    +  _muzzle - The muzzle used [String]
    +  _ammo - The ammo used [String]
    +  _magazine - The magazine used [String]
    +  _projectile - The projectile object [Object]
    +  _vehicle - The vehicle the weapon is mounted on, if any [Object]
    +  _ammoSimType - The ammo simulation type [String]
    +
    +Returns:
    +  [_markTextLocal,_markName,_markColor,_markerType] - The marker data [Array]
    +
    +Examples:
    +  > ([_weapon, _muzzle, _ammo, _magazine, _projectile, _vehicle, _ammoSimType] call FUNC(getAmmoMarkerData)) params ["_markTextLocal","_markName","_markColor","_markerType"];
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +params ["_weapon", "_muzzle", "_ammo", "_magazine", "_projectile", "_vehicle", "_ammoSimType"];
    +
    +_int = random 2000;
    +([_weapon, _muzzle, _magazine, _ammo] call FUNC(getWeaponDisplayData)) params ["_muzzleDisp", "_magDisp"];
    +
    +// non-bullet handling
    +private ["_markTextLocal"];
    +if (!isNull _vehicle) then {
    +  _markTextLocal = format["[%3] %1 - %2", _muzzleDisp, _magDisp, ([configOf _vehicle] call BIS_fnc_displayName)];
    +} else {
    +  if (_ammoSimType isEqualTo "shotGrenade") then {
    +    _markTextLocal = format["%1", _magDisp];
    +  } else {
    +    _markTextLocal = format["%1 - %2", _muzzleDisp, _magDisp];
    +  };
    +};
    +
    +_markName = format["Projectile#%1", _int];
    +_markColor = "ColorRed";
    +_markerType = "";
    +_magPic = (getText(configfile >> "CfgMagazines" >> _magazine >> "picture"));
    +if (_magPic == "") then {
    +  _markerType = "mil_triangle";
    +} else {
    +  _magPicSplit = _magPic splitString "\";
    +  _magPic = _magPicSplit # ((count _magPicSplit) -1);
    +  _markerType = format["magIcons/%1", _magPic];
    +  _markColor = "ColorWhite";
    +};
    +
    +[_markTextLocal,_markName,_markColor,_markerType];
    +
    +
    +  // _markStr = format["|%1|%2|%3|%4|%5|%6|%7|%8|%9|%10",
    +  // 	_markName,
    +  // 	getPos _firer,
    +  // 	"mil_triangle",
    +  // 	"ICON",
    +  // 	[1, 1],
    +  // 	0,
    +  // 	"Solid",
    +  // 	"ColorRed",
    +  // 	1,
    +  // 	_markTextLocal
    +  // ];
    +
    +  // _markStr call BIS_fnc_stringToMarkerLocal;
    +
    +  // diag_log text format["detected grenade, created marker %1", _markStr];
    +
    +  // _markStr = str _mark;
    +  // _mark = createMarkerLocal [format["Projectile%1", _int],_projectile];
    +  // _mark setMarkerColorLocal "ColorRed";
    +  // _mark setMarkerTypeLocal "selector_selectable";
    +  // _mark setMarkerShapeLocal "ICON";
    +  // _mark setMarkerTextLocal format["%1 - %2", _firer, _markTextLocal];
    diff --git a/x/ocap/addons/recorder/fnc_getClass.sqf b/x/ocap/addons/recorder/fnc_getClass.sqf
    new file mode 100644
    index 0000000..8a774be
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_getClass.sqf
    @@ -0,0 +1,39 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_getClass.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_getClass
    +
    +Description:
    +  Determines what type of vehicle is being recorded to match with the more limited icon set preloaded in the OCAP playback UI.
    +
    +Parameters:
    +  _this - The vehicle being queried [Object]
    +
    +Returns:
    +  [String] - The icon name that should be used to represent the vehicle in the playback UI
    +
    +Examples:
    +  > _class = _vehType call FUNC(getClass);
    +
    +Public:
    +  No
    +
    +Author:
    +  Zealot, Dell
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +if (getText(configFile >> "CfgVehicles" >> _this >> "model") isEqualTo "\A3\Weapons_f\empty") exitWith {"unknown"};
    +
    +if (_this isKindOf "Truck_F") exitWith {"truck"}; // Should be higher than Car
    +if (_this call FUNC(isKindOfApc)) exitWith {"apc"};
    +if (_this isKindOf "Car") exitWith {"car"};
    +if (_this isKindOf "Tank") exitWith {"tank"};
    +if (_this isKindOf "StaticMortar") exitWith {"static-mortar"};
    +if (_this isKindOf "StaticWeapon") exitWith {"static-weapon"};
    +if (_this isKindOf "ParachuteBase") exitWith {"parachute"};
    +if (_this isKindOf "Helicopter") exitWith {"heli"};
    +if (_this isKindOf "Plane") exitWith {"plane"};
    +if (_this isKindOf "Air") exitWith {"plane"};
    +if (_this isKindOf "Ship") exitWith {"sea"};
    +"unknown"
    diff --git a/x/ocap/addons/recorder/fnc_getEventWeaponText.sqf b/x/ocap/addons/recorder/fnc_getEventWeaponText.sqf
    new file mode 100644
    index 0000000..c1e4a97
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_getEventWeaponText.sqf
    @@ -0,0 +1,57 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_getEventWeaponText.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_getEventWeaponText
    +
    +Description:
    +  Used to identify the current weapon a unit is using that has injured or killed another. Will determine the handheld weapon or vehicle weapon they're using.
    +
    +  Attempts to reference <OCAP_lastFired> but will fall back to current value if not available.
    +
    +  Called during <OCAP_recorder_fnc_projectileHit> and <OCAP_recorder_fnc_eh_killed>.
    +
    +Parameters:
    +  _instigator - The unit to evaluate [Object]
    +
    +Returns:
    +  The description of weapon or vehicle > weapon. [String]
    +
    +Examples:
    +  > [_shooter] call FUNC(getEventWeaponText)
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +params ["_instigator"];
    +
    +if (isNull _instigator) exitWith {""};
    +
    +if !(_instigator call CBA_fnc_isPerson) then {
    +  _instigator = _instigator call {
    +    if(alive(gunner _this))exitWith{gunner _this};
    +    if(alive(commander _this))exitWith{commander _this};
    +    if(alive(driver _this))exitWith{driver _this};
    +    effectiveCommander _this
    +  };
    +};
    +
    +if (_instigator call CBA_fnc_isPerson) then {
    +  (_instigator weaponstate (currentWeapon _instigator)) params ["_weapon", "_muzzle", "_mode", "_magazine"];
    +  ([_weapon, _muzzle, _magazine] call FUNC(getWeaponDisplayData)) params ["_muzDisp", "_magDisp"];
    +
    +  _instigator getVariable [
    +    QGVARMAIN(lastFired),
    +    format [
    +      "%1 [%2]",
    +      _muzDisp,
    +      _magDisp
    +    ]
    +  ];
    +} else {
    +  getText(configFile >> "CfgVehicles" >> (typeOf vehicle _instigator) >> "displayName");
    +};
    diff --git a/x/ocap/addons/recorder/fnc_getInstigator.sqf b/x/ocap/addons/recorder/fnc_getInstigator.sqf
    new file mode 100644
    index 0000000..d107a83
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_getInstigator.sqf
    @@ -0,0 +1,50 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_getInstigator.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_getInstigator
    +
    +Description:
    +  Attempts to identify who truly pulled the trigger on a kill event.
    +
    +  Called in <OCAP_recorder_fnc_eh_killed>.
    +
    +Parameters:
    +  _victim - Who was killed. [Object]
    +  _killer - What caused the damage. [Object, default objNull]
    +  _instigator - Who pulled the trigger, as reported by Arma. [Object, default objNull]
    +
    +Returns:
    +  The true killer. [Object]
    +
    +Examples:
    +  > [_victim, _killer] call FUNC(getInstigator);
    +
    +Public:
    +  No
    +
    +Author:
    +  Dell
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +params [["_victim", objNull], ["_killer", objNull], ["_instigator", objNull]];
    +
    +if (isNull _instigator) then {
    +  _instigator = UAVControl vehicle _killer select 0;
    +};
    +if ((isNull _instigator) || (_instigator == _victim)) then {
    +  _instigator = _killer;
    +};
    +if (_instigator isKindOf "AllVehicles") then {
    +  _instigator = _instigator call {
    +    if(alive(gunner _this))exitWith{gunner _this};
    +    if(alive(commander _this))exitWith{commander _this};
    +    if(alive(driver _this))exitWith{driver _this};
    +    effectiveCommander _this
    +  };
    +};
    +if (isNull _instigator) then {
    +  _instigator = _killer;
    +};
    +
    +_instigator;
    diff --git a/x/ocap/addons/recorder/fnc_getUnitType.sqf b/x/ocap/addons/recorder/fnc_getUnitType.sqf
    new file mode 100644
    index 0000000..dd35f08
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_getUnitType.sqf
    @@ -0,0 +1,77 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_getUnitType.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_getUnitType
    +
    +Description:
    +  Identifies the role of a unit using similar methodology to Arma 3's. Used in <FUNC(captureLoop)>.
    +
    +Parameters:
    +  _unitToCheck - Unit to evaluate. [Object]
    +
    +Returns:
    +  The role text. [String]
    +
    +Examples:
    +  > [_x] call ocap_fnc_getUnitType;
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox, veteran29
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +params ["_unitToCheck"];
    +
    +private _role = "Man";
    +private _typePic = getText (configOf _unitToCheck >> "icon");
    +
    +
    +switch (true) do {
    +  case (
    +    ["Officer", _typePic] call BIS_fnc_inString
    +  ): {_role = "Officer"};
    +  case (
    +    _unitToCheck == leader group _unitToCheck
    +  ): {_role = "Leader"};
    +};
    +
    +if (_role == "Man") then {
    +  switch (true) do {
    +    case (_unitToCheck getUnitTrait 'medic'): {
    +      _role = 'Medic';
    +    };
    +    case (_unitToCheck getUnitTrait 'engineer'): {
    +      _role = 'Engineer';
    +    };
    +    case (_unitToCheck getUnitTrait 'explosiveSpecialist'): {
    +      _role = 'ExplosiveSpecialist';
    +    };
    +  };
    +};
    +
    +if (_role == "Man") then {
    +  private _weaponPicture = toLower getText (configFile >> "CfgWeapons" >> secondaryWeapon _unitToCheck >> "UiPicture");
    +  switch (true) do {
    +    case ("_mg_" in _weaponPicture): {_role = "MG"};
    +    case ("_gl_" in _weaponPicture): {_role = "GL"};
    +    case ("_at_" in _weaponPicture): {_role = "AT"};
    +    case ("_sniper_" in _weaponPicture): {_role = "Sniper"};
    +    case ("_aa_" in _weaponPicture): {_role = "AA"};
    +  };
    +};
    +
    +if (_role == "Man") then {
    +  private _weaponPicture = toLower getText (configFile >> "CfgWeapons" >> primaryWeapon _unitToCheck >> "UiPicture");
    +  switch (true) do {
    +    case ("_mg_" in _weaponPicture): {_role = "MG"};
    +    case ("_gl_" in _weaponPicture): {_role = "GL"};
    +    case ("_at_" in _weaponPicture): {_role = "AT"};
    +    case ("_sniper_" in _weaponPicture): {_role = "Sniper"};
    +    case ("_aa_" in _weaponPicture): {_role = "AA"};
    +  };
    +};
    +
    +_role
    diff --git a/x/ocap/addons/recorder/fnc_getWeaponDisplayData.sqf b/x/ocap/addons/recorder/fnc_getWeaponDisplayData.sqf
    new file mode 100644
    index 0000000..3e66387
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_getWeaponDisplayData.sqf
    @@ -0,0 +1,44 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_getWeaponDisplayData.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_getWeaponDisplayData
    +
    +Description:
    +  Used to populate <OCAP_lastFired> on units in <OCAP_recorder_fnc_eh_firedMan>.
    +
    +Parameters:
    +  _weapon - Weapon class name [String]
    +  _muzzle - Muzzle class name [String]
    +  _magazine - Magazine class name [String]
    +  _ammo - Ammo class name [String]
    +
    +Returns:
    +  [Array]
    +
    +    0 - Muzzle display name [String]
    +    1 - Magazine display name [String]
    +
    +Examples:
    +  > ([_weapon, _muzzle, _magazine, _ammo] call FUNC(getWeaponDisplayData)) params ["_muzzleDisp", "_magDisp"];
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox
    +---------------------------------------------------------------------------- */
    +params ["_weapon", "_muzzle", "_magazine", "_ammo"];
    +
    +_muzzleDisp = getText(configFile >> "CfgWeapons" >> _weapon >> _muzzle >> "displayName");
    +if (_muzzleDisp == "") then {_muzzleDisp = getText(configFile >> "CfgWeapons" >> _weapon >> "displayNameShort")};
    +if (_muzzleDisp == "") then {_muzzleDisp = getText(configFile >> "CfgWeapons" >> _weapon >> "displayName")};
    +_magDisp = getText(configFile >> "CfgMagazines" >> _magazine >> "displayNameShort");
    +if (_magDisp == "") then {_magDisp = getText(configFile >> "CfgMagazines" >> _magazine >> "displayName")};
    +if (_magDisp == "" && !isNil "_ammo") then {_magDisp = getText(configFile >> "CfgAmmo" >> _ammo >> "displayNameShort")};
    +if (_magDisp == "" && !isNil "_ammo") then {_magDisp = getText(configFile >> "CfgAmmo" >> _ammo >> "displayName")};
    +
    +if (_muzzleDisp find _magDisp > -1 && _magDisp isNotEqualTo "") then {
    +  _muzzleDisp = getText(configFile >> "CfgWeapons" >> _weapon >> "displayName");
    +};
    +
    +[_muzzleDisp, _magDisp];
    diff --git a/x/ocap/addons/recorder/fnc_handleCustomEvent.sqf b/x/ocap/addons/recorder/fnc_handleCustomEvent.sqf
    new file mode 100644
    index 0000000..2cfb2cc
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_handleCustomEvent.sqf
    @@ -0,0 +1,61 @@
    +/*
    +  FILE: fnc_handleCustomEvent.sqf
    +
    +  FUNCTION: OCAP_recorder_fnc_handleCustomEvent
    +
    +  Description:
    +    Sends custom event data to the extension to save it to the timeline. This custom event data is later read by Javascript in the web component to determine how it should be displayed.
    +
    +    Applied during initialization of OCAP in <OCAP_recorder_fnc_init>.
    +
    +  Parameters:
    +    _type - classifier for the type of event. used to determine text & icon [[String], one of: "flag", "generalEvent"]
    +    _unit - name of the unit that performed the action [String]
    +    _unitColor - (optional) color for the unit's name shown in Events list and for the pulse on the map [[String], Hex RGB, defaults "" and will show as white]
    +    _objectiveColor - (optional) color representing the icon in Events list [[String], Hex RGB, defaults "" and will show as white]
    +    _position - (optional) the location to pulse on the map [<PositionATL>, default nil]
    +
    +  Returns:
    +    Nothing
    +
    +  Examples:
    +    (start code)
    +    ["ocap_handleCustomEvent", ["eventType", "eventMessage"]] call CBA_fnc_serverEvent;
    +
    +    // saves a general event to the timeline
    +    ["ocap_handleCustomEvent", ["generalEvent", "eventText"]] call CBA_fnc_serverEvent;
    +
    +    // indicates a flag has been captured
    +    ["ocap_handleCustomEvent", ["captured", [
    +      "flag",
    +      name _unit,
    +      str side group _unit,
    +      "#FF0000",
    +      getPosAtl _flag
    +    ]]] call call CBA_fnc_serverEvent;
    +
    +
    +    // Not yet implemented
    +    ["ocap_handleCustomEvent", ["captured", [
    +      "sector",
    +      name _unit,
    +      str side group _unit,
    +      "#FF0000",
    +      getPosAtl _sectorObject
    +    ]]] call call CBA_fnc_serverEvent;
    +    (end code)
    +
    +  Public:
    +    Yes
    +
    +  Author:
    +    Fank, Zealot
    +*/
    +#include "script_component.hpp"
    +
    +if (!SHOULDSAVEEVENTS) exitWith {};
    +
    +params ["_eventName", "_eventMessage"];
    +[":EVENT:",
    +  [GVAR(captureFrameNo), _eventName, _eventMessage]
    +] call EFUNC(extension,sendData);
    diff --git a/x/ocap/addons/recorder/fnc_handleMarkers.sqf b/x/ocap/addons/recorder/fnc_handleMarkers.sqf
    new file mode 100644
    index 0000000..3a9ab33
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_handleMarkers.sqf
    @@ -0,0 +1,333 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_handleMarkers.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_handleMarkers
    +
    +Description:
    +  Used for tracking all markers in the vanilla Arma 3 system.
    +
    +  This function creates a server-side CBA listener as well as local Event Handlers on the server and all clients. It facilitates marker creation, modification, and deletion that occurs across any machine or on the server.
    +
    +  Delays are integrated into the system to allow for multi-line scripted marker creations during a mission to reflect correctly in the created marker during playback. These delays are accounted for so that playback reflects the true creation time.
    +
    +  Due to the nature of locality and single-view playback, markers of the same name which exist in different states on different clients may display odd behavior during playback.
    +
    +  Marker exclusions as configured in <OCAP_settings_excludeMarkerFromRecord> are handled client-side to avoid unnecessary network traffic.
    +
    +  This will also wait until the mission proceeds past the briefing screen, then gather all existing markers and send them to the server for entry onto the Editor/Briefing Markers layer during playback.
    +
    +  Applied during mission event handler application in <OCAP_recorder_fnc_addEventMission>.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > call FUNC(handleMarkers);
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox, Fank
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +// VARIABLE: OCAP_recorder_trackedMarkers
    +// Persistent global variable on server that defines unique marker names currently being tracked.
    +// Entries are added at marker create events and removed at marker delete events to avoid duplicate processing.
    +GVAR(trackedMarkers) = []; // Markers which we save into replay
    +
    +// VARIABLE: OCAP_listener_markers
    +// Contains handle for <OCAP_handleMarker> CBA event handler.
    +
    +// CBA Event: OCAP_handleMarker
    +// Handles marker creation, modification, and deletion events.
    +EGVAR(listener,markers) = [QGVARMAIN(handleMarker), {
    +
    +  if (!SHOULDSAVEEVENTS) exitWith {};
    +
    +  params["_eventType", "_mrk_name", "_mrk_owner", "_pos", "_type", "_shape", "_size", "_dir", "_brush", "_color", "_alpha", "_text", ["_forceGlobal", false], ["_creationTime", 0]];
    +
    +  switch (_eventType) do {
    +
    +    case "CREATED":{
    +
    +      if (GVARMAIN(isDebug)) then {
    +        OCAPEXTLOG(ARR2("MARKER:CREATE: Processing marker data -- ", _mrk_name));
    +      };
    +
    +      if (_mrk_name in GVAR(trackedMarkers)) exitWith {
    +        if (GVARMAIN(isDebug)) then {
    +          OCAPEXTLOG(ARR3("MARKER:CREATE: Marker", _mrk_name, "already tracked, exiting"));
    +        };
    +      };
    +
    +      if (GVARMAIN(isDebug)) then {
    +        format["CREATE:MARKER: Valid CREATED process of %1, sending to extension", _mrk_name] SYSCHAT;
    +        OCAPEXTLOG(ARR3("CREATE:MARKER: Valid CREATED process of", _mrk_name, ", sending to extension"));
    +      };
    +
    +      if (_type isEqualTo "") then {_type = "mil_dot"};
    +      GVAR(trackedMarkers) pushBackUnique _mrk_name;
    +
    +      private _mrk_color = "";
    +      if (_color == "Default") then {
    +        _mrk_color = (configfile >> "CfgMarkers" >> _type >> "color") call BIS_fnc_colorConfigToRGBA call bis_fnc_colorRGBtoHTML;
    +      } else {
    +        _mrk_color = (configfile >> "CfgMarkerColors" >> _color >> "color") call BIS_fnc_colorConfigToRGBA call bis_fnc_colorRGBtoHTML;
    +      };
    +
    +      private ["_sideOfMarker"];
    +      if (_mrk_owner isEqualTo objNull) then {
    +        _forceGlobal = true;
    +        _mrk_owner = -1;
    +        _sideOfMarker = -1;
    +      } else {
    +        _sideOfMarker = (side _mrk_owner) call BIS_fnc_sideID;
    +        _mrk_owner = _mrk_owner getVariable[QGVARMAIN(id), 0];
    +      };
    +
    +      if (_sideOfMarker isEqualTo 4 ||
    +      (["Projectile#", _mrk_name] call BIS_fnc_inString) ||
    +      (["Detonation#", _mrk_name] call BIS_fnc_inString) ||
    +      (["Mine#", _mrk_name] call BIS_fnc_inString) ||
    +      (["ObjectMarker", _mrk_name] call BIS_fnc_inString) ||
    +      (["moduleCoverMap", _mrk_name] call BIS_fnc_inString) ||
    +      _forceGlobal) then {_sideOfMarker = -1};
    +
    +      private ["_polylinePos"];
    +      if (count _pos > 3) then {
    +        _polylinePos = [];
    +        for [{_i = 0}, {_i < ((count _pos) - 1)}, {_i = _i + 1}] do {
    +          _polylinePos pushBack [_pos # (_i), _pos # (_i + 1)];
    +          _i = _i + 1;
    +        };
    +        _pos = _polylinePos;
    +      };
    +
    +      if (isNil "_dir") then {
    +        _dir = 0;
    +      } else {if (_dir isEqualTo "") then {_dir = 0}};
    +
    +      private _captureFrameNo = GVAR(captureFrameNo);
    +      if (_creationTime > 0) then {
    +        private _delta = time - _creationTime;
    +        private _lastFrameTime = (GVAR(captureFrameNo) * GVAR(frameCaptureDelay)) + GVAR(startTime);
    +        if (_delta > (time - _lastFrameTime)) then { // marker was initially created in some frame(s) before
    +          _captureFrameNo = ceil _lastFrameTime - (_delta / GVAR(frameCaptureDelay));
    +          private _logParams = (str [GVAR(captureFrameNo), time, _creationTime, _delta, _lastFrameTime, _captureFrameNo]);
    +
    +          if (GVARMAIN(isDebug)) then {
    +            OCAPEXTLOG(ARR2("CREATE:MARKER: adjust frame ", _logParams));
    +          };
    +        };
    +      };
    +
    +      private _logParams = (str [_mrk_name, _dir, _type, _text, _captureFrameNo, -1, _mrk_owner, _mrk_color, _size, _sideOfMarker, _pos, _shape, _alpha, _brush]);
    +
    +      [":MARKER:CREATE:", [_mrk_name, _dir, _type, _text, _captureFrameNo, -1, _mrk_owner, _mrk_color, _size, _sideOfMarker, _pos, _shape, _alpha, _brush]] call EFUNC(extension,sendData);
    +    };
    +
    +    case "UPDATED":{
    +
    +      if (_mrk_name in GVAR(trackedMarkers)) then {
    +        if (isNil "_dir") then {_dir = 0};
    +        [":MARKER:MOVE:", [_mrk_name, GVAR(captureFrameNo), _pos, _dir, _alpha]] call EFUNC(extension,sendData);
    +      };
    +    };
    +
    +    case "DELETED":{
    +
    +      if (_mrk_name in GVAR(trackedMarkers)) then {
    +
    +        if (GVARMAIN(isDebug)) then {
    +          format["MARKER:DELETE: Marker %1", _mrk_name] SYSCHAT;
    +          OCAPEXTLOG(ARR3("MARKER:DELETE: Marker", _mrk_name, "deleted"));
    +        };
    +
    +        [":MARKER:DELETE:", [_mrk_name, GVAR(captureFrameNo)]] call EFUNC(extension,sendData);
    +        GVAR(trackedMarkers) = GVAR(trackedMarkers) - [_mrk_name];
    +      };
    +    };
    +  };
    +}] call CBA_fnc_addEventHandler;
    +
    +
    +
    +
    +
    +// handle created markers
    +{
    +  /*
    +    Event Handler: MarkerCreated
    +    Description:
    +      Tracks marker creations. Present on server and all clients. Ignores remotely-owned markers.
    +
    +      References <OCAP_settings_excludeMarkerFromRecord> on each local machine to determine if a marker should be recorded.
    +
    +      If so, sends marker data to <OCAP_handleMarker> on the server for processing.
    + */
    +  addMissionEventHandler["MarkerCreated", {
    +    params["_marker", "_channelNumber", "_owner", "_local"];
    +
    +    if (!_local) exitWith {};
    +
    +    // check for excluded values in marker name. if name contains at least one value, skip sending traffic to server
    +    // if value is undefined, then skip
    +    private _isExcluded = false;
    +    if (!isNil QEGVAR(settings,excludeMarkerFromRecord)) then {
    +      {
    +        if ((str _marker) find _x >= 0) exitWith {
    +          _isExcluded = true;
    +        };
    +      } forEach (parseSimpleArray EGVAR(settings,excludeMarkerFromRecord));
    +    };
    +    if (_isExcluded) exitWith {};
    +
    +    private _event = _this;
    +    _event pushBack time;
    +
    +    [{
    +      params["_marker", "_channelNumber", "_owner", "_local", "_creationTime"];
    +      _pos = ATLToASL (markerPos [_marker, true]);
    +      _type = markerType _marker;
    +      _shape = markerShape _marker;
    +      _size = markerSize _marker;
    +      _dir = markerDir _marker;
    +      _brush = markerBrush _marker;
    +      _color = markerColor _marker;
    +      _text = markerText _marker;
    +      _alpha = markerAlpha _marker;
    +      _polyline = markerPolyline _marker;
    +      if (count _polyline != 0) then {
    +        _pos = _polyline;
    +      };
    +
    +      [QGVARMAIN(handleMarker), ["CREATED", _marker, _owner, _pos, _type, _shape, _size, _dir, _brush, _color, _alpha, _text, false, _creationTime]] call CBA_fnc_serverEvent;
    +    }, _event, 2] call CBA_fnc_waitAndExecute;
    +  }];
    +
    +  // handle marker moves/updates
    +  /*
    +    Event Handler: MarkerUpdated
    +    Description:
    +      Tracks marker updates (moves). Present on server and all clients. Ignores remotely-owned markers.
    +
    +      References <OCAP_settings_excludeMarkerFromRecord> on each local machine to determine if a marker should be recorded.
    +
    +      If so, sends marker data to <OCAP_handleMarker> on the server for processing.
    +  */
    +  addMissionEventHandler["MarkerUpdated", {
    +    params["_marker", "_local"];
    +
    +    if (!_local) exitWith {};
    +
    +    // check for excluded values in marker name. if name contains at least one value, skip sending traffic to server
    +    // if value is undefined, then skip
    +    private _isExcluded = false;
    +    if (!isNil QEGVAR(settings,excludeMarkerFromRecord)) then {
    +      {
    +        if ((str _marker) find _x >= -1) exitWith {
    +          _isExcluded = true;
    +        };
    +      } forEach (parseSimpleArray EGVAR(settings,excludeMarkerFromRecord));
    +    };
    +    if (_isExcluded) exitWith {};
    +
    +    private _pos = ATLToASL (markerPos [_marker, true]);
    +
    +    [QGVARMAIN(handleMarker), ["UPDATED", _marker, player, _pos, "", "", "", markerDir _marker, "", "", markerAlpha _marker]] call CBA_fnc_serverEvent;
    +  }];
    +
    +  // handle marker deletions
    +  /*
    +    Event Handler: MarkerDeleted
    +    Description:
    +      Tracks marker deletions. Present on server and all clients. Ignores remotely-owned markers.
    +
    +      References <OCAP_settings_excludeMarkerFromRecord> on each local machine to determine if a marker should be recorded.
    +
    +      If so, sends marker data to <OCAP_handleMarker> on the server for processing.
    +  */
    +  addMissionEventHandler["MarkerDeleted", {
    +    params["_marker", "_local"];
    +
    +    if (!_local) exitWith {};
    +
    +    // check for excluded values in marker name. if name contains at least one value, skip sending traffic to server
    +    // if value is undefined, then skip
    +    private _isExcluded = false;
    +    if (!isNil QEGVAR(settings,excludeMarkerFromRecord)) then {
    +      {
    +        if ((str _marker) find _x > -1) exitWith {
    +          _isExcluded = true;
    +        };
    +      } forEach (parseSimpleArray EGVAR(settings,excludeMarkerFromRecord));
    +    };
    +    if (_isExcluded) exitWith {};
    +
    +    [QGVARMAIN(handleMarker), ["DELETED", _marker, player]] call CBA_fnc_serverEvent;
    +  }];
    +} remoteExec["call", 0, true];
    +
    +
    +
    +// collect all initial markers & add event handlers to clients
    +[
    +  {getClientStateNumber > 8 && !isNil QGVAR(startTime)},
    +  {
    +    {
    +      private _marker = _x;
    +
    +      // check for excluded values in marker name. if name contains at least one value, skip sending traffic to server
    +      // if value is undefined, then skip
    +      private _isExcluded = false;
    +      if (!isNil QEGVAR(settings,excludeMarkerFromRecord)) then {
    +        {
    +          if ((_marker) find _x >= 0) exitWith {
    +            _isExcluded = true;
    +          };
    +        } forEach (parseSimpleArray EGVAR(settings,excludeMarkerFromRecord));
    +      };
    +      if (_isExcluded) then {continue};
    +
    +
    +      // "Started polling starting markers" remoteExec ["hint", 0];
    +      // get intro object markers
    +      _pos = ATLToASL (markerPos [_marker, true]);
    +      _type = markerType _marker;
    +      _shape = markerShape _marker;
    +      _size = markerSize _marker;
    +      _dir = markerDir _marker;
    +      _brush = markerBrush _marker;
    +      _color = markerColor _marker;
    +      _text = markerText _marker;
    +      _alpha = markerAlpha _marker;
    +      _polyline = markerPolyline _marker;
    +      if (count _polyline != 0) then {
    +        _pos = _polyline;
    +      };
    +
    +
    +
    +      if (isNil "_dir") then {
    +        _dir = 0;
    +      } else {if (_dir isEqualTo "") then {_dir = 0}};
    +
    +      _forceGlobal = true;
    +
    +      // "_eventType", "_mrk_name", "_mrk_owner","_pos", "_type", "_shape", "_size", "_dir", "_brush", "_color", "_alpha", "_text", "_forceGlobal"
    +      [QGVARMAIN(handleMarker), ["CREATED", _marker, objNull, _pos, _type, _shape, _size, _dir, _brush, _color, _alpha, _text, _forceGlobal]] call CBA_fnc_localEvent;
    +
    +    } forEach (allMapMarkers select {_x find "_USER_DEFINED" == -1});
    +
    +    LOG("GETINITIALMARKERS: Successfully parsed init-scripted and editor-placed markers");
    +    if (GVARMAIN(isDebug)) then {
    +      "GETINITIALMARKERS: Successfully parsed init-scripted and editor-placed markers" SYSCHAT;
    +      OCAPEXTLOG(["GETINITIALMARKERS: Successfully parsed init-scripted and editor-placed markers"]);
    +    };
    +  }
    +] call CBA_fnc_waitUntilAndExecute;
    diff --git a/x/ocap/addons/recorder/fnc_init.sqf b/x/ocap/addons/recorder/fnc_init.sqf
    new file mode 100644
    index 0000000..de36520
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_init.sqf
    @@ -0,0 +1,202 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_init.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_init
    +
    +Description:
    +  Initializes event listeners, event handlers, gathers <OCAP_version> and <OCAP_extension_version>, and kicks off waiters for the auto-start conditions if settings are configured to enable it.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Example:
    +  > call OCAP_recorder_fnc_init
    +
    +Public:
    +  No
    +
    +Author:
    +  Dell, Zealot, IndigoFox
    +---------------------------------------------------------------------------- */
    +
    +#include "script_component.hpp"
    +
    +// exit if in 3DEN editor (when loaded in PreInit XEH)
    +if (is3DEN || !isMultiplayer) exitWith {};
    +// exit if not server
    +if (!isServer) exitWith {};
    +// if OCAP is disabled do nothing
    +if (!GVARMAIN(enabled)) exitWith {};
    +// if recording has already initialized this session then just start recording, don't re-init
    +if (!isNil QGVAR(startTime)) exitWith {
    +  if (!SHOULDSAVEEVENTS) exitWith {};
    +  call FUNC(startRecording)
    +};
    +
    +// "debug_console" callExtension format["clientState: %1 (%2) | %3", getClientState, getClientStateNumber, __FILE__];
    +
    +// VARIABLE: OCAP_recorder_recording
    +// Global variable that represents whether or not recording is active [Bool]
    +GVAR(recording) = false;
    +publicVariable QGVAR(recording);
    +
    +/*
    +  VARIABLE: OCAP_recorder_captureFrameNo
    +  Global variable that represents the current frame number [Number]
    +*/
    +GVAR(captureFrameNo) = 0;
    +publicVariable QGVAR(captureFrameNo);
    +
    +/*
    +  VARIABLE: OCAP_recorder_nextId
    +  Global variable that represents the next available id to assign to a unit or vehicle [Number]
    +*/
    +GVAR(nextId) = 0;
    +
    +
    +
    +// save static setting values so changes during a mission don't interrupt timeline
    +
    +/*
    +  VARIABLE: OCAP_recorder_frameCaptureDelay
    +  Global variable that represents the delay between frame captures in seconds. Gathered from CBA settings at init. [Number]
    +*/
    +GVAR(frameCaptureDelay) = EGVAR(settings,frameCaptureDelay);
    +
    +/*
    +  VARIABLE: OCAP_recorder_autoStart
    +  Global variable that represents whether or not recording should automatically start. Gathered from CBA settings at init. [Bool]
    +*/
    +GVAR(autoStart) = EGVAR(settings,autoStart);
    +
    +
    +/*
    +  VARIABLE: OCAP_recorder_minMissionTime
    +  Global variable that represents the minimum mission time in seconds to qualify for saving. Can be overridden by using the <ocap_exportData> CBA event. Gathered from CBA settings at init. [Number]
    +*/
    +GVAR(minMissionTime) = EGVAR(settings,minMissionTime);
    +
    +GVAR(projectileMonitorMultiplier) = 1;
    +
    +/*
    +  VARIABLE: OCAP_version
    +  Global variable that represents the version of OCAP addon being used [String]
    +*/
    +GVARMAIN(version) = QUOTE(VERSION_STR);
    +publicVariable QGVARMAIN(version);
    +
    +/*
    +  VARIABLE: OCAP_extension_version
    +  Global variable that represents the version of OCAP extension being used [String]
    +*/
    +EGVAR(extension,version) = ([":VERSION:", []] call EFUNC(extension,sendData));
    +publicVariable QEGVAR(extension,version);
    +
    +// Add mission event handlers
    +call FUNC(addEventMission);
    +
    +// remoteExec diary creation commands to clients listing version numbers and waiting start state
    +{
    +  [{!isNil QGVARMAIN(version) && !isNil QEGVAR(extension,version)}, {
    +    player createDiarySubject ["OCAPInfo", "OCAP AAR", "\A3\ui_f\data\igui\cfg\simpleTasks\types\whiteboard_ca.paa"];
    +
    +    ocap_fnc_copyGitHubToClipboard = {copyToClipboard "https://github.com/OCAP2/OCAP"; systemChat "OCAP GitHub link copied to clipboard";};
    +    EGVAR(diary,about) = player createDiaryRecord [
    +      "OCAPInfo",
    +      [
    +        "About",
    +        (
    +          "<font size='20' face='PuristaBold'><font color='#BBBBBB'>OCAP</font><font color='#44AAFF'>2</font></font><br/>" +
    +          "Addon version: " + GVARMAIN(version) +
    +          "<br/>" +
    +          "Extension version: " + (EGVAR(extension,version) # 0) + " (built " + (EGVAR(extension,version) # 1) + ")" +
    +          "<br/>" +
    +          "<execute expression='call ocap_fnc_copyGitHubToClipboard;'>https://github.com/OCAP2/OCAP</execute>" +
    +          "<br/><br/>" +
    +          "OCAP is a server-side Arma 3 recording suite that provides web-based playback of all units, vehicles, markers, and projectiles present, placed, and fired during a mission." +
    +          "<br/><br/>" +
    +          "Recording status can be found in the Status section." +
    +          "<br/><br/>" +
    +          "DISCLAIMER: This mission may be recorded and made publicly available at the discretion of the server administrators. Please be aware that your actions during this mission will be tracked and attributed to your in-game username."
    +        )
    +      ]
    +    ];
    +
    +    EGVAR(diary,status) = player createDiaryRecord [
    +      "OCAPInfo",
    +      [
    +        "Status",
    +        "OCAP initialized."
    +      ]
    +    ];
    +  }] call CBA_fnc_waitUntilAndExecute;
    +} remoteExecCall ["call", [0, -2] select isDedicated, true];
    +
    +
    +// Support both methods of setting mission name.
    +GVAR(missionName) = getMissionConfigValue ["onLoadName", ""];
    +if (GVAR(missionName) == "") then {
    +    GVAR(missionName) = briefingName;
    +};
    +
    +
    +// On the dedicated server, the color of the markers is blue
    +// This overrides it with client data so it's saved properly
    +{
    +  _x params ["_name", "_color"];
    +  profilenamespace setVariable [_name, _color];
    +} forEach [
    +  ["map_blufor_r", 0],
    +  ["map_blufor_g", 0.3],
    +  ["map_blufor_b", 0.6],
    +  ["map_independent_r", 0],
    +  ["map_independent_g", 0.5],
    +  ["map_independent_b", 0],
    +  ["map_civilian_r", 0.4],
    +  ["map_civilian_g", 0],
    +  ["map_civilian_b", 0.5],
    +  ["map_unknown_r", 0.7],
    +  ["map_unknown_g", 0.6],
    +  ["map_unknown_b", 0],
    +  ["map_opfor_r", 0.5],
    +  ["map_opfor_g", 0],
    +  ["map_opfor_b", 0]
    +];
    +
    +
    +/*
    +  Conditional Start Recording
    +  We'll wait to see if auto-start is enabled and minPlayercount setting is met. This covers scenarios where someone changes the autostart setting during the mission as well, and excludes cases where autostart is disabled.
    +  If recording hasn't started already, we'll initialize it here assuming the above conditions are met.
    +  The startRecording function checks internally if recording has already started by other means via whether GVAR(startTime) has been declared or not.
    +  Start recording AFTER Briefing screen, so the beginning of the recording matches the start of the actual mission session.
    +*/
    +[
    +  {(getClientStateNumber > 9 && (count allPlayers) >= EGVAR(settings,minPlayerCount) && GVAR(autoStart)) || !isNil QGVAR(startTime)},
    +  {
    +    call FUNC(startRecording);
    +    [QGVARMAIN(customEvent), ["generalEvent", "Mission has started!"]] call CBA_fnc_serverEvent;
    +  }
    +] call CBA_fnc_waitUntilAndExecute;
    +
    +// Auto-save on empty - checked every 30 seconds
    +// If a recording has been started, exceeds min mission time, and no players are on the server, auto-save
    +[{
    +  if (
    +    EGVAR(settings,saveOnEmpty) &&
    +    !isNil QGVAR(startTime) && (GVAR(frameCaptureDelay) * GVAR(captureFrameNo)) / 60 >= GVAR(minMissionTime) && count (call CBA_fnc_players) == 0
    +  ) then {
    +      [nil, "Recording ended due to server being empty"] call FUNC(exportData);
    +  };
    +}, 30] call CBA_fnc_addPerFrameHandler;
    +
    +if (isNil QGVAR(projectileMonitorsInitialized)) then {
    +  call FUNC(projectileMonitors);
    +};
    +
    +if (isNil QGVAR(entityMonitorsInitialized)) then {
    +  call FUNC(entityMonitors);
    +};
    diff --git a/x/ocap/addons/recorder/fnc_isKindOfApc.sqf b/x/ocap/addons/recorder/fnc_isKindOfApc.sqf
    new file mode 100644
    index 0000000..4a86356
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_isKindOfApc.sqf
    @@ -0,0 +1,32 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_isKindOfApc.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_isKindOfApc
    +
    +Description:
    +  Helper function for <OCAP_recorder_fnc_getClass> to prevent APCs from being classified as Cars or Trucks.
    +
    +Parameters:
    +  _this - The vehicle to check [Object]
    +
    +Returns:
    +  [Bool] - True if the vehicle is an APC, false otherwise
    +
    +Examples:
    +  > if (_this call FUNC(isKindOfApc)) exitWith {"apc"};
    +
    +Public:
    +  No
    +
    +Author:
    +  Dell, Zealot
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +_bool = false;
    +{
    +  if (_this isKindOf _x) exitWith {_bool = true;};
    +  false;
    +} count ["Wheeled_APC_F","Tracked_APC","APC_Wheeled_01_base_F","APC_Wheeled_02_base_F",
    +"APC_Wheeled_03_base_F","APC_Tracked_01_base_F","APC_Tracked_02_base_F","APC_Tracked_03_base_F"];
    +_bool
    diff --git a/x/ocap/addons/recorder/fnc_projectileMonitors.sqf b/x/ocap/addons/recorder/fnc_projectileMonitors.sqf
    new file mode 100644
    index 0000000..73d4f57
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_projectileMonitors.sqf
    @@ -0,0 +1,143 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_projectileMonitors.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_projectileMonitors
    +
    +Description:
    +  This initializes projectile monitoring for the purposes of moving non-bullet projectile markers across the map during playback as well as to display them on the in-game map while <OCAP_isDebug> is true.
    +
    +  On clients, it will create a "Draw" UI event handler to display both fire-lines representing bullets and markers representing non-bullet projectiles. It will also create an event handler used by the server in <OCAP_recorder_fnc_eh_firedMan> to integrate new projectiles to the array being procesed by the "Draw" handler.
    +
    +  On the server, it will initialize <OCAP_recorder_liveMissiles> and <OCAP_recorder_liveGrenades>. These are watch arrays that are used to track the position of non-bullet projectiles and update the extension with their positions as they travel. This causes the effect of a 'moving marker' during playback.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Example:
    +  > call FUNC(projectileMonitors);
    +
    +Public:
    +  No
    +
    +Author:
    +  IndigoFox
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +// PFH to track missiles, rockets, shells
    +// Variable: OCAP_recorder_liveMissiles
    +// Watched array of missiles, rockets, shells, and any other unaccounted projectile. Every 0.7 seconds, the position of each object in the array is updated and sent to the extension.
    +GVAR(liveMissiles) = [];
    +[{
    +  {
    +    _x params ["_projectile", "_wepString", "_firer", "_pos", "_markName", "_markTextLocal"];
    +    if (isNull _projectile) then {
    +      [QGVARMAIN(handleMarker), ["DELETED", _markName]] call CBA_fnc_localEvent;
    +    } else {
    +      _pos = getPosASL _projectile;
    +      GVAR(liveMissiles) set [_forEachIndex, [_projectile, _wepString, _firer, _pos, _markName, _markTextLocal]];
    +      [QGVARMAIN(handleMarker), ["UPDATED", _markName, _firer, _pos, "", "", "", getDir (_x#0), "", "", 1]] call CBA_fnc_localEvent;
    +    };
    +  } forEach GVAR(liveMissiles);
    +
    +  GVAR(liveMissiles) = GVAR(liveMissiles) select {!isNull (_x select 0)};
    +}, GVAR(frameCaptureDelay)] call CBA_fnc_addPerFrameHandler;
    +
    +// PFH to track grenades, flares, thrown charges
    +// Variable: OCAP_recorder_liveGrenades
    +// Watched array of grenades, flares, and thrown charges. Every 0.7 seconds, the position of each object in the array is updated and sent to the extension.
    +GVAR(liveGrenades) = [];
    +[{
    +  {
    +    _x params ["_projectile", "_wepString", "_firer", "_pos", "_markName", "_markTextLocal", "_ammoSimType"];
    +    if (isNull _projectile) then {
    +      [QGVARMAIN(handleMarker), ["DELETED", _markName]] call CBA_fnc_localEvent;
    +    } else {
    +      _pos = getPosASL _projectile;
    +      GVAR(liveGrenades) set [_forEachIndex, [_projectile, _wepString, _firer, _pos, _markName, _markTextLocal, _ammoSimType]];
    +      [QGVARMAIN(handleMarker), ["UPDATED", _markName, _firer, _pos, "", "", "", getDir (_x#0), "", "", 1]] call CBA_fnc_localEvent;
    +    };
    +  } forEach GVAR(liveGrenades);
    +
    +  GVAR(liveGrenades) = GVAR(liveGrenades) select {!isNull (_x select 0)};
    +}, GVAR(frameCaptureDelay)] call CBA_fnc_addPerFrameHandler;
    +
    +
    +
    +// DEBUG draws on clients
    +
    +// drawLine for each bullet on map if debug active, to verify rounds are captured
    +// these are only added once the projectile has hit something
    +{
    +  if (!hasInterface) exitWith {};
    +  [] spawn {
    +    waitUntil {!isNull (findDisplay 12)};
    +
    +    // Variable: OCAP_recorder_liveDebugBullets
    +    // Used by clients to draw bullet lines. Entered via <OCAP_recorder_fnc_eh_firedMan> and managed in ??
    +    GVAR(liveDebugBullets) = [];
    +    disableSerialization;
    +    (findDisplay 12 displayCtrl 51) ctrlAddEventHandler ["Draw", {
    +      if (GVARMAIN(isDebug)) then {
    +        // remove bullets from display that have landed > 7 seconds ago
    +        GVAR(liveDebugBullets) = GVAR(liveDebugBullets) select {cba_missionTime < (_x#3) + 7};
    +        {
    +          // _x params ["_startPos", "_endPos", "_color", "_timeHit"];
    +          (_this#0) drawLine [
    +            _x#0,
    +            _x#1,
    +            _x#2
    +          ];
    +        } forEach GVAR(liveDebugBullets);
    +      };
    +    }];
    +
    +    [QGVAR(addDebugBullet), {
    +      GVAR(liveDebugBullets) pushBack _this;
    +    }] call CBA_fnc_addEventHandler;
    +  };
    +} remoteExec ["call", [0, -2] select isDedicated, true];
    +
    +// drawIcon for magazines/non-bullet projectiles
    +// these are added when fired and tracked in array
    +{
    +  if (!hasInterface) exitWith {};
    +  [] spawn {
    +    waitUntil {!isNull (findDisplay 12)};
    +
    +    // Variable: OCAP_recorder_liveDebugMagIcons
    +    // Used by clients to draw magazine icons of non-bullet projectiles. Entered via <OCAP_recorder_fnc_eh_firedMan> and managed in ??
    +    GVAR(liveDebugMagIcons) = [];
    +    disableSerialization;
    +    (findDisplay 12 displayCtrl 51) ctrlAddEventHandler ["Draw", {
    +      if (GVARMAIN(isDebug)) then {
    +        GVAR(liveDebugMagIcons) = GVAR(liveDebugMagIcons) select {!isNull (_x#0)};
    +        {
    +          // _x params ["_obj", "_magIcon", "_text", "_sideColor"];
    +          (_this#0) drawIcon [
    +            _x#1, // Custom images can also be used: getMissionPath "\myFolder\myIcon.paa"
    +            _x#3,
    +            getPos (_x#0),
    +            25,
    +            25,
    +            getDir (_x#0),
    +            _x#2,
    +            0,
    +            0.03,
    +            "PuristaLight",
    +            "center"
    +          ];
    +        } forEach GVAR(liveDebugMagIcons);
    +      };
    +    }];
    +
    +    [QGVAR(addDebugMagIcon), {
    +      GVAR(liveDebugMagIcons) pushBack _this;
    +    }] call CBA_fnc_addEventHandler;
    +  };
    +} remoteExec ["call", [0, -2] select isDedicated, true];
    +
    +GVAR(projectileMonitorsInitialized) = true;
    diff --git a/x/ocap/addons/recorder/fnc_startRecording.sqf b/x/ocap/addons/recorder/fnc_startRecording.sqf
    new file mode 100644
    index 0000000..6f80f79
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_startRecording.sqf
    @@ -0,0 +1,77 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_startRecording.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_startRecording
    +
    +Description:
    +  Begins recording the current mission.
    +
    +  Called via <OCAP_record> via direct CBA event or the administrative diary entry, or by a waiter in <OCAP_recorder_fnc_init> (see <OCAP_settings_autoStart>).
    +
    +  Will not start recording if <OCAP_recorder_recording> is true and will notify players.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > call FUNC(startRecording);
    +
    +Public:
    +  No
    +
    +Author:
    +  Dell, Zealot, IndigoFox
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +// disregard recording attempts while OCAP is disabled.
    +if (!GVARMAIN(enabled)) exitWith {};
    +
    +// if recording started earlier and startTime has been noted, only restart the capture loop with any updated settings.
    +if (GVAR(recording) && GVAR(captureFrameNo) > 10) exitWith {
    +  OCAPEXTLOG(["OCAP was asked to record and is already recording!"]);
    +  [
    +    ["OCAP was asked to record", 1, [1, 1, 1, 1]],
    +    ["and is already recording", 1, [1, 1, 1, 1]]
    +  ] remoteExecCall ["CBA_fnc_notify", [0, -2] select isDedicated];
    +};
    +
    +GVAR(recording) = true;
    +publicVariable QGVAR(recording);
    +
    +private _systemTimeFormat = ["%1-%2-%3T%4:%5:%6.%7"];
    +_systemTimeFormat append (systemTimeUTC apply {if (_x < 10) then {"0" + str _x} else {str _x}});
    +private _missionDateFormat = ["%1-%2-%3T%4:%5:00"];
    +_missionDateFormat append (date apply {if (_x < 10) then {"0" + str _x} else {str _x}});
    +
    +[[cba_missionTime, format _missionDateFormat, format _systemTimeFormat], { // add diary entry for clients on recording start
    +  [{!isNull player}, {
    +    player setDiarySubjectPicture [
    +      "OCAPInfo",
    +      "\A3\ui_f\data\igui\cfg\simpleTasks\types\use_ca.paa"
    +    ];
    +    player createDiaryRecord [
    +      "OCAPInfo",
    +      [
    +        "Status",
    +        format["<font color='#33FF33'>OCAP started recording.<br/>In-Mission Time Elapsed: %1<br/>Mission World Time: %2<br/>System Time UTC: %3</font>", _this#0, _this#1, _this#2]
    +      ]
    +    ];
    +  }, _this] call CBA_fnc_waitUntilAndExecute;
    +}] remoteExec ["call", [0, -2] select isDedicated, true];
    +
    +if (GVAR(captureFrameNo) == 0) then {
    +  // Notify the extension
    +  [":START:", [worldName, GVAR(missionName), getMissionConfigValue ["author", ""], GVAR(frameCaptureDelay)]] call EFUNC(extension,sendData);
    +  [":SET:VERSION:", [GVARMAIN(version)]] call EFUNC(extension,sendData);
    +  call FUNC(captureLoop);
    +};
    +
    +[QGVARMAIN(customEvent), ["generalEvent", "Recording started."]] call CBA_fnc_serverEvent;
    +["OCAP began recording", 1, [1, 1, 1, 1]] remoteExecCall ["CBA_fnc_notify", [0, -2] select isDedicated];
    +
    +// Log times
    +[] call FUNC(updateTime);
    diff --git a/x/ocap/addons/recorder/fnc_stopRecording.sqf b/x/ocap/addons/recorder/fnc_stopRecording.sqf
    new file mode 100644
    index 0000000..f553370
    --- /dev/null
    +++ b/x/ocap/addons/recorder/fnc_stopRecording.sqf
    @@ -0,0 +1,56 @@
    +/* ----------------------------------------------------------------------------
    +FILE: fnc_stopRecording.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_stopRecording
    +
    +Description:
    +  Stops recording the current mission. Can be used to pause the recording for later resumption. Also called automatically as part of <OCAP_recorder_fnc_exportData>.
    +
    +  Called via <OCAP_pause> via direct CBA event or the administrative diary entry.
    +
    +Parameters:
    +  None
    +
    +Returns:
    +  Nothing
    +
    +Examples:
    +  > call FUNC(stopRecording);
    +
    +Public:
    +  No
    +
    +Author:
    +  Dell, Zealot, IndigoFox
    +---------------------------------------------------------------------------- */
    +#include "script_component.hpp"
    +
    +private _systemTimeFormat = ["%1-%2-%3T%4:%5:%6.%7"];
    +_systemTimeFormat append (systemTimeUTC apply {if (_x < 10) then {"0" + str _x} else {str _x}});
    +private _missionDateFormat = ["%1-%2-%3T%4:%5:00"];
    +_missionDateFormat append (date apply {if (_x < 10) then {"0" + str _x} else {str _x}});
    +
    +[QGVARMAIN(customEvent), ["generalEvent", "Recording paused."]] call CBA_fnc_serverEvent;
    +["OCAP stopped recording", 1, [1, 1, 1, 1]] remoteExecCall ["CBA_fnc_notify", [0, -2] select isDedicated];
    +
    +[[cba_missionTime, format _missionDateFormat, format _systemTimeFormat], { // add diary entry for clients on recording pause
    +  [{!isNull player}, {
    +    player createDiaryRecord [
    +      "OCAPInfo",
    +      [
    +        "Status",
    +        format["<font color='#33FF33'>OCAP stopped recording.<br/>In-Mission Time Elapsed: %1<br/>Mission World Time: %2<br/>System Time UTC: %3</font>", _this#0, _this#1, _this#2]
    +      ]
    +    ];
    +    player setDiarySubjectPicture [
    +      "OCAPInfo",
    +      "\A3\ui_f\data\igui\cfg\simpleTasks\types\use_ca.paa"
    +    ];
    +  }, _this] call CBA_fnc_waitUntilAndExecute;
    +}] remoteExec ["call", [0, -2] select isDedicated, true];
    +
    +// Log times
    +[] call FUNC(updateTime);
    +
    +GVAR(recording) = false;
    +publicVariable QGVAR(recording);
    diff --git a/addons/@ocap/addons/ocap/functions/fn_updateTime.sqf b/x/ocap/addons/recorder/fnc_updateTime.sqf
    similarity index 59%
    rename from addons/@ocap/addons/ocap/functions/fn_updateTime.sqf
    rename to x/ocap/addons/recorder/fnc_updateTime.sqf
    index 0383625..3cc3c41 100644
    --- a/addons/@ocap/addons/ocap/functions/fn_updateTime.sqf
    +++ b/x/ocap/addons/recorder/fnc_updateTime.sqf
    @@ -1,8 +1,10 @@
     /* ----------------------------------------------------------------------------
    -Script: ocap_fnc_updateTime
    +FILE: fnc_updateTime.sqf
    +
    +FUNCTION: OCAP_recorder_fnc_updateTime
     
     Description:
    -	Sends server's system time, mission environment date/time, time multiplier setting, and time since mission start (post-briefing) to the extension. Will run on a recurring basis as part of <ocap_fnc_startCaptureLoop> if the setting in userconfig.hpp is configured to do so. This is required in missions that utilize time acceleration or have time skips as part of mission flow.
    +	Sends server's system time, mission environment date/time, time multiplier setting, and time since mission start (post-briefing) to the extension. Will run on a recurring basis as part of <FUNC(captureLoop)> if the setting in userconfig.hpp is configured to do so. This is required in missions that utilize time acceleration or have time skips as part of mission flow.
     
     Parameters:
     	_date - A manual in-game time to check. [optional, Array]
    @@ -11,9 +13,7 @@ Returns:
     	Nothing
     
     Examples:
    -	--- Code
    -	[] call ocap_fnc_updateTime;
    -	---
    +	> [] call FUNC(updateTime);
     
     Public:
     	No
    @@ -21,25 +21,24 @@ Public:
     Author:
     	Fank
     ---------------------------------------------------------------------------- */
    -
    -#include "script_macros.hpp"
    +#include "script_component.hpp"
     
     params [
    -	["_date", []]
    +  ["_date", []]
     ];
     
     private _systemTimeFormat = ["%1-%2-%3T%4:%5:%6.%7"];
     _systemTimeFormat append (systemTimeUTC apply {if (_x < 10) then {"0" + str _x} else {str _x}});
     private _missionDateFormat = ["%1-%2-%3T%4:%5:00"];
     if (_date isEqualTo []) then {
    -	_date = date;
    +  _date = date;
     };
     _missionDateFormat append (_date apply {if (_x < 10) then {"0" + str _x} else {str _x}});
     
     [":TIME:", [
    -	ocap_captureFrameNo,
    -	format _systemTimeFormat,
    -	format _missionDateFormat,
    -	timeMultiplier,
    -	time
    -]] call ocap_fnc_extension;
    +  GVAR(captureFrameNo),
    +  format _systemTimeFormat,
    +  format _missionDateFormat,
    +  timeMultiplier,
    +  time
    +]] call EFUNC(extension,sendData);
    diff --git a/x/ocap/addons/recorder/script_component.hpp b/x/ocap/addons/recorder/script_component.hpp
    new file mode 100644
    index 0000000..ac61b0f
    --- /dev/null
    +++ b/x/ocap/addons/recorder/script_component.hpp
    @@ -0,0 +1,8 @@
    +// HEADER: script_component.hpp
    +
    +// DEFINE: COMPONENT
    +#define COMPONENT recorder
    +// DEFINE: COMPONENT_BEAUTIFIED
    +#define COMPONENT_BEAUTIFIED Recorder
    +
    +#include "\x\ocap\addons\main\script_macros.hpp"