LAATCMonitor.sqf 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. LAATCMonitor.SQF
  3. Custom script for SWOP's LAAT/c cargo bird for loading and unloading objects (vehicles, turrets, crates etc) with
  4. options to customize attaching and detaching positions for specific object types
  5. JIP and MP Compatible and works alongside slingloading
  6. Written for Arma 3's Star Wars Opposition Mod by ^bdc January 2018
  7. */
  8. // Global Configuration Vars
  9. co18_BDC_LAATCMonitor_AirCargoTypes = ["swop_LAAT_cargo"]; // default: "swop_LAAT_cargo" contingent on classname change
  10. co18_BDC_LAATCMonitor_ExcludedObjects = []; // List of any classnames of objects we do NOT want to be able to pick up
  11. co18_BDC_LAATCMonitor_ReverseObjects = ["SW_AV7"]; // Object to load in 180* direction
  12. co18_BDC_LAATCMonitor_IncludeAircraft = true; // If true, parent class 'Air' will be included in scan search and loading functionality (default: false)
  13. co18_BDC_LAATCMonitor_IncludeAircraftObjects = [ // List of aircraft classes (by object classname) that will be able to be loaded (if other air are not in this list, they will be automatically excluded)
  14. "swop_LAAT","swop_LAATmk2","swop_LAATmk2_104","swop_LAATmk2_74","swop_LAATmk2_ARC","swop_LAATmk2_spec" // LAAT gunships
  15. ];
  16. co18_BDC_LAATCMonitor_ForceEmptyCrewOnly = false; // If true, LAAT cargo bird will only load vehicle objects that are empty of any player or AI crew
  17. co18_BDC_LAATCMonitor_ParachuteDropAlt = 40; // Terrain altitude, in meters, that cargo bird will automatically add a parachute to object being dropped (set to 0 to disable) (default: 40)
  18. co18_BDC_LAATCMonitor_SearchPoint = [0,-2,-6]; // back behind and lower a bit (default: [0,-2,-6]
  19. co18_BDC_LAATCMonitor_ScanRange = 7.5; // Scan range, in meters radius from the configured SearchPoint behind and under the cargo bird, that we'll look for a compatible object we can attach (default: 7.5)
  20. co18_BDC_LAATCMonitor_AttachPoint = [0,-2,-1.5]; // default: [0,-2,-1.5]
  21. co18_BDC_LAATCMonitor_SpecificAttachPoints = [ // List of specific object classes or config classes (as a list in array form) that have specific attachment points to the underside of the bird
  22. // Array structure: [["classname or type","classname","classname"],[x,y,z]],
  23. [["Republic_ATTE"],[0,-1.65,-7.75]], // Republic AT-TE turret tank monstrosity
  24. [["SW_FIELDGUN"],[0,-2.5,-6.75]], // Republic large turret - move it back a bit so the main turret isn't sticking thru the cockpit
  25. [["SW_AV7"],[0,-4,-9]], // AV7
  26. [["O_JM_TX130r_1","O_JM_TX130m1r_1","O_JM_TX130m2r_1","O_JM_TX130_1","O_JM_TX130m1_1","O_JM_TX130m2_1"],[0,0,-4.0]], // Sabre tanks raised up due to short body
  27. [["Slingload_base_F","Slingload_01_Base_F"],[0,-3,-1.5]], // Cargo containers - move back and up
  28. [["swop_LAAT","swop_LAATmk2","swop_LAATmk2_104","swop_LAATmk2_74","swop_LAATmk2_ARC","swop_LAATmk2_spec"],[0,0,-4.35]] // LAAT gunships
  29. ];
  30. co18_BDC_LAATCMonitor_DetachPoint = [0,0,-3.0]; // Detach point relative to the attached point of the cargo object - Do we want to move it left/right, forward/back, or up/down any when we detach?
  31. co18_BDC_LAATCMonitor_SpecificDetachPoints = [ // List of specific objects that require a specific detachment point (such as vehicles with length turrets) relative to the attached point of that object
  32. [["Republic_ATTE"],[0,-2,-2]], // Republic AT-TE move it back some to prevent turret from sticking to LAAT cockpit body
  33. [["SW_AV7"],[0,0,-1.25]], // AV7 turret
  34. [["Slingload_base_F","Slingload_01_Base_F"],[0,0,-1.5]], // Cargo containers - lower a bit
  35. [["swop_LAAT","swop_LAATmk2","swop_LAATmk2_104","swop_LAATmk2_74","swop_LAATmk2_ARC","swop_LAATmk2_spec"],[0,0,-5.25]] // LAAT gunships
  36. ];
  37. co18_BDC_LAATCMonitor_SpecificParachuteAttachPoints = [ // Specific attach points of unloaded object to parachute per classname
  38. [["Republic_ATTE"],1.25], // Array structure: [["Classname1","Classname2",etc],-2] // Where classnames1 and 2 will attach themselves to the parachute at 2 meters above 0,0,0 relative to the chute itself
  39. [["swop_LAAT","swop_LAATmk2","swop_LAATmk2_104","swop_LAATmk2_74","swop_LAATmk2_ARC","swop_LAATmk2_spec"],3.75] // LAAT gunships
  40. ];
  41. co18_BDC_LAATCMonitor_MinimumLoadAlt = 4; // default: 4
  42. co18_BDC_LAATCMonitor_MinimumDropAlt = 5.5; // default: 5.5 to 6 - Set to 5m as absolute minimum lowest due to larger objects such as the AT-TE to prevent collisions
  43. // Attach cargo chute function
  44. co18_BDC_LAATCMonitor_AttachCargoParachuteFunc = {
  45. _Object = _this select 0;
  46. diag_log format["(LAAT/C Monitor) AttachCargoParachuteFunc spawned. Created chute for %1 %2",_Object,typeOf _Object];
  47. sleep 3.5;
  48. _Chute = createVehicle ["B_Parachute_02_F", (getPos _Object), [], 0, "FLY"];
  49. _Chute setPos (getPos _Object);
  50. _Chute setDir (getDir _Object);
  51. _Chute allowDamage false;
  52. _ZPos = -0.65;
  53. _isCrate = (_Object isKindOf "Slingload_base_F" || _Object isKindOf "ReammoBox_F" || _Object isKindOf "ReammoBox");
  54. if (!_isCrate) then {
  55. _ZPos = 1.65; // Attach object to chute higher than chute's 0,0,0 to help prevent collision with ground when landing - default attach point for larger objects
  56. };
  57. _Type = typeOf _Object;
  58. _FoundSpecific = false;
  59. {
  60. _Array = _x;
  61. _VTypes = _Array select 0;
  62. _AttachZ = _Array select 1;
  63. if (_Type in _VTypes && !_FoundSpecific) then {
  64. _ZPos = _AttachZ;
  65. _FoundSpecific = true;
  66. diag_log format["(LAAT/C Monitor) Found custom attach point for parachute: %1",_ZPos];
  67. };
  68. } forEach co18_BDC_LAATCMonitor_SpecificParachuteAttachPoints;
  69. _Object attachTo [_Chute,[0,0,_ZPos]];
  70. };
  71. // Server-side EH to manage parachuting
  72. if (isServer || isDedicated) then {
  73. "CO18_BDC_LAATCMonitor_AttachCargoParachute" addPublicVariableEventhandler {
  74. _Object = _this select 1;
  75. diag_log format["(LAAT/C Monitor) AttachCargoParachute EH called for Object %1 %2.",_Object,typeOf _Object];
  76. [_Object] spawn co18_BDC_LAATCMonitor_AttachCargoParachuteFunc;
  77. };
  78. };
  79. if (!hasInterface) exitWith {}; // Only players from here on out
  80. // Reset loading and unloading scroll actions and global vars
  81. co18_BDC_r_player_LoadViVCargo = -1;
  82. co18_BDC_r_player_UnloadViVCargo = -1;
  83. co18_BDC_r_player_CheckViVCargo = -1;
  84. co18_BDC_r_player_DisableParachute = -1;
  85. co18_BDC_r_player_EnableParachute = -1;
  86. co18_BDC_r_player_nearestViVObject = objNull;
  87. _MonitorPlayerAircraft = {
  88. diag_log format["(LAAT/C Monitor) Starting monitor loop."];
  89. while {true} do {
  90. // Vehicles work-around
  91. if (alive player && (vehicle player != player)) then {
  92. _Vehicle = vehicle player;
  93. _VehType = typeOf _Vehicle;
  94. _isDriver = false;
  95. if (driver _Vehicle == player) then { _isDriver = true; };
  96. if (!alive _Vehicle) then { _isDriver = false; };
  97. // LAAT Cargo bird ViV loading of objects
  98. if (_isDriver && (_VehType in co18_BDC_LAATCMonitor_AirCargoTypes)) then {
  99. // Gather altitude and speed
  100. _vAlt = round ((getposATL _Vehicle) select 2);
  101. _vSpeed = round(speed _Vehicle);
  102. // See if there's any actual ViV cargo loaded in (from Zeus or editor presumably)
  103. _ViVCargoArray = getVehicleCargo _Vehicle;
  104. if (count _ViVCargoArray > 0) then {
  105. _ViVObj = _ViVCargoArray select 0;
  106. _Vehicle setVariable ["VehViVCargo",_ViVObj,true]; // Convert to our system so we can unload it our way
  107. };
  108. // Flag to DISABLE ViV cargo loading
  109. _isEnabled = false;
  110. _isEnabled = _Vehicle getVariable ["ViVCargoEnabled",false];
  111. if (_isEnabled) then { // Only runs once per live vehicle once first pilot enters
  112. //_Vehicle enableVehicleCargo true;
  113. _Vehicle setVariable ["ViVCargoEnabled",false,true];
  114. diag_log format["Cargo bird %1 %2 ViV cargo loading disabled.",_Vehicle,typeOf _Vehicle];
  115. };
  116. // Check and Unload cargo
  117. //_VehViVCargo = getVehicleCargo _Vehicle;
  118. _VehViVCargo = _Vehicle getVariable ["VehViVCargo",objNull];
  119. _ParachuteDropDisabled = _Vehicle getVariable ["CargoParachuteDisabled",false];
  120. // Disable/enable automatic cargo parachute
  121. if (co18_BDC_LAATCMonitor_ParachuteDropAlt > 0) then {
  122. if (_ParachuteDropDisabled) then {
  123. if (co18_BDC_r_player_EnableParachute < 0) then {
  124. co18_BDC_r_player_EnableParachute = player addAction ["Enable Parachute for Cargo Drop", {
  125. (vehicle player) setVariable ["CargoParachuteDisabled",false,true];
  126. hint format["Automatic parachute for cargo drop enabled. Cargo will automatically drop with attached parachute when dropped from altitudes of %1 meters and above.",co18_BDC_LAATCMonitor_ParachuteDropAlt];
  127. player removeAction co18_BDC_r_player_EnableParachute;
  128. co18_BDC_r_player_EnableParachute = -1;
  129. }];
  130. };
  131. } else {
  132. if (co18_BDC_r_player_DisableParachute < 0) then {
  133. co18_BDC_r_player_DisableParachute = player addAction ["Disable Parachute for Cargo Drop", {
  134. (vehicle player) setVariable ["CargoParachuteDisabled",true,true];
  135. hint "Automatic parachute for cargo drop disabled.";
  136. player removeAction co18_BDC_r_player_DisableParachute;
  137. co18_BDC_r_player_DisableParachute = -1;
  138. }];
  139. };
  140. };
  141. };
  142. if !(isNull _VehViVCargo) then {
  143. // Check ViV loaded cargo
  144. if (co18_BDC_r_player_CheckViVCargo < 0) then {
  145. _ObjTxt = getText (configFile >> "CfgVehicles" >> typeOf _VehViVCargo >> "displayName");
  146. _FStr = format["Analyze Attached Cargo %1",_ObjTxt];
  147. co18_BDC_r_player_CheckViVCargo = player addAction [_FStr, {
  148. _Vehicle = vehicle player;
  149. _VehViVCargo = _Vehicle getVariable ["VehViVCargo",objNull];
  150. s_player_HintCtr = 40;
  151. _ObjTxt = getText (configFile >> "CfgVehicles" >> typeOf _VehViVCargo >> "displayName");
  152. _Fuel = round(fuel _VehViVCargo);
  153. _FuelTxt = round(_Fuel * 100);
  154. _Damage = getDammage _VehViVCargo;
  155. _DamageTxt = round (_Damage / 100);
  156. _CrewNum = count (crew _VehViVCargo);
  157. hint format["Attached Cargo:\n%1\n\nFuel: %2 percent\nDamage: %3 percent\nCrew Number: %4",_ObjTxt,_FuelTxt,_DamageTxt,_CrewNum];
  158. player removeAction co18_BDC_r_player_CheckViVCargo;
  159. co18_BDC_r_player_CheckViVCargo = -1;
  160. }];
  161. };
  162. // Unload
  163. if (_vAlt >= co18_BDC_LAATCMonitor_MinimumDropAlt) then {
  164. if (co18_BDC_r_player_UnloadViVCargo < 0) then {
  165. _ObjTxt = getText (configFile >> "CfgVehicles" >> typeOf _VehViVCargo >> "displayName");
  166. _FStr = format["Unload %1",_ObjTxt];
  167. /*
  168. if (_vAlt >= co18_BDC_LAATCMonitor_ParachuteDropAlt && (co18_BDC_LAATCMonitor_ParachuteDropAlt > 15)) then { // absolute minimum 15 meters
  169. _FStr = format["Unload %1 (Parachute)",_ObjTxt];
  170. }; */
  171. co18_BDC_r_player_UnloadViVCargo = player addAction [_FStr, {
  172. _Vehicle = vehicle player;
  173. _VehViVCargo = _Vehicle getVariable ["VehViVCargo",objNull];
  174. s_player_HintCtr = 30;
  175. _ObjTxt = getText (configFile >> "CfgVehicles" >> typeOf _VehViVCargo >> "displayName");
  176. private["_DetachPoint"];
  177. _DetachPoint = _VehViVCargo modelToWorld co18_BDC_LAATCMonitor_DetachPoint; // default
  178. _Vehicle allowDamage false;
  179. // Find our detachment point
  180. _FoundDetachPt = false;
  181. {
  182. _Selection = _x;
  183. _ClassArray = _Selection select 0;
  184. _PosArray = _Selection select 1;
  185. {
  186. _ClassStr = _x;
  187. if (typeOf _VehViVCargo == _ClassStr || _VehViVCargo isKindOf _ClassStr && !_FoundDetachPt) then {
  188. _DetachPoint = _VehViVCargo modelToWorld _PosArray;
  189. _FoundDetachPt = true;
  190. };
  191. } forEach _ClassArray;
  192. } forEach co18_BDC_LAATCMonitor_SpecificDetachPoints;
  193. detach _VehViVCargo;
  194. _VehViVCargo setPos _DetachPoint; // Move to detach point
  195. _VehViVCargo allowDamage false; // Temp invulnerability for our attached object
  196. _VehViVCargo enableRopeAttach true;
  197. // Attach parachute?
  198. _vAlt = round ((getposATL _Vehicle) select 2);
  199. _ParachuteDropDisabled = _Vehicle getVariable ["CargoParachuteDisabled",false];
  200. hint format["Unloading %1...",_ObjTxt];
  201. if ((_vAlt >= co18_BDC_LAATCMonitor_ParachuteDropAlt) && (co18_BDC_LAATCMonitor_ParachuteDropAlt > 15) && !_ParachuteDropDisabled) then { // Ping server to create and attach chute
  202. if (isServer) then {
  203. [_VehViVCargo] spawn co18_BDC_LAATCMonitor_AttachCargoParachuteFunc;
  204. } else {
  205. CO18_BDC_LAATCMonitor_AttachCargoParachute = _VehViVCargo;
  206. publicVariableServer "CO18_BDC_LAATCMonitor_AttachCargoParachute";
  207. };
  208. hint format["Unloading %1 with parachute...",_ObjTxt];
  209. };
  210. // Brief sleep before making cargo bird vulnerable
  211. sleep 0.5;
  212. _Vehicle allowDamage true;
  213. _Vehicle setVariable ["VehViVCargo",objNull,true]; // reset our cargo variable
  214. // Set specific position here?
  215. player removeAction co18_BDC_r_player_LoadViVCargo;
  216. co18_BDC_r_player_LoadViVCargo = -1;
  217. player removeAction co18_BDC_r_player_UnloadViVCargo;
  218. co18_BDC_r_player_UnloadViVCargo = -1;
  219. player removeAction co18_BDC_r_player_CheckViVCargo;
  220. co18_BDC_r_player_CheckViVCargo = -1;
  221. r_nearestViVObject = objNull;
  222. sleep 4; // Disallow further actions for 5 seconds after unloading
  223. _VehViVCargo allowDamage true;
  224. }];
  225. };
  226. } else {
  227. player removeAction co18_BDC_r_player_UnloadViVCargo;
  228. co18_BDC_r_player_UnloadViVCargo = -1;
  229. };
  230. };
  231. // Search for nearestObjects to load cargo
  232. _ScanPoint = _Vehicle modelToWorld co18_BDC_LAATCMonitor_SearchPoint;
  233. _nearestObjects = [];
  234. if (isNull _VehViVCargo) then {
  235. _nearestObjects = nearestObjects [_ScanPoint, ["LandVehicle","Slingload_base_F","ReammoBox_F","ReammoBox","StaticWeapon","StaticCannon","StaticMGWeapon","Air"], co18_BDC_LAATCMonitor_ScanRange];
  236. // Remove attached object if it's popping up in our nearestObjects scan - Also remove any that are in the excluded list - Remove dead objects as well
  237. if (count _nearestObjects > 0) then {
  238. {
  239. if ((_Vehicle == _x) || _VehViVCargo == _x || (typeOf _x in co18_BDC_LAATCMonitor_ExcludedObjects) || (!alive _x) || (_x == player)) then {
  240. _nearestObjects = _nearestObjects - [_x];
  241. };
  242. // Empty crew only?
  243. if (co18_BDC_LAATCMonitor_ForceEmptyCrewOnly && (count (crew _x) > 0)) then {
  244. _nearestObjects = _nearestObjects - [_x];
  245. };
  246. // Exclude any non-specified aircraft
  247. if ((_x isKindOf "Air" && !co18_BDC_LAATCMonitor_IncludeAircraft) || (_x isKindOf "Air" && !(typeOf _x in co18_BDC_LAATCMonitor_IncludeAircraftObjects))) then {
  248. _nearestObjects = _nearestObjects - [_x];
  249. };
  250. } forEach _nearestObjects;
  251. };
  252. };
  253. if (count _nearestObjects == 0) then {
  254. player removeAction co18_BDC_r_player_LoadViVCargo;
  255. co18_BDC_r_player_LoadViVCargo = -1;
  256. };
  257. if (count _nearestObjects > 0) then {
  258. co18_BDC_r_player_nearestViVObject = _nearestObjects select 0;
  259. _TypeNO = typeOf co18_BDC_r_player_nearestViVObject;
  260. if ((co18_BDC_r_player_nearestViVObject != _VehViVCargo) && (co18_BDC_r_player_nearestViVObject isKindOf "StaticCannon" || co18_BDC_r_player_nearestViVObject isKindOf "StaticMGWeapon" || co18_BDC_r_player_nearestViVObject isKindOf "Car" || co18_BDC_r_player_nearestViVObject isKindOf "Tank" || co18_BDC_r_player_nearestViVObject isKindOf "ReammoBox" || co18_BDC_r_player_nearestViVObject isKindOf "ReammoBox_F" || co18_BDC_r_player_nearestViVObject isKindOf "Slingload_base_F" || (co18_BDC_r_player_nearestViVObject isKindOf "Air" && co18_BDC_LAATCMonitor_IncludeAircraft)) && (_vSpeed <= 15) && (_vAlt >= co18_BDC_LAATCMonitor_MinimumLoadAlt)) then {
  261. _Txt = getText (configFile >> "CfgVehicles" >> _TypeNO >> "displayName");
  262. _FStr = format["Load %1",_Txt];
  263. if (co18_BDC_r_player_LoadViVCargo < 0) then {
  264. co18_BDC_r_player_LoadViVCargo = player addAction [_FStr, {
  265. _Vehicle = vehicle player;
  266. _Txt = getText (configFile >> "CfgVehicles" >> (typeOf co18_BDC_r_player_nearestViVObject) >> "displayName");
  267. s_player_HintCtr = 30;
  268. hint format["%1 has been loaded.",_Txt];
  269. _Vehicle setVariable ["VehViVCargo",co18_BDC_r_player_nearestViVObject,true];
  270. co18_BDC_r_player_nearestViVObject enableRopeAttach false;
  271. // Find attachment point
  272. private["_AttachPoint"];
  273. _AttachPoint = co18_BDC_LAATCMonitor_AttachPoint; // default
  274. _FoundSpecific = false;
  275. {
  276. _Selection = _x;
  277. _ClassArray = _Selection select 0;
  278. _PosArray = _Selection select 1;
  279. {
  280. _ClassStr = _x;
  281. if ((co18_BDC_r_player_nearestViVObject isKindOf _ClassStr || typeOf co18_BDC_r_player_nearestViVObject == _ClassStr) && !_FoundSpecific) then {
  282. _FoundSpecific = true;
  283. _AttachPoint = _PosArray;
  284. };
  285. } forEach _ClassArray;
  286. } forEach co18_BDC_LAATCMonitor_SpecificAttachPoints;
  287. co18_BDC_r_player_nearestViVObject attachTo [_Vehicle, _AttachPoint];
  288. // Reverse direction
  289. if (typeOf co18_BDC_r_player_nearestViVObject in co18_BDC_LAATCMonitor_ReverseObjects) then {
  290. _VDir = getDir _Vehicle;
  291. _ReverseDir = _VDir + 180;
  292. co18_BDC_r_player_nearestViVObject setDir _ReverseDir;
  293. };
  294. player removeAction co18_BDC_r_player_LoadViVCargo;
  295. co18_BDC_r_player_LoadViVCargo = -1;
  296. co18_BDC_r_player_nearestViVObject = objNull;
  297. player removeAction co18_BDC_r_player_UnloadViVCargo;
  298. co18_BDC_r_player_UnloadViVCargo = -1;
  299. }];
  300. };
  301. } else {
  302. player removeAction co18_BDC_r_player_LoadViVCargo;
  303. co18_BDC_r_player_LoadViVCargo = -1;
  304. co18_BDC_r_player_nearestViVObject = objNull;
  305. };
  306. };
  307. } else {
  308. player removeAction co18_BDC_r_player_LoadViVCargo;
  309. co18_BDC_r_player_LoadViVCargo = -1;
  310. player removeAction co18_BDC_r_player_UnloadViVCargo;
  311. co18_BDC_r_player_UnloadViVCargo = -1;
  312. player removeAction co18_BDC_r_player_CheckViVCargo;
  313. co18_BDC_r_player_CheckViVCargo = -1;
  314. co18_BDC_r_player_nearestViVObject = objNull;
  315. };
  316. } else {
  317. /*
  318. // If vehicle is dead and we have cargo attached, destroy it too
  319. _VehViVCargo = (vehicle player) getVariable ["VehViVCargo",objNull];
  320. if (!alive _Vehicle && !(isNull _VehViVCargo)) then {
  321. detach _VehViVCargo;
  322. _VehViVCargo setDamage 1;
  323. }; */
  324. player removeAction co18_BDC_r_player_LoadViVCargo;
  325. co18_BDC_r_player_LoadViVCargo = -1;
  326. player removeAction co18_BDC_r_player_UnloadViVCargo;
  327. co18_BDC_r_player_UnloadViVCargo = -1;
  328. player removeAction co18_BDC_r_player_CheckViVCargo;
  329. co18_BDC_r_player_CheckViVCargo = -1;
  330. co18_BDC_r_player_nearestViVObject = objNull;
  331. player removeAction co18_BDC_r_player_EnableParachute;
  332. co18_BDC_r_player_EnableParachute = -1;
  333. player removeAction co18_BDC_r_player_DisableParachute;
  334. co18_BDC_r_player_DisableParachute = -1;
  335. };
  336. sleep 1;
  337. };
  338. };
  339. [] spawn _MonitorPlayerAircraft;
  340. diag_log format["(LAAT/C Monitor) Script running."];