Advertisement
skotracker

fn_advancedTowingInit

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