Advertisement
Guest User

Untitled

a guest
Apr 25th, 2019
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.95 KB | None | 0 0
  1. diag_log "Towing script line 1 found...";
  2. #define SA_Find_Surface_ASL_Under_Position(_object,_positionAGL,_returnSurfaceASL,_canFloat) \
  3. _objectASL = AGLToASL (_object modelToWorldVisual (getCenterOfMass _object)); \
  4. _surfaceIntersectStartASL = [_positionAGL select 0, _positionAGL select 1, (_objectASL select 2) + 1]; \
  5. _surfaceIntersectEndASL = [_positionAGL select 0, _positionAGL select 1, (_objectASL select 2) - 5]; \
  6. _surfaces = lineIntersectsSurfaces [_surfaceIntersectStartASL, _surfaceIntersectEndASL, _object, objNull, true, 5]; \
  7. _returnSurfaceASL = AGLToASL _positionAGL; \
  8. { \
  9. scopeName "surfaceLoop"; \
  10. if( isNull (_x select 2) ) then { \
  11. _returnSurfaceASL = _x select 0; \
  12. breakOut "surfaceLoop"; \
  13. } else { \
  14. if!((_x select 2) isKindOf "RopeSegment") then { \
  15. _objectFileName = str (_x select 2); \
  16. if((_objectFileName find " t_") == -1 && (_objectFileName find " b_") == -1) then { \
  17. _returnSurfaceASL = _x select 0; \
  18. breakOut "surfaceLoop"; \
  19. }; \
  20. }; \
  21. }; \
  22. } forEach _surfaces; \
  23. if(_canFloat && (_returnSurfaceASL select 2) < 0) then { \
  24. _returnSurfaceASL set [2,0]; \
  25. }; \
  26. diag_log "Towing script started...";
  27. #define SA_Find_Surface_ASL_Under_Model(_object,_modelOffset,_returnSurfaceASL,_canFloat) \
  28. SA_Find_Surface_ASL_Under_Position(_object, (_object modelToWorldVisual _modelOffset), _returnSurfaceASL,_canFloat);
  29.  
  30. #define SA_Find_Surface_AGL_Under_Model(_object,_modelOffset,_returnSurfaceAGL,_canFloat) \
  31. SA_Find_Surface_ASL_Under_Model(_object,_modelOffset,_returnSurfaceAGL,_canFloat); \
  32. _returnSurfaceAGL = ASLtoAGL _returnSurfaceAGL;
  33.  
  34. #define SA_Get_Cargo(_vehicle,_cargo) \
  35. if( count (ropeAttachedObjects _vehicle) == 0 ) then { \
  36. _cargo = objNull; \
  37. } else { \
  38. _cargo = ((ropeAttachedObjects _vehicle) select 0) getVariable ["SA_Cargo",objNull]; \
  39. };
  40.  
  41. SA_Advanced_Towing_Install = {
  42.  
  43. // Prevent advanced towing from installing twice
  44. if(!isNil "SA_TOW_INIT") exitWith {};
  45. SA_TOW_INIT = true;
  46.  
  47. diag_log "Advanced Towing Loading...";
  48.  
  49. SA_Simulate_Towing_Speed = {
  50.  
  51. params ["_vehicle"];
  52.  
  53. private ["_runSimulation","_currentCargo","_maxVehicleSpeed","_maxTowedVehicles","_vehicleMass"];
  54.  
  55. _maxVehicleSpeed = getNumber (configFile >> "CfgVehicles" >> typeOf _vehicle >> "maxSpeed");
  56. _vehicleMass = 1000 max (getMass _vehicle);
  57. _maxTowedCargo = missionNamespace getVariable ["SA_MAX_TOWED_CARGO",2];
  58. _runSimulation = true;
  59.  
  60. private ["_currentVehicle","_totalCargoMass","_totalCargoCount","_findNextCargo","_towRopes","_ropeLength"];
  61. private ["_ends","_endsDistance","_currentMaxSpeed","_newMaxSpeed"];
  62.  
  63. while {_runSimulation} do {
  64.  
  65. // Calculate total mass and count of cargo being towed (only takes into account
  66. // cargo that's actively being towed (e.g. there's no slack in the rope)
  67.  
  68. _currentVehicle = _vehicle;
  69. _totalCargoMass = 0;
  70. _totalCargoCount = 0;
  71. _findNextCargo = true;
  72. while {_findNextCargo} do {
  73. _findNextCargo = false;
  74. SA_Get_Cargo(_currentVehicle,_currentCargo);
  75. if(!isNull _currentCargo) then {
  76. _towRopes = _currentVehicle getVariable ["SA_Tow_Ropes",[]];
  77. if(count _towRopes > 0) then {
  78. _ropeLength = ropeLength (_towRopes select 0);
  79. _ends = ropeEndPosition (_towRopes select 0);
  80. _endsDistance = (_ends select 0) distance (_ends select 1);
  81. if( _endsDistance >= _ropeLength - 2 ) then {
  82. _totalCargoMass = _totalCargoMass + (1000 max (getMass _currentCargo));
  83. _totalCargoCount = _totalCargoCount + 1;
  84. _currentVehicle = _currentCargo;
  85. _findNextCargo = true;
  86. };
  87. };
  88. };
  89. };
  90.  
  91. _newMaxSpeed = _maxVehicleSpeed / (1 max ((_totalCargoMass / _vehicleMass) * 2));
  92. _newMaxSpeed = (_maxVehicleSpeed * 0.75) min _newMaxSpeed;
  93.  
  94. // Prevent vehicle from moving if trying to move more cargo than pre-defined max
  95. if(_totalCargoCount > _maxTowedCargo) then {
  96. _newMaxSpeed = 0;
  97. };
  98.  
  99. _currentMaxSpeed = _vehicle getVariable ["SA_Max_Tow_Speed",_maxVehicleSpeed];
  100.  
  101. if(_currentMaxSpeed != _newMaxSpeed) then {
  102. _vehicle setVariable ["SA_Max_Tow_Speed",_newMaxSpeed];
  103. };
  104.  
  105. sleep 0.1;
  106.  
  107. };
  108. };
  109.  
  110. SA_Simulate_Towing = {
  111.  
  112. params ["_vehicle","_vehicleHitchModelPos","_cargo","_cargoHitchModelPos","_ropeLength"];
  113.  
  114. private ["_lastCargoHitchPosition","_lastCargoVectorDir","_cargoLength","_maxDistanceToCargo","_lastMovedCargoPosition","_cargoHitchPoints"];
  115. private ["_vehicleHitchPosition","_cargoHitchPosition","_newCargoHitchPosition","_cargoVector","_movedCargoVector","_attachedObjects","_currentCargo"];
  116. private ["_newCargoDir","_lastCargoVectorDir","_newCargoPosition","_doExit","_cargoPosition","_vehiclePosition","_maxVehicleSpeed","_vehicleMass","_cargoMass","_cargoCanFloat"];
  117. private ["_cargoCorner1AGL","_cargoCorner1ASL","_cargoCorner2AGL","_cargoCorner2ASL","_cargoCorner3AGL","_cargoCorner3ASL","_cargoCorner4AGL","_cargoCorner4ASL","_surfaceNormal1","_surfaceNormal2","_surfaceNormal"];
  118. private ["_cargoCenterASL","_surfaceHeight","_surfaceHeight2","_maxSurfaceHeight"];
  119.  
  120. _maxVehicleSpeed = getNumber (configFile >> "CfgVehicles" >> typeOf _vehicle >> "maxSpeed");
  121. _cargoCanFloat = if( getNumber (configFile >> "CfgVehicles" >> typeOf _cargo >> "canFloat") == 1 ) then { true } else { false };
  122.  
  123. private ["_cargoCenterOfMassAGL","_cargoModelCenterGroundPosition"];
  124. SA_Find_Surface_AGL_Under_Model(_cargo,getCenterOfMass _cargo,_cargoCenterOfMassAGL,_cargoCanFloat);
  125. _cargoModelCenterGroundPosition = _cargo worldToModelVisual _cargoCenterOfMassAGL;
  126. _cargoModelCenterGroundPosition set [0,0];
  127. _cargoModelCenterGroundPosition set [1,0];
  128. _cargoModelCenterGroundPosition set [2, (_cargoModelCenterGroundPosition select 2) - 0.05]; // Adjust height so that it doesn't ride directly on ground
  129.  
  130. // Calculate cargo model corner points
  131. private ["_cargoCornerPoints"];
  132. _cargoCornerPoints = [_cargo] call SA_Get_Corner_Points;
  133. _corner1 = _cargoCornerPoints select 0;
  134. _corner2 = _cargoCornerPoints select 1;
  135. _corner3 = _cargoCornerPoints select 2;
  136. _corner4 = _cargoCornerPoints select 3;
  137.  
  138.  
  139. // Try to set cargo owner if the towing client doesn't own the cargo
  140. if(local _vehicle && !local _cargo) then {
  141. [[_cargo, clientOwner],"SA_Set_Owner"] call SA_RemoteExecServer;
  142. };
  143.  
  144. _vehicleHitchModelPos set [2,0];
  145. _cargoHitchModelPos set [2,0];
  146.  
  147. _lastCargoHitchPosition = _cargo modelToWorld _cargoHitchModelPos;
  148. _lastCargoVectorDir = vectorDir _cargo;
  149. _lastMovedCargoPosition = getPos _cargo;
  150.  
  151. _cargoHitchPoints = [_cargo] call SA_Get_Hitch_Points;
  152. _cargoLength = (_cargoHitchPoints select 0) distance (_cargoHitchPoints select 1);
  153.  
  154. _vehicleMass = 1 max (getMass _vehicle);
  155. _cargoMass = getMass _cargo;
  156. if(_cargoMass == 0) then {
  157. _cargoMass = _vehicleMass;
  158. };
  159.  
  160. _maxDistanceToCargo = _ropeLength;
  161.  
  162. _doExit = false;
  163.  
  164. // Start vehicle speed simulation
  165. [_vehicle] spawn SA_Simulate_Towing_Speed;
  166.  
  167. while {!_doExit} do {
  168.  
  169. _vehicleHitchPosition = _vehicle modelToWorld _vehicleHitchModelPos;
  170. _vehicleHitchPosition set [2,0];
  171. _cargoHitchPosition = _lastCargoHitchPosition;
  172. _cargoHitchPosition set [2,0];
  173.  
  174. _cargoPosition = getPos _cargo;
  175. _vehiclePosition = getPos _vehicle;
  176.  
  177. if(_vehicleHitchPosition distance _cargoHitchPosition > _maxDistanceToCargo) then {
  178.  
  179. // Calculated simulated towing position + direction
  180. _newCargoHitchPosition = _vehicleHitchPosition vectorAdd ((_vehicleHitchPosition vectorFromTo _cargoHitchPosition) vectorMultiply _ropeLength);
  181. _cargoVector = _lastCargoVectorDir vectorMultiply _cargoLength;
  182. _movedCargoVector = _newCargoHitchPosition vectorDiff _lastCargoHitchPosition;
  183. _newCargoDir = vectorNormalized (_cargoVector vectorAdd _movedCargoVector);
  184. //if(_isRearCargoHitch) then {
  185. // _newCargoDir = _newCargoDir vectorMultiply -1;
  186. //};
  187. _lastCargoVectorDir = _newCargoDir;
  188. _newCargoPosition = _newCargoHitchPosition vectorAdd (_newCargoDir vectorMultiply -(vectorMagnitude (_cargoHitchModelPos)));
  189.  
  190. SA_Find_Surface_ASL_Under_Position(_cargo,_newCargoPosition,_newCargoPosition,_cargoCanFloat);
  191.  
  192. // Calculate surface normal (up) (more realistic than surfaceNormal function)
  193. SA_Find_Surface_ASL_Under_Model(_cargo,_corner1,_cargoCorner1ASL,_cargoCanFloat);
  194. SA_Find_Surface_ASL_Under_Model(_cargo,_corner2,_cargoCorner2ASL,_cargoCanFloat);
  195. SA_Find_Surface_ASL_Under_Model(_cargo,_corner3,_cargoCorner3ASL,_cargoCanFloat);
  196. SA_Find_Surface_ASL_Under_Model(_cargo,_corner4,_cargoCorner4ASL,_cargoCanFloat);
  197. _surfaceNormal1 = (_cargoCorner1ASL vectorFromTo _cargoCorner3ASL) vectorCrossProduct (_cargoCorner1ASL vectorFromTo _cargoCorner2ASL);
  198. _surfaceNormal2 = (_cargoCorner4ASL vectorFromTo _cargoCorner2ASL) vectorCrossProduct (_cargoCorner4ASL vectorFromTo _cargoCorner3ASL);
  199. _surfaceNormal = _surfaceNormal1 vectorAdd _surfaceNormal2;
  200.  
  201. if(missionNamespace getVariable ["SA_TOW_DEBUG_ENABLED", false]) then {
  202. if(isNil "sa_tow_debug_arrow_1") then {
  203. sa_tow_debug_arrow_1 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
  204. sa_tow_debug_arrow_2 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
  205. sa_tow_debug_arrow_3 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
  206. sa_tow_debug_arrow_4 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
  207. };
  208. sa_tow_debug_arrow_1 setPosASL _cargoCorner1ASL;
  209. sa_tow_debug_arrow_1 setVectorUp _surfaceNormal;
  210. sa_tow_debug_arrow_2 setPosASL _cargoCorner2ASL;
  211. sa_tow_debug_arrow_2 setVectorUp _surfaceNormal;
  212. sa_tow_debug_arrow_3 setPosASL _cargoCorner3ASL;
  213. sa_tow_debug_arrow_3 setVectorUp _surfaceNormal;
  214. sa_tow_debug_arrow_4 setPosASL _cargoCorner4ASL;
  215. sa_tow_debug_arrow_4 setVectorUp _surfaceNormal;
  216. };
  217.  
  218. // Calculate adjusted surface height based on surface normal (prevents vehicle from clipping into ground)
  219. _cargoCenterASL = AGLtoASL (_cargo modelToWorldVisual [0,0,0]);
  220. _cargoCenterASL set [2,0];
  221. _surfaceHeight = ((_cargoCorner1ASL vectorAdd ( _cargoCenterASL vectorMultiply -1)) vectorDotProduct _surfaceNormal1) / ([0,0,1] vectorDotProduct _surfaceNormal1);
  222. _surfaceHeight2 = ((_cargoCorner1ASL vectorAdd ( _cargoCenterASL vectorMultiply -1)) vectorDotProduct _surfaceNormal2) / ([0,0,1] vectorDotProduct _surfaceNormal2);
  223. _maxSurfaceHeight = (_newCargoPosition select 2) max _surfaceHeight max _surfaceHeight2;
  224. _newCargoPosition set [2, _maxSurfaceHeight ];
  225.  
  226. _newCargoPosition = _newCargoPosition vectorAdd ( _cargoModelCenterGroundPosition vectorMultiply -1 );
  227.  
  228. _cargo setVectorDir _newCargoDir;
  229. _cargo setVectorUp _surfaceNormal;
  230. _cargo setPosWorld _newCargoPosition;
  231.  
  232. _lastCargoHitchPosition = _newCargoHitchPosition;
  233. _maxDistanceToCargo = _vehicleHitchPosition distance _newCargoHitchPosition;
  234. _lastMovedCargoPosition = _cargoPosition;
  235.  
  236. _massAdjustedMaxSpeed = _vehicle getVariable ["SA_Max_Tow_Speed",_maxVehicleSpeed];
  237. if(speed _vehicle > (_massAdjustedMaxSpeed)+0.1) then {
  238. _vehicle setVelocity ((vectorNormalized (velocity _vehicle)) vectorMultiply (_massAdjustedMaxSpeed/3.6));
  239. };
  240.  
  241. } else {
  242.  
  243. if(_lastMovedCargoPosition distance _cargoPosition > 2) then {
  244. _lastCargoHitchPosition = _cargo modelToWorld _cargoHitchModelPos;
  245. _lastCargoVectorDir = vectorDir _cargo;
  246. };
  247.  
  248. };
  249.  
  250. // If vehicle isn't local to the client, switch client running towing simulation
  251. if(!local _vehicle) then {
  252. [_this,"SA_Simulate_Towing",_vehicle] call SA_RemoteExec;
  253. _doExit = true;
  254. };
  255.  
  256. // If the vehicle isn't towing anything, stop the towing simulation
  257. SA_Get_Cargo(_vehicle,_currentCargo);
  258. if(isNull _currentCargo) then {
  259. _doExit = true;
  260. };
  261.  
  262. sleep 0.01;
  263.  
  264. };
  265. };
  266.  
  267. SA_Get_Corner_Points = {
  268. params ["_vehicle"];
  269. private ["_centerOfMass","_bbr","_p1","_p2","_rearCorner","_rearCorner2","_frontCorner","_frontCorner2"];
  270. private ["_maxWidth","_widthOffset","_maxLength","_lengthOffset","_widthFactor","_lengthFactor"];
  271.  
  272. // Correct width and length factor for air
  273. _widthFactor = 0.75;
  274. _lengthFactor = 0.75;
  275. if(_vehicle isKindOf "Air") then {
  276. _widthFactor = 0.3;
  277. };
  278. if(_vehicle isKindOf "Helicopter") then {
  279. _widthFactor = 0.2;
  280. _lengthFactor = 0.45;
  281. };
  282.  
  283. _centerOfMass = getCenterOfMass _vehicle;
  284. _bbr = boundingBoxReal _vehicle;
  285. _p1 = _bbr select 0;
  286. _p2 = _bbr select 1;
  287. _maxWidth = abs ((_p2 select 0) - (_p1 select 0));
  288. _widthOffset = ((_maxWidth / 2) - abs ( _centerOfMass select 0 )) * _widthFactor;
  289. _maxLength = abs ((_p2 select 1) - (_p1 select 1));
  290. _lengthOffset = ((_maxLength / 2) - abs (_centerOfMass select 1 )) * _lengthFactor;
  291. _rearCorner = [(_centerOfMass select 0) + _widthOffset, (_centerOfMass select 1) - _lengthOffset, _centerOfMass select 2];
  292. _rearCorner2 = [(_centerOfMass select 0) - _widthOffset, (_centerOfMass select 1) - _lengthOffset, _centerOfMass select 2];
  293. _frontCorner = [(_centerOfMass select 0) + _widthOffset, (_centerOfMass select 1) + _lengthOffset, _centerOfMass select 2];
  294. _frontCorner2 = [(_centerOfMass select 0) - _widthOffset, (_centerOfMass select 1) + _lengthOffset, _centerOfMass select 2];
  295.  
  296. if(missionNamespace getVariable ["SA_TOW_DEBUG_ENABLED", false]) then {
  297. if(isNil "sa_tow_debug_arrow_1") then {
  298. sa_tow_debug_arrow_1 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
  299. sa_tow_debug_arrow_2 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
  300. sa_tow_debug_arrow_3 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
  301. sa_tow_debug_arrow_4 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
  302. };
  303. sa_tow_debug_arrow_1 setPosASL AGLtoASL (_vehicle modelToWorldVisual _rearCorner);
  304. sa_tow_debug_arrow_2 setPosASL AGLtoASL (_vehicle modelToWorldVisual _rearCorner2);
  305. sa_tow_debug_arrow_3 setPosASL AGLtoASL (_vehicle modelToWorldVisual _frontCorner);
  306. sa_tow_debug_arrow_4 setPosASL AGLtoASL (_vehicle modelToWorldVisual _frontCorner2);
  307. };
  308.  
  309. [_rearCorner,_rearCorner2,_frontCorner,_frontCorner2];
  310. };
  311.  
  312. SA_Get_Hitch_Points = {
  313. params ["_vehicle"];
  314. private ["_cornerPoints","_rearCorner","_rearCorner2","_frontCorner","_frontCorner2","_rearHitchPoint"];
  315. private ["_frontHitchPoint","_sideLeftPoint","_sideRightPoint"];
  316. _cornerPoints = [_vehicle] call SA_Get_Corner_Points;
  317. _rearCorner = _cornerPoints select 0;
  318. _rearCorner2 = _cornerPoints select 1;
  319. _frontCorner = _cornerPoints select 2;
  320. _frontCorner2 = _cornerPoints select 3;
  321. _rearHitchPoint = ((_rearCorner vectorDiff _rearCorner2) vectorMultiply 0.5) vectorAdd _rearCorner2;
  322. _frontHitchPoint = ((_frontCorner vectorDiff _frontCorner2) vectorMultiply 0.5) vectorAdd _frontCorner2;
  323. //_sideLeftPoint = ((_frontCorner vectorDiff _rearCorner) vectorMultiply 0.5) vectorAdd _frontCorner;
  324. //_sideRightPoint = ((_frontCorner2 vectorDiff _rearCorner2) vectorMultiply 0.5) vectorAdd _frontCorner2;
  325. [_frontHitchPoint,_rearHitchPoint];
  326. };
  327.  
  328. SA_Attach_Tow_Ropes = {
  329. params ["_cargo","_player"];
  330. _vehicle = _player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
  331. if(!isNull _vehicle) then {
  332. if(local _vehicle) then {
  333. private ["_towRopes","_vehicleHitch","_cargoHitch","_objDistance","_ropeLength"];
  334. _towRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
  335. if(count _towRopes == 1) then {
  336.  
  337. /*
  338. private ["_cargoHitchPoints","_distanceToFrontHitch","_distanceToRearHitch","_isRearCargoHitch"];
  339. _cargoHitchPoints = [_cargo] call SA_Get_Hitch_Points;
  340. _distanceToFrontHitch = player distance (_cargo modelToWorld (_cargoHitchPoints select 0));
  341. _distanceToRearHitch = player distance (_cargo modelToWorld (_cargoHitchPoints select 1));
  342. if( _distanceToFrontHitch < _distanceToRearHitch ) then {
  343. _cargoHitch = _cargoHitchPoints select 0;
  344. _isRearCargoHitch = false;
  345. } else {
  346. _cargoHitch = _cargoHitchPoints select 1;
  347. _isRearCargoHitch = true;
  348. };
  349. */
  350.  
  351. _cargoHitch = ([_cargo] call SA_Get_Hitch_Points) select 0;
  352.  
  353. _vehicleHitch = ([_vehicle] call SA_Get_Hitch_Points) select 1;
  354. _ropeLength = (ropeLength (_towRopes select 0));
  355. _objDistance = ((_vehicle modelToWorld _vehicleHitch) distance (_cargo modelToWorld _cargoHitch));
  356. if( _objDistance > _ropeLength ) then {
  357. [["The tow ropes are too short. Move vehicle closer.", false],"SA_Hint",_player] call SA_RemoteExec;
  358. } else {
  359. [_vehicle,_player] call SA_Drop_Tow_Ropes;
  360. _helper = "Land_Can_V2_F" createVehicle position _cargo;
  361. _helper attachTo [_cargo, _cargoHitch];
  362. _helper setVariable ["SA_Cargo",_cargo,true];
  363. hideObject _helper;
  364. [[_helper],"SA_Hide_Object_Global"] call SA_RemoteExecServer;
  365. [_helper, [0,0,0], [0,0,-1]] ropeAttachTo (_towRopes select 0);
  366. [_vehicle,_vehicleHitch,_cargo,_cargoHitch,_ropeLength] spawn SA_Simulate_Towing;
  367. };
  368. };
  369. } else {
  370. [_this,"SA_Attach_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
  371. };
  372. };
  373. };
  374.  
  375. SA_Take_Tow_Ropes = {
  376. params ["_vehicle","_player"];
  377. if(local _vehicle) then {
  378. diag_log format ["Take Tow Ropes Called %1", _this];
  379. private ["_existingTowRopes","_hitchPoint","_rope"];
  380. _existingTowRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
  381. if(count _existingTowRopes == 0) then {
  382. _hitchPoint = [_vehicle] call SA_Get_Hitch_Points select 1;
  383. _rope = ropeCreate [_vehicle, _hitchPoint, 10];
  384. _vehicle setVariable ["SA_Tow_Ropes",[_rope],true];
  385. _this call SA_Pickup_Tow_Ropes;
  386. };
  387. } else {
  388. [_this,"SA_Take_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
  389. };
  390. };
  391.  
  392. SA_Pickup_Tow_Ropes = {
  393. params ["_vehicle","_player"];
  394. if(local _vehicle) then {
  395. private ["_attachedObj","_helper"];
  396. {
  397. _attachedObj = _x;
  398. {
  399. _attachedObj ropeDetach _x;
  400. } forEach (_vehicle getVariable ["SA_Tow_Ropes",[]]);
  401. deleteVehicle _attachedObj;
  402. } forEach ropeAttachedObjects _vehicle;
  403. _helper = "Land_Can_V2_F" createVehicle position _player;
  404. {
  405. [_helper, [0, 0, 0], [0,0,-1]] ropeAttachTo _x;
  406. _helper attachTo [_player, [-0.1, 0.1, 0.15], "Pelvis"];
  407. } forEach (_vehicle getVariable ["SA_Tow_Ropes",[]]);
  408. hideObject _helper;
  409. [[_helper],"SA_Hide_Object_Global"] call SA_RemoteExecServer;
  410. _player setVariable ["SA_Tow_Ropes_Vehicle", _vehicle,true];
  411. _player setVariable ["SA_Tow_Ropes_Pick_Up_Helper", _helper,true];
  412. } else {
  413. [_this,"SA_Pickup_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
  414. };
  415. };
  416.  
  417. SA_Drop_Tow_Ropes = {
  418. params ["_vehicle","_player"];
  419. if(local _vehicle) then {
  420. private ["_helper"];
  421. _helper = (_player getVariable ["SA_Tow_Ropes_Pick_Up_Helper", objNull]);
  422. if(!isNull _helper) then {
  423. {
  424. _helper ropeDetach _x;
  425. } forEach (_vehicle getVariable ["SA_Tow_Ropes",[]]);
  426. detach _helper;
  427. deleteVehicle _helper;
  428. };
  429. _player setVariable ["SA_Tow_Ropes_Vehicle", nil,true];
  430. _player setVariable ["SA_Tow_Ropes_Pick_Up_Helper", nil,true];
  431. } else {
  432. [_this,"SA_Drop_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
  433. };
  434. };
  435. diag_log "Towing script 50% done...";
  436. SA_Put_Away_Tow_Ropes = {
  437. params ["_vehicle","_player"];
  438. if(local _vehicle) then {
  439. private ["_existingTowRopes","_hitchPoint","_rope"];
  440. _existingTowRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
  441. if(count _existingTowRopes > 0) then {
  442. _this call SA_Pickup_Tow_Ropes;
  443. _this call SA_Drop_Tow_Ropes;
  444. {
  445. ropeDestroy _x;
  446. } forEach _existingTowRopes;
  447. _vehicle setVariable ["SA_Tow_Ropes",nil,true];
  448. };
  449. } else {
  450. [_this,"SA_Put_Away_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
  451. };
  452. };
  453.  
  454. SA_Attach_Tow_Ropes_Action = {
  455. private ["_vehicle","_cargo","_canBeTowed"];
  456. _cargo = cursorTarget;
  457. _vehicle = player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
  458. if([_vehicle,_cargo] call SA_Can_Attach_Tow_Ropes) then {
  459.  
  460. _canBeTowed = true;
  461.  
  462. if!(missionNamespace getVariable ["SA_TOW_LOCKED_VEHICLES_ENABLED",false]) then {
  463. if( locked _cargo > 1 ) then {
  464. ["Cannot attach tow ropes to locked vehicle",false] call SA_Hint;
  465. _canBeTowed = false;
  466. };
  467. };
  468.  
  469. if!(missionNamespace getVariable ["SA_TOW_IN_EXILE_SAFEZONE_ENABLED",false]) then {
  470. if(!isNil "ExilePlayerInSafezone") then {
  471. if( ExilePlayerInSafezone ) then {
  472. ["Cannot attach tow ropes in safe zone",false] call SA_Hint;
  473. _canBeTowed = false;
  474. };
  475. };
  476. };
  477.  
  478. if(_canBeTowed) then {
  479. [_cargo,player] call SA_Attach_Tow_Ropes;
  480. };
  481.  
  482. };
  483. };
  484.  
  485. SA_Attach_Tow_Ropes_Action_Check = {
  486. private ["_vehicle","_cargo"];
  487. _vehicle = player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
  488. _cargo = cursorTarget;
  489. [_vehicle,_cargo] call SA_Can_Attach_Tow_Ropes;
  490. };
  491.  
  492. SA_Can_Attach_Tow_Ropes = {
  493. params ["_vehicle","_cargo"];
  494. if(!isNull _vehicle && !isNull _cargo) then {
  495. [_vehicle,_cargo] call SA_Is_Supported_Cargo && vehicle player == player && player distance _cargo < 10 && _vehicle != _cargo;
  496. } else {
  497. false;
  498. };
  499. };
  500.  
  501. SA_Take_Tow_Ropes_Action = {
  502. private ["_vehicle","_canTakeTowRopes"];
  503. _vehicle = cursorTarget;
  504. if([_vehicle] call SA_Can_Take_Tow_Ropes) then {
  505.  
  506. _canTakeTowRopes = true;
  507.  
  508. if!(missionNamespace getVariable ["SA_TOW_LOCKED_VEHICLES_ENABLED",false]) then {
  509. if( locked _vehicle > 1 ) then {
  510. ["Cannot take tow ropes from locked vehicle",false] call SA_Hint;
  511. _canTakeTowRopes = false;
  512. };
  513. };
  514.  
  515. if!(missionNamespace getVariable ["SA_TOW_IN_EXILE_SAFEZONE_ENABLED",false]) then {
  516. if(!isNil "ExilePlayerInSafezone") then {
  517. if( ExilePlayerInSafezone ) then {
  518. ["Cannot take tow ropes in safe zone",false] call SA_Hint;
  519. _canTakeTowRopes = false;
  520. };
  521. };
  522. };
  523.  
  524. if(_canTakeTowRopes) then {
  525. [_vehicle,player] call SA_Take_Tow_Ropes;
  526. };
  527.  
  528. };
  529. };
  530.  
  531. SA_Take_Tow_Ropes_Action_Check = {
  532. [cursorTarget] call SA_Can_Take_Tow_Ropes;
  533. };
  534.  
  535. SA_Can_Take_Tow_Ropes = {
  536. params ["_vehicle"];
  537. if([_vehicle] call SA_Is_Supported_Vehicle) then {
  538. private ["_existingVehicle","_existingTowRopes"];
  539. _existingTowRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
  540. _existingVehicle = player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
  541. vehicle player == player && player distance _vehicle < 10 && (count _existingTowRopes) == 0 && isNull _existingVehicle;
  542. } else {
  543. false;
  544. };
  545. };
  546.  
  547. SA_Put_Away_Tow_Ropes_Action = {
  548. private ["_vehicle","_canPutAwayTowRopes"];
  549. _vehicle = cursorTarget;
  550. if([_vehicle] call SA_Can_Put_Away_Tow_Ropes) then {
  551.  
  552. _canPutAwayTowRopes = true;
  553.  
  554. if!(missionNamespace getVariable ["SA_TOW_LOCKED_VEHICLES_ENABLED",false]) then {
  555. if( locked _vehicle > 1 ) then {
  556. ["Cannot put away tow ropes in locked vehicle",false] call SA_Hint;
  557. _canPutAwayTowRopes = false;
  558. };
  559. };
  560.  
  561. if!(missionNamespace getVariable ["SA_TOW_IN_EXILE_SAFEZONE_ENABLED",false]) then {
  562. if(!isNil "ExilePlayerInSafezone") then {
  563. if( ExilePlayerInSafezone ) then {
  564. ["Cannot put away tow ropes in safe zone",false] call SA_Hint;
  565. _canPutAwayTowRopes = false;
  566. };
  567. };
  568. };
  569.  
  570. if(_canPutAwayTowRopes) then {
  571. [_vehicle,player] call SA_Put_Away_Tow_Ropes;
  572. };
  573.  
  574. };
  575. };
  576.  
  577. SA_Put_Away_Tow_Ropes_Action_Check = {
  578. [cursorTarget] call SA_Can_Put_Away_Tow_Ropes;
  579. };
  580.  
  581. SA_Can_Put_Away_Tow_Ropes = {
  582. params ["_vehicle"];
  583. private ["_existingTowRopes"];
  584. if([_vehicle] call SA_Is_Supported_Vehicle) then {
  585. _existingTowRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
  586. vehicle player == player && player distance _vehicle < 10 && (count _existingTowRopes) > 0;
  587. } else {
  588. false;
  589. };
  590. };
  591.  
  592.  
  593. SA_Drop_Tow_Ropes_Action = {
  594. private ["_vehicle"];
  595. _vehicle = player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
  596. if([] call SA_Can_Drop_Tow_Ropes) then {
  597. [_vehicle, player] call SA_Drop_Tow_Ropes;
  598. };
  599. };
  600.  
  601. SA_Drop_Tow_Ropes_Action_Check = {
  602. [] call SA_Can_Drop_Tow_Ropes;
  603. };
  604.  
  605. SA_Can_Drop_Tow_Ropes = {
  606. !isNull (player getVariable ["SA_Tow_Ropes_Vehicle", objNull]) && vehicle player == player;
  607. };
  608.  
  609.  
  610.  
  611. SA_Pickup_Tow_Ropes_Action = {
  612. private ["_nearbyTowVehicles","_canPickupTowRopes","_vehicle"];
  613. _nearbyTowVehicles = missionNamespace getVariable ["SA_Nearby_Tow_Vehicles",[]];
  614. if([] call SA_Can_Pickup_Tow_Ropes) then {
  615.  
  616. _vehicle = _nearbyTowVehicles select 0;
  617. _canPickupTowRopes = true;
  618.  
  619. if!(missionNamespace getVariable ["SA_TOW_LOCKED_VEHICLES_ENABLED",false]) then {
  620. if( locked _vehicle > 1 ) then {
  621. ["Cannot pick up tow ropes from locked vehicle",false] call SA_Hint;
  622. _canPickupTowRopes = false;
  623. };
  624. };
  625.  
  626. if!(missionNamespace getVariable ["SA_TOW_IN_EXILE_SAFEZONE_ENABLED",false]) then {
  627. if(!isNil "ExilePlayerInSafezone") then {
  628. if( ExilePlayerInSafezone ) then {
  629. ["Cannot pick up tow ropes in safe zone",false] call SA_Hint;
  630. _canPickupTowRopes = false;
  631. };
  632. };
  633. };
  634.  
  635. if(_canPickupTowRopes) then {
  636. [_nearbyTowVehicles select 0, player] call SA_Pickup_Tow_Ropes;
  637. };
  638.  
  639. };
  640. };
  641.  
  642. SA_Pickup_Tow_Ropes_Action_Check = {
  643. [] call SA_Can_Pickup_Tow_Ropes;
  644. };
  645.  
  646. SA_Can_Pickup_Tow_Ropes = {
  647. isNull (player getVariable ["SA_Tow_Ropes_Vehicle", objNull]) && count (missionNamespace getVariable ["SA_Nearby_Tow_Vehicles",[]]) > 0 && vehicle player == player;
  648. };
  649.  
  650. SA_TOW_SUPPORTED_VEHICLES = [
  651. "Tank", "Car", "Ship"
  652. ];
  653.  
  654. SA_Is_Supported_Vehicle = {
  655. params ["_vehicle","_isSupported"];
  656. _isSupported = false;
  657. if(not isNull _vehicle) then {
  658. {
  659. if(_vehicle isKindOf _x) then {
  660. _isSupported = true;
  661. };
  662. } forEach (missionNamespace getVariable ["SA_TOW_SUPPORTED_VEHICLES_OVERRIDE",SA_TOW_SUPPORTED_VEHICLES]);
  663. };
  664. _isSupported;
  665. };
  666.  
  667. SA_TOW_RULES = [
  668. ["Tank","CAN_TOW","Tank"],
  669. ["Tank","CAN_TOW","Car"],
  670. ["Tank","CAN_TOW","Ship"],
  671. ["Tank","CAN_TOW","Air"],
  672. ["Car","CAN_TOW","Tank"],
  673. ["Car","CAN_TOW","Car"],
  674. ["Car","CAN_TOW","Ship"],
  675. ["Car","CAN_TOW","Air"],
  676. ["Ship","CAN_TOW","Ship"]
  677. ];
  678.  
  679. SA_Is_Supported_Cargo = {
  680. params ["_vehicle","_cargo"];
  681. private ["_canTow"];
  682. _canTow = false;
  683. if(not isNull _vehicle && not isNull _cargo) then {
  684. {
  685. if(_vehicle isKindOf (_x select 0)) then {
  686. if(_cargo isKindOf (_x select 2)) then {
  687. if( (toUpper (_x select 1)) == "CAN_TOW" ) then {
  688. _canTow = true;
  689. } else {
  690. _canTow = false;
  691. };
  692. };
  693. };
  694. } forEach (missionNamespace getVariable ["SA_TOW_RULES_OVERRIDE",SA_TOW_RULES]);
  695. };
  696. _canTow;
  697. };
  698.  
  699. SA_Hint = {
  700. params ["_msg",["_isSuccess",true]];
  701. if(!isNil "ExileClient_gui_notification_event_addNotification") then {
  702. if(_isSuccess) then {
  703. ["Success", [_msg]] call ExileClient_gui_notification_event_addNotification;
  704. } else {
  705. ["Whoops", [_msg]] call ExileClient_gui_notification_event_addNotification;
  706. };
  707. } else {
  708. hint _msg;
  709. };
  710. };
  711.  
  712. SA_Hide_Object_Global = {
  713. params ["_obj"];
  714. if( _obj isKindOf "Land_Can_V2_F" ) then {
  715. hideObjectGlobal _obj;
  716. };
  717. };
  718.  
  719. SA_Set_Owner = {
  720. params ["_obj","_client"];
  721. _obj setOwner _client;
  722. };
  723.  
  724. SA_Add_Player_Tow_Actions = {
  725.  
  726. player addAction ["Deploy Tow Ropes", {
  727. [] call SA_Take_Tow_Ropes_Action;
  728. }, nil, 0, false, true, "", "call SA_Take_Tow_Ropes_Action_Check"];
  729.  
  730. player addAction ["Put Away Tow Ropes", {
  731. [] call SA_Put_Away_Tow_Ropes_Action;
  732. }, nil, 0, false, true, "", "call SA_Put_Away_Tow_Ropes_Action_Check"];
  733.  
  734. player addAction ["Attach To Tow Ropes", {
  735. [] call SA_Attach_Tow_Ropes_Action;
  736. }, nil, 0, false, true, "", "call SA_Attach_Tow_Ropes_Action_Check"];
  737.  
  738. player addAction ["Drop Tow Ropes", {
  739. [] call SA_Drop_Tow_Ropes_Action;
  740. }, nil, 0, false, true, "", "call SA_Drop_Tow_Ropes_Action_Check"];
  741.  
  742. player addAction ["Pickup Tow Ropes", {
  743. [] call SA_Pickup_Tow_Ropes_Action;
  744. }, nil, 0, false, true, "", "call SA_Pickup_Tow_Ropes_Action_Check"];
  745.  
  746. player addEventHandler ["Respawn", {
  747. player setVariable ["SA_Tow_Actions_Loaded",false];
  748. }];
  749.  
  750. };
  751.  
  752. SA_Find_Nearby_Tow_Vehicles = {
  753. private ["_nearVehicles","_nearVehiclesWithTowRopes","_vehicle","_ends","_end1","_end2"];
  754. _nearVehicles = [];
  755. {
  756. _nearVehicles append (position player nearObjects [_x, 30]);
  757. } forEach (missionNamespace getVariable ["SA_TOW_SUPPORTED_VEHICLES_OVERRIDE",SA_TOW_SUPPORTED_VEHICLES]);
  758. _nearVehiclesWithTowRopes = [];
  759. {
  760. _vehicle = _x;
  761. {
  762. _ends = ropeEndPosition _x;
  763. if(count _ends == 2) then {
  764. _end1 = _ends select 0;
  765. _end2 = _ends select 1;
  766. if(((position player) distance _end1) < 5 || ((position player) distance _end2) < 5 ) then {
  767. _nearVehiclesWithTowRopes pushBack _vehicle;
  768. }
  769. };
  770. } forEach (_vehicle getVariable ["SA_Tow_Ropes",[]]);
  771. } forEach _nearVehicles;
  772. _nearVehiclesWithTowRopes;
  773. };
  774.  
  775. if(!isDedicated) then {
  776. [] spawn {
  777. while {true} do {
  778. if(!isNull player && isPlayer player) then {
  779. if!( player getVariable ["SA_Tow_Actions_Loaded",false] ) then {
  780. [] call SA_Add_Player_Tow_Actions;
  781. player setVariable ["SA_Tow_Actions_Loaded",true];
  782. };
  783. };
  784. missionNamespace setVariable ["SA_Nearby_Tow_Vehicles", (call SA_Find_Nearby_Tow_Vehicles)];
  785. sleep 2;
  786. };
  787. };
  788. };
  789.  
  790. SA_RemoteExec = {
  791. params ["_params","_functionName","_target",["_isCall",false]];
  792. if(!isNil "ExileClient_system_network_send") then {
  793. ["AdvancedTowingRemoteExecClient",[_params,_functionName,_target,_isCall]] call ExileClient_system_network_send;
  794. } else {
  795. if(_isCall) then {
  796. _params remoteExecCall [_functionName, _target];
  797. } else {
  798. _params remoteExec [_functionName, _target];
  799. };
  800. };
  801. };
  802.  
  803. SA_RemoteExecServer = {
  804. params ["_params","_functionName",["_isCall",false]];
  805. if(!isNil "ExileClient_system_network_send") then {
  806. ["AdvancedTowingRemoteExecServer",[_params,_functionName,_isCall]] call ExileClient_system_network_send;
  807. } else {
  808. if(_isCall) then {
  809. _params remoteExecCall [_functionName, 2];
  810. } else {
  811. _params remoteExec [_functionName, 2];
  812. };
  813. };
  814. };
  815.  
  816. if(isServer) then {
  817.  
  818. // Adds support for exile network calls (Only used when running exile) //
  819.  
  820. SA_SUPPORTED_REMOTEEXECSERVER_FUNCTIONS = ["SA_Set_Owner","SA_Hide_Object_Global"];
  821.  
  822. ExileServer_AdvancedTowing_network_AdvancedTowingRemoteExecServer = {
  823. params ["_sessionId", "_messageParameters",["_isCall",false]];
  824. _messageParameters params ["_params","_functionName"];
  825. if(_functionName in SA_SUPPORTED_REMOTEEXECSERVER_FUNCTIONS) then {
  826. if(_isCall) then {
  827. _params call (missionNamespace getVariable [_functionName,{}]);
  828. } else {
  829. _params spawn (missionNamespace getVariable [_functionName,{}]);
  830. };
  831. };
  832. };
  833.  
  834. SA_SUPPORTED_REMOTEEXECCLIENT_FUNCTIONS = ["SA_Simulate_Towing","SA_Attach_Tow_Ropes","SA_Take_Tow_Ropes","SA_Put_Away_Tow_Ropes","SA_Pickup_Tow_Ropes","SA_Drop_Tow_Ropes","SA_Hint"];
  835.  
  836. ExileServer_AdvancedTowing_network_AdvancedTowingRemoteExecClient = {
  837. params ["_sessionId", "_messageParameters"];
  838. _messageParameters params ["_params","_functionName","_target",["_isCall",false]];
  839. if(_functionName in SA_SUPPORTED_REMOTEEXECCLIENT_FUNCTIONS) then {
  840. if(_isCall) then {
  841. _params remoteExecCall [_functionName, _target];
  842. } else {
  843. _params remoteExec [_functionName, _target];
  844. };
  845. };
  846. };
  847.  
  848. // Install Advanced Towing on all clients (plus JIP) //
  849.  
  850. publicVariable "SA_Advanced_Towing_Install";
  851. remoteExecCall ["SA_Advanced_Towing_Install", -2,true];
  852.  
  853. };
  854.  
  855. diag_log "Advanced Towing Loaded";
  856.  
  857. };
  858.  
  859. if(isServer) then {
  860. [] call SA_Advanced_Towing_Install;
  861. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement