diff --git a/addons/AR_AdvancedRappelling/functions/fn_advancedRappellingInit.sqf b/addons/AR_AdvancedRappelling/functions/fn_advancedRappellingInit.sqf index 5e2c6cf..46545cb 100644 --- a/addons/AR_AdvancedRappelling/functions/fn_advancedRappellingInit.sqf +++ b/addons/AR_AdvancedRappelling/functions/fn_advancedRappellingInit.sqf @@ -26,6 +26,355 @@ AR_RAPPEL_POINT_CLASS_HEIGHT_OFFSET = [ ["All", [-0.05, -0.05, -0.05, -0.05, -0.05, -0.05]] ]; + +#define AR_FNC_CAMERA_DISTANCE (missionNamespace getVariable ["AR_3rd_Person_Camera_Distance",5]) +#define AR_FNC_CAMERA (missionNamespace getVariable ["AR_3rd_Person_Camera",objNull]) +#define AR_FNC_CAMERA_X_TOTAL (missionNamespace getVariable ["AR_3rd_Person_Camera_X_Move_Total",-90]) +#define AR_FNC_CAMERA_Y_TOTAL (missionNamespace getVariable ["AR_3rd_Person_Camera_Y_Move_Total",60]) +#define AR_FNC_CAMERA_Y_TOTAL_PRIOR (missionNamespace getVariable ["AR_3rd_Person_Camera_Y_Move_Total_Prior",AR_FNC_CAMERA_Y_TOTAL]) +#define AR_FNC_CAMERA_REL_POSITION [AR_FNC_CAMERA_DISTANCE * (cos AR_FNC_CAMERA_X_TOTAL) * (sin AR_FNC_CAMERA_Y_TOTAL), AR_FNC_CAMERA_DISTANCE * (sin AR_FNC_CAMERA_X_TOTAL) * (sin AR_FNC_CAMERA_Y_TOTAL), AR_FNC_CAMERA_DISTANCE * (cos AR_FNC_CAMERA_Y_TOTAL)] +#define AR_FNC_CAMERA_WORLD_POSITION ((camTarget AR_FNC_CAMERA) modelToWorld AR_FNC_CAMERA_REL_POSITION) + +AR_Enable_3rd_Person_Camera = { + _this spawn { + params ["_object"]; + private ["_lastPosition"]; + waitUntil {time > 0}; + showCinemaBorder false; + AR_3rd_Person_Camera = "camera" camCreate (_object modelToWorld [0,0,0]); + AR_3rd_Person_Camera camSetTarget _object; + AR_3rd_Person_Camera cameraEffect ["internal", "BACK"]; + [] call AR_Camera_Update_Position; + waitUntil {!isNull (findDisplay 46)}; + _mouseMoveEventHandler = (findDisplay 46) displayAddEventHandler ["MouseMoving", "_this call AR_Camera_Mouse_Move_Handler"]; + _mouseZoomEventHandler = (findDisplay 46) displayAddEventHandler ["MouseZChanged", "_this call AR_Camera_Mouse_Zoom_Handler"]; + _lastPosition = getPos _object; + _lastVectorDir = vectorDir _object; + while {!isNull AR_FNC_CAMERA && !isNull _object && alive _object} do { + if(_lastPosition distance _object > 0.01 || vectorMagnitude (_lastVectorDir vectorDiff (vectorDir _object)) > 0.01 ) then { + [] call AR_Camera_Update_Position; + _lastPosition = getPos _object; + }; + sleep 0.01; + }; + [] call AR_Disable_3rd_Person_Camera; + }; +}; + +AR_Disable_3rd_Person_Camera = { + if(!isNull AR_FNC_CAMERA) then { + AR_FNC_CAMERA cameraEffect ["Terminate", "Back"]; + camDestroy AR_FNC_CAMERA; + missionNamespace setVariable ["AR_3rd_Person_Camera_Distance",nil]; + missionNamespace setVariable ["AR_3rd_Person_Camera",nil]; + missionNamespace setVariable ["AR_3rd_Person_Camera_X_Move_Total",nil]; + missionNamespace setVariable ["AR_3rd_Person_Camera_Y_Move_Total",nil]; + missionNamespace setVariable ["AR_3rd_Person_Camera_Y_Move_Total_Prior",nil]; + } +}; + +AR_Camera_Mouse_Zoom_Handler = { + private ["_mouseZoom","_distance"]; + _mouseZoom = (_this select 1); + if(_mouseZoom > 0) then { + _mouseZoom = 1; + } else { + _mouseZoom = -1; + }; + _distance = AR_FNC_CAMERA_DISTANCE; + AR_3rd_Person_Camera_Distance = (_distance - _mouseZoom) max 3 min 30; + [] spawn AR_Camera_Update_Position; +}; + +AR_Camera_Mouse_Move_Handler = { + private ["_cam","_distance","_target"]; + AR_3rd_Person_Camera_X_Move_Total = AR_FNC_CAMERA_X_TOTAL + (-(_this select 1)*0.16); + AR_3rd_Person_Camera_Y_Move_Total = AR_FNC_CAMERA_Y_TOTAL + (-(_this select 2)*0.16); + AR_3rd_Person_Camera_Y_Move_Total = AR_FNC_CAMERA_Y_TOTAL max 20 min 160; + [] spawn AR_Camera_Update_Position; +}; + +AR_Camera_Update_Position = { + private ["_cam"]; + _cam = AR_FNC_CAMERA; + if(!isNil "_cam") then { + if(AR_FNC_CAMERA_WORLD_POSITION select 2 < 0) then { + AR_3rd_Person_Camera_Y_Move_Total = AR_FNC_CAMERA_Y_TOTAL min AR_FNC_CAMERA_Y_TOTAL_PRIOR; + }; + _cam camSetRelPos AR_FNC_CAMERA_REL_POSITION; + _cam camCommit 0.01; + AR_3rd_Person_Camera_Y_Move_Total_Prior = AR_FNC_CAMERA_Y_TOTAL; + }; +}; + +AR_Get_Unit_Anchor = { + params ["_unit"]; + _unit getVariable ["AR_Anchor_Attached_To_Unit",objNull]; +}; + +// Must be executed where unit's anchor is local (or unit if no anchor exists) +AR_Unit_Rope_Create = { + params ["_unit","_length"]; + private ["_unitAnchor","_rope","_ropeEndPositions"]; + _rope = objNull; + _unitAnchor = [_unit] call AR_Create_Or_Get_Unit_Anchor; + if(!isNull _unitAnchor) then { + if(!isNull attachedTo _unitAnchor) then { + detach _unitAnchor; + _rope = ropeCreate [_unitAnchor, [0,0,-1000], _length]; + [_rope,_unitAnchor, _unit] spawn { + params ["_rope","_unitAnchor","_unit"]; + _time = diag_tickTime; + waitUntil { + // Rope won't work if you immediately attach anchor to unit. + // need to wait for rope to be created first by checking rope ends + // or 1 second has passed. + _ropeEndPositions = ropeEndPosition _rope; + ((_ropeEndPositions select 0) distance2D (_ropeEndPositions select 1)) > 0.1 || (diag_tickTime - _time) > 1; + }; + _unitAnchor attachTo [_unit, [0,0,1] vectorAdd [0,0,1000]]; + }; + } else { + _rope = ropeCreate [_unitAnchor, [0,0,-1000], _length]; + }; + }; + _rope; +}; + +AR_Attach_Rope_To_Unit_Anchor = { + params ["_vehicle","_rope","_unitAnchor",["_extend",0]]; + if(local _vehicle) then { + if(_extend > 0) then { + ropeUnwind [_rope, 100, (ropeLength _rope) + _extend]; + }; + [_unitAnchor, [0,0,-1000], [0,0,-1]] ropeAttachTo _rope; + _unitAnchor setMass 80; + } else { + [_this,"AR_Attach_Rope_To_Unit_Anchor",_vehicle] call AR_RemoteExec; + }; +}; + + +AR_Unit_Leave_Rope_Chain = { + params ["_unit"]; + private ["_rope","_vehicle","_cargo","_cargoAnchor"]; + private ["_cargoUnit","_cargoRope"]; + _unitAnchor = [_unit] call AR_Get_Unit_Anchor; + if(!local _unitAnchor) exitWith { + [_this,"AR_Unit_Leave_Rope_Chain",_unitAnchor] call AR_RemoteExec; + }; + _rope = _unit getVariable ["AR_Rope_Attached_To_Unit",objNull]; + _vehicle = ropeAttachedTo _unitAnchor; + _cargo = ropeAttachedObjects _unitAnchor; + deleteVehicle _unitAnchor; + _unit setVariable ["AR_Rope_Attached_To_Unit",nil,true]; + _unit setVariable ["AR_Anchor_Attached_To_Unit",nil,true]; + if(player == _unit) then { + [] call AR_Disable_3rd_Person_Camera; + }; + if(count _cargo > 0) then { + _cargoAnchor = _cargo select 0; + _cargoUnit = _cargoAnchor getVariable ["AR_Anchor_Attached_To_Unit",objNull]; + _cargoRope = _cargoUnit getVariable ["AR_Rope_Attached_To_Unit",objNull]; + [_cargoUnit, _rope, _vehicle, ropeLength _cargoRope] call AR_Attach_Rope_To_Unit; + }; +}; + +AR_Detach_Rope_From_Unit_Anchor = { + params ["_rope","_unitAnchor"]; + if(local _unitAnchor) then { + _unitAnchor ropeDetach _rope; + } else { + [_this,"AR_Detach_Rope_From_Unit_Anchor",_unitAnchor] call AR_RemoteExec; + }; +}; + +AR_Detach_Rope_From_Unit = { + params ["_unit"]; + private ["_unitAnchor","_rope","_cargo"]; + if(!local _unit) exitWith { + [_this,"AR_Detach_Rope_From_Unit",_unit] call AR_RemoteExec; + }; + _unitAnchor = [_unit] call AR_Get_Unit_Anchor; + _rope = _unit getVariable ["AR_Rope_Attached_To_Unit",objNull]; + if(!isNull _unitAnchor && !isNull _rope) then { + _cargo = ropeAttachedObjects _unitAnchor; + if(count _cargo > 0) then { + [_rope,_unitAnchor] call AR_Detach_Rope_From_Unit_Anchor; + _unit setVariable ["AR_Rope_Attached_To_Unit",nil,true]; + } else { + deleteVehicle _unitAnchor; + _unit setVariable ["AR_Rope_Attached_To_Unit",nil,true]; + _unit setVariable ["AR_Anchor_Attached_To_Unit",nil,true]; + }; + if(player == _unit) then { + [] call AR_Disable_3rd_Person_Camera; + }; + }; +}; + +AR_Simulate_Unit_Rope_Attachment = { + params ["_unit"]; + private ["_lastUnitSetPosTime","_lastUnitPosition","_currentUnitPosition"]; + private ["_unitAnchor","_allRopes","_vehicleRope"]; + private ["_unitInAir","_ropeEnds","_ropeLength"]; + if(!local _unit) exitWith { + [_this,"AR_Simulate_Unit_Rope_Attachment",_unit] call AR_RemoteExec; + }; + if(_unit getVariable ["AR_Unit_Rope_Simulation_Running",false]) exitWith {}; + _unit setVariable ["AR_Unit_Rope_Simulation_Running",true]; + _lastUnitSetPosTime = -1; + _lastUnitPosition = getPosASL _unit; + while {true} do { + if(!local _unit) exitWith { + _unit allowDamage true; + _unit setVariable ["AR_Unit_Rope_Simulation_Running",false]; + [_this,"AR_Simulate_Unit_Rope_Attachment",_unit] call AR_RemoteExec; + }; + if(!alive _unit) exitWith { + [_unit] call AR_Unit_Leave_Rope_Chain; + _unit setVariable ["AR_Unit_Rope_Simulation_Running",false]; + }; + _currentUnitPosition = getPosASL _unit; + _unitAnchor = [_unit] call AR_Get_Unit_Anchor; + if(isNull _unitAnchor) exitWith { + _unit allowDamage true; + _unit setVariable ["AR_Unit_Rope_Simulation_Running",false]; + }; + _allRopes = ropes _unitAnchor; + if(isNil "_allRopes") then { + _allRopes = []; + }; + _vehicleRope = _unit getVariable ["AR_Rope_Attached_To_Unit",objNull]; + if(!isNull _vehicleRope) then { + _allRopes pushBack _vehicleRope; + }; + if(count _allRopes == 0) exitWith { + _unit allowDamage true; + _unit setVariable ["AR_Unit_Rope_Simulation_Running",false]; + }; + _unitInAir = _unit getVariable ["AR_Rope_Unit_In_Air",false]; + if(!_unitInAir) then { + { + _rope = _x; + _ropeEnds = ropeEndPosition _rope; + _ropeLength = ropeLength _rope; + _unitEnd = (_ropeEnds select 0); + _vehicleEnd = (_ropeEnds select 1); + _vehicleEnd = ASLtoAGL _vehicleEnd; + _vehicleEnd set [2, (_vehicleEnd select 2) max 0]; + _vehicleEnd = AGLToASL _vehicleEnd; + if(_currentUnitPosition distance _unitEnd > _currentUnitPosition distance _vehicleEnd) then { + _unitEnd = (_ropeEnds select 1); + _vehicleEnd = (_ropeEnds select 0); + }; + if(_unitEnd distance _vehicleEnd > _ropeLength && ((getPos _unit) select 2) < 0.1) then { + if( _lastUnitPosition distance _currentUnitPosition > 0.01 && _currentUnitPosition distance _vehicleEnd > _lastUnitPosition distance _vehicleEnd ) then { + _unit allowDamage false; + _unit setPosASL _lastUnitPosition; + _lastUnitSetPosTime = diag_tickTime; + }; + }; + if(_rope == _vehicleRope) then { + _playerInAir = _unitEnd distance _vehicleEnd > _ropeLength + 2 && (ASLtoAGL _vehicleEnd select 2) > 5; + _playerInAir = _playerInAir || ( _unitEnd distance _vehicleEnd > _ropeLength && (ASLtoAGL _vehicleEnd select 2) > 5 && ((getPos _unit) select 2) > 1); + if(_playerInAir) then { + _unit allowDamage false; + _lastUnitSetPosTime = diag_tickTime; + detach _unitAnchor; + _unit attachTo [_unitAnchor, [0,0,-1] vectorAdd [0,0,-1000]]; + _unit switchMove "HubSittingChairC_idle1"; + if(player == _unit) then { + [_unit] spawn AR_Enable_3rd_Person_Camera; + }; + _unit setVariable ["AR_Rope_Unit_In_Air",true,true]; + sleep 2; + }; + }; + } forEach _allRopes; + } else { + _unitPos = getPos _unit; + if(_unitPos select 2 <= 0) then { + _unit allowDamage false; + _lastUnitSetPosTime = diag_tickTime; + detach _unit; + _unitAnchor attachTo [_unit, [0,0,1] vectorAdd [0,0,1000]]; + _unitStartASLIntersect = (getPosASL _unit) vectorAdd [0,0,2]; + _unitEndASLIntersect = [_unitStartASLIntersect select 0, _unitStartASLIntersect select 1, (_unitStartASLIntersect select 2) - 7]; + _surfaces = lineIntersectsSurfaces [_unitStartASLIntersect, _unitEndASLIntersect, _unit, objNull, true, 10]; + _intersectionASL = []; + { + scopeName "surfaceLoop"; + _intersectionObject = _x select 2; + _objectFileName = str _intersectionObject; + if((_objectFileName find " t_") == -1 && (_objectFileName find " b_") == -1) then { + _intersectionASL = _x select 0; + breakOut "surfaceLoop"; + }; + } forEach _surfaces; + if(count _intersectionASL != 0) then { + _unit setPosASL _intersectionASL; + systemChat str [_unit, 2, _intersectionASL]; + }; + _unit switchMove ""; + if(player == _unit) then { + [] spawn AR_Disable_3rd_Person_Camera; + }; + _unit setVariable ["AR_Rope_Unit_In_Air",false,true]; + _maxRopeExtend = 0; + { + _maxRopeExtend = _maxRopeExtend max (ropeLength _x); + } forEach (_allRopes - [_vehicleRope]); + _maxRopeExtend = _maxRopeExtend min 3; + ropeUnwind [_vehicleRope, 4, (ropeLength _vehicleRope) + _maxRopeExtend]; + sleep 2; + }; + }; + if(_lastUnitSetPosTime > 0 && diag_tickTime -_lastUnitSetPosTime > 5) then { + _unit allowDamage true; + _lastUnitSetPosTime = -1; + }; + _lastUnitPosition = getPosASL _unit; + sleep 0.01; + }; +}; + +AR_Create_Or_Get_Unit_Anchor = { + params ["_unit"]; + private ["_unitAnchor","_unitPosition","_unitAnchorPosition","_unitAnchorHeight"]; + _unitAnchor = [_unit] call AR_Get_Unit_Anchor; + if(isNull _unitAnchor) then { + _unitAnchorHeight = 1000; + _unitPosition = getPos _unit; + _unitAnchorPosition = _unitPosition vectorAdd [0,0,_unitAnchorHeight]; + _unitAnchor = createVehicle ["B_static_AA_F", _unitAnchorPosition, [], 0, "CAN_COLLIDE"]; + _unitAnchor allowDamage false; + _unitAnchor setCenterOfMass [0,0,-_unitAnchorHeight]; + _unitAnchor attachTo [_unit, [0,0,1] vectorAdd [0,0,_unitAnchorHeight]]; + _unitAnchor setVariable ["AR_Anchor_Attached_To_Unit",_unit,true]; + _unit setVariable ["AR_Anchor_Attached_To_Unit",_unitAnchor,true]; + }; + _unitAnchor; +}; + +AR_Attach_Rope_To_Unit = { + params ["_unit","_rope","_vehicle",["_extend",0]]; + private ["_unitAnchor","_vehicleAnchor"]; + if(!local _unit) exitWith { + [_this,"AR_Attach_Rope_To_Unit",_unit] call AR_RemoteExec; + }; + [_unit] call AR_Detach_Rope_From_Unit; + _unitAnchor = [_unit] call AR_Create_Or_Get_Unit_Anchor; + _vehicleAnchor = _vehicle getVariable ["AR_Anchor_Attached_To_Unit",objNull]; + if(!isNull _vehicleAnchor) then { + _vehicle = _vehicleAnchor; + }; + _unit setVariable ["AR_Rope_Attached_To_Unit",_rope,true]; + _unit setVariable ["AR_Rope_Unit_In_Air",false,true]; + [_vehicle,_rope,_unitAnchor,_extend] call AR_Attach_Rope_To_Unit_Anchor; + [_unit] spawn AR_Simulate_Unit_Rope_Attachment; +}; + AR_Has_Addon_Animations_Installed = { (count getText ( configFile / "CfgMovesBasic" / "ManActions" / "AR_01" )) > 0; }; @@ -361,37 +710,17 @@ AR_Client_Rappel_From_Heli = { _playerStartPosition set [0,(_playerStartPosition select 0) - ((((random 100)-50))/25)]; _player setPosWorld _playerStartPosition; - _anchor = "Land_Can_V2_F" createVehicle position _player; - _anchor allowDamage false; - hideObject _anchor; - [[_anchor],"AR_Hide_Object_Global"] call AR_RemoteExecServer; - _anchor attachTo [_heli,_rappelPoint]; + // Start rappelling + _ropeLength = 65; + _bottomRopeLength = _ropeLength - 2; + _topRopeLength = 2; + _topRope = ropeCreate [_heli, _rappelPoint, _topRopeLength]; + [_player, _topRope, _heli] call AR_Attach_Rope_To_Unit; + _bottomRope = [_player,_bottomRopeLength] call AR_Unit_Rope_Create; - _rappelDevice = "B_static_AA_F" createVehicle position _player; - _rappelDevice setPosWorld _playerStartPosition; - _rappelDevice allowDamage false; - hideObject _rappelDevice; - [[_rappelDevice],"AR_Hide_Object_Global"] call AR_RemoteExecServer; - - [[_player,_rappelDevice,_anchor],"AR_Play_Rappelling_Sounds_Global"] call AR_RemoteExecServer; - - _bottomRopeLength = 60; - _bottomRope = ropeCreate [_rappelDevice, [-0.15,0,0], _bottomRopeLength]; - _bottomRope allowDamage false; - _topRopeLength = 3; - _topRope = ropeCreate [_rappelDevice, [0,0.15,0], _anchor, [0, 0, 0], _topRopeLength]; - _topRope allowDamage false; + //[[_player,_rappelDevice,_anchor],"AR_Play_Rappelling_Sounds_Global"] call AR_RemoteExecServer; + //[_player] spawn AR_Enable_Rappelling_Animation_Client; - [_player] spawn AR_Enable_Rappelling_Animation_Client; - - _gravityAccelerationVec = [0,0,-9.8]; - _velocityVec = [0,0,0]; - _lastTime = diag_tickTime; - _lastPosition = AGLtoASL (_rappelDevice modelToWorldVisual [0,0,0]); - _lookDirFreedom = 50; - _dir = (random 360) + (_lookDirFreedom / 2); - _dirSpinFactor = (((random 10) - 5) / 5) max 0.1; - _ropeKeyDownHandler = -1; _ropeKeyUpHandler = -1; if(_player == player) then { @@ -446,7 +775,7 @@ AR_Client_Rappel_From_Heli = { }; }; - + _lastTime = diag_tickTime; while {true} do { @@ -456,124 +785,35 @@ AR_Client_Rappel_From_Heli = { if(_timeSinceLastUpdate > 1) then { _timeSinceLastUpdate = 0; }; - - _environmentWindVelocity = wind; - _playerWindVelocity = _velocityVec vectorMultiply -1; - _helicopterWindVelocity = (vectorUp _heli) vectorMultiply -30; - _totalWindVelocity = _environmentWindVelocity vectorAdd _playerWindVelocity vectorAdd _helicopterWindVelocity; - _totalWindForce = _totalWindVelocity vectorMultiply (9.8/53); - - _accelerationVec = _gravityAccelerationVec vectorAdd _totalWindForce; - _velocityVec = _velocityVec vectorAdd ( _accelerationVec vectorMultiply _timeSinceLastUpdate ); - _newPosition = _lastPosition vectorAdd ( _velocityVec vectorMultiply _timeSinceLastUpdate ); - - _heliPos = AGLtoASL (_heli modelToWorldVisual _rappelPoint); - - if(_newPosition distance _heliPos > _topRopeLength) then { - _newPosition = (_heliPos) vectorAdd (( vectorNormalized ( (_heliPos) vectorFromTo _newPosition )) vectorMultiply _topRopeLength); - _surfaceVector = ( vectorNormalized ( _newPosition vectorFromTo (_heliPos) )); - _velocityVec = _velocityVec vectorAdd (( _surfaceVector vectorMultiply (_velocityVec vectorDotProduct _surfaceVector)) vectorMultiply -1); - }; - - _rappelDevice setPosWorld (_lastPosition vectorAdd ((_newPosition vectorDiff _lastPosition) vectorMultiply 6)); - - _rappelDevice setVectorDir (vectorDir _player); - _player setPosWorld [_newPosition select 0, _newPosition select 1, (_newPosition select 2)-0.6]; - _player setVelocity [0,0,0]; - + // Handle rappelling down rope - if(_player getVariable ["AR_DECEND_PRESSED",false]) then { - _decendSpeedMetersPerSecond = 3.5; + if(_player getVariable ["AR_DECEND_PRESSED",false] && _player getVariable ["AR_Rope_Unit_In_Air",false]) then { + _decendSpeedMetersPerSecond = 3; if(_player getVariable ["AR_FAST_DECEND_PRESSED",false]) then { - _decendSpeedMetersPerSecond = 5; + _decendSpeedMetersPerSecond = 4.5; }; _decendSpeedMetersPerSecond = _decendSpeedMetersPerSecond + (_player getVariable ["AR_RANDOM_DECEND_SPEED_ADJUSTMENT",0]); - _bottomRopeLength = _bottomRopeLength - (_timeSinceLastUpdate * _decendSpeedMetersPerSecond); - _topRopeLength = _topRopeLength + (_timeSinceLastUpdate * _decendSpeedMetersPerSecond); + _bottomRopeLength = (_bottomRopeLength - (_timeSinceLastUpdate * _decendSpeedMetersPerSecond)) max 1; + _topRopeLength = (_topRopeLength + (_timeSinceLastUpdate * _decendSpeedMetersPerSecond)) min (_ropeLength-1); ropeUnwind [_topRope, _decendSpeedMetersPerSecond, _topRopeLength - 0.5]; ropeUnwind [_bottomRope, _decendSpeedMetersPerSecond, _bottomRopeLength]; }; - // Fix player direction - _dir = _dir + ((360/1000) * _dirSpinFactor); - if(isPlayer _player) then { - _currentDir = getDir _player; - _minDir = (_dir - (_lookDirFreedom/2)) mod 360; - _maxDir = (_dir + (_lookDirFreedom/2)) mod 360; - _minDegreesToMax = 0; - _minDegreesToMin = 0; - if( _currentDir > _maxDir ) then { - _minDegreesToMax = (_currentDir - _maxDir) min (360 - _currentDir + _maxDir); - }; - if( _currentDir < _maxDir ) then { - _minDegreesToMax = (_maxDir - _currentDir) min (360 - _maxDir + _currentDir); - }; - if( _currentDir > _minDir ) then { - _minDegreesToMin = (_currentDir - _minDir) min (360 - _currentDir + _minDir); - }; - if( _currentDir < _minDir ) then { - _minDegreesToMin = (_minDir - _currentDir) min (360 - _minDir + _currentDir); - }; - if( _minDegreesToMin > _lookDirFreedom || _minDegreesToMax > _lookDirFreedom ) then { - if( _minDegreesToMin < _minDegreesToMax ) then { - _player setDir _minDir; - } else { - _player setDir _maxDir; - }; - } else { - _player setDir (_currentDir + ((360/1000) * _dirSpinFactor)); - }; - } else { - _player setDir _dir; + if!(_player setVariable ["AR_Unit_Rope_Simulation_Running",false]) exitWith {}; + + if(_player getVariable ["AR_Detach_Rope",false]) exitWith { + [_player] call AR_Unit_Leave_Rope_Chain; }; - _lastPosition = _newPosition; - - if((getPos _player) select 2 < 1 || !alive _player || vehicle _player != _player || _bottomRopeLength <= 1 || _player getVariable ["AR_Detach_Rope",false] ) exitWith {}; - - sleep 0.01; - }; - - if(_bottomRopeLength > 1 && alive _player && vehicle _player == _player) then { - - _playerStartASLIntersect = getPosASL _player; - _playerEndASLIntersect = [_playerStartASLIntersect select 0, _playerStartASLIntersect select 1, (_playerStartASLIntersect select 2) - 5]; - _surfaces = lineIntersectsSurfaces [_playerStartASLIntersect, _playerEndASLIntersect, _player, objNull, true, 10]; - _intersectionASL = []; - { - scopeName "surfaceLoop"; - _intersectionObject = _x select 2; - _objectFileName = str _intersectionObject; - if((_objectFileName find " t_") == -1 && (_objectFileName find " b_") == -1) then { - _intersectionASL = _x select 0; - breakOut "surfaceLoop"; - }; - } forEach _surfaces; - - if(count _intersectionASL != 0) then { - _player allowDamage false; - _player setPosASL _intersectionASL; - }; - - if(_player getVariable ["AR_Detach_Rope",false]) then { - // Player detached from rope. Don't prevent damage - // if we didn't find a position on the ground - if(count _intersectionASL == 0) then { - _player allowDamage true; - }; - }; - - // Allow damage if you get out of a heli with no engine on - if(!isEngineOn _heli) then { - _player allowDamage true; + if( not (_player getVariable ["AR_Rope_Unit_In_Air",false]) && !isPlayer _player && (getPos _player) select 2 < 1 ) exitWith { + [_player] call AR_Unit_Leave_Rope_Chain; }; + sleep 0.3; }; ropeDestroy _topRope; ropeDestroy _bottomRope; - deleteVehicle _anchor; - deleteVehicle _rappelDevice; _player setVariable ["AR_Is_Rappelling",nil,true]; _player setVariable ["AR_Rappelling_Vehicle", nil, true]; @@ -587,10 +827,6 @@ AR_Client_Rappel_From_Heli = { (findDisplay 46) displayRemoveEventHandler ["KeyUp", _ropeKeyUpHandler]; }; - sleep 2; - - _player allowDamage true; - } else { [_this,"AR_Client_Rappel_From_Heli",_player] call AR_RemoteExec; };