SHARE
TWEET

Untitled

a guest Apr 25th, 2019 81 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. };
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top