Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define SA_Find_Surface_ASL_Under_Position(_object,_positionAGL,_returnSurfaceASL,_canFloat) \
- _objectASL = AGLToASL (_object modelToWorldVisual (getCenterOfMass _object)); \
- _surfaceIntersectStartASL = [_positionAGL select 0, _positionAGL select 1, (_objectASL select 2) + 1]; \
- _surfaceIntersectEndASL = [_positionAGL select 0, _positionAGL select 1, (_objectASL select 2) - 5]; \
- _surfaces = lineIntersectsSurfaces [_surfaceIntersectStartASL, _surfaceIntersectEndASL, _object, objNull, true, 5]; \
- _returnSurfaceASL = AGLToASL _positionAGL; \
- { \
- scopeName "surfaceLoop"; \
- if( isNull (_x select 2) ) then { \
- _returnSurfaceASL = _x select 0; \
- breakOut "surfaceLoop"; \
- } else { \
- if!((_x select 2) isKindOf "RopeSegment") then { \
- _objectFileName = str (_x select 2); \
- if((_objectFileName find " t_") == -1 && (_objectFileName find " b_") == -1) then { \
- _returnSurfaceASL = _x select 0; \
- breakOut "surfaceLoop"; \
- }; \
- }; \
- }; \
- } forEach _surfaces; \
- if(_canFloat && (_returnSurfaceASL select 2) < 0) then { \
- _returnSurfaceASL set [2,0]; \
- }; \
- #define SA_Find_Surface_ASL_Under_Model(_object,_modelOffset,_returnSurfaceASL,_canFloat) \
- SA_Find_Surface_ASL_Under_Position(_object, (_object modelToWorldVisual _modelOffset), _returnSurfaceASL,_canFloat);
- #define SA_Find_Surface_AGL_Under_Model(_object,_modelOffset,_returnSurfaceAGL,_canFloat) \
- SA_Find_Surface_ASL_Under_Model(_object,_modelOffset,_returnSurfaceAGL,_canFloat); \
- _returnSurfaceAGL = ASLtoAGL _returnSurfaceAGL;
- #define SA_Get_Cargo(_vehicle,_cargo) \
- if( count (ropeAttachedObjects _vehicle) == 0 ) then { \
- _cargo = objNull; \
- } else { \
- _cargo = ((ropeAttachedObjects _vehicle) select 0) getVariable ["SA_Cargo",objNull]; \
- };
- SA_Advanced_Towing_Install = {
- // Prevent advanced towing from installing twice
- if(!isNil "SA_TOW_INIT") exitWith {};
- SA_TOW_INIT = true;
- diag_log "Advanced Towing Loading...";
- SA_Simulate_Towing_Speed = {
- params ["_vehicle"];
- private ["_runSimulation","_currentCargo","_maxVehicleSpeed","_maxTowedVehicles","_vehicleMass"];
- _maxVehicleSpeed = getNumber (configFile >> "CfgVehicles" >> typeOf _vehicle >> "maxSpeed");
- _vehicleMass = 1000 max (getMass _vehicle);
- _maxTowedCargo = missionNamespace getVariable ["SA_MAX_TOWED_CARGO",2];
- _runSimulation = true;
- private ["_currentVehicle","_totalCargoMass","_totalCargoCount","_findNextCargo","_towRopes","_ropeLength"];
- private ["_ends","_endsDistance","_currentMaxSpeed","_newMaxSpeed"];
- while {_runSimulation} do {
- // Calculate total mass and count of cargo being towed (only takes into account
- // cargo that's actively being towed (e.g. there's no slack in the rope)
- _currentVehicle = _vehicle;
- _totalCargoMass = 0;
- _totalCargoCount = 0;
- _findNextCargo = true;
- while {_findNextCargo} do {
- _findNextCargo = false;
- SA_Get_Cargo(_currentVehicle,_currentCargo);
- if(!isNull _currentCargo) then {
- _towRopes = _currentVehicle getVariable ["SA_Tow_Ropes",[]];
- if(count _towRopes > 0) then {
- _ropeLength = ropeLength (_towRopes select 0);
- _ends = ropeEndPosition (_towRopes select 0);
- _endsDistance = (_ends select 0) distance (_ends select 1);
- if( _endsDistance >= _ropeLength - 2 ) then {
- _totalCargoMass = _totalCargoMass + (1000 max (getMass _currentCargo));
- _totalCargoCount = _totalCargoCount + 1;
- _currentVehicle = _currentCargo;
- _findNextCargo = true;
- };
- };
- };
- };
- _newMaxSpeed = _maxVehicleSpeed / (1 max ((_totalCargoMass / _vehicleMass) * 2));
- _newMaxSpeed = (_maxVehicleSpeed * 0.75) min _newMaxSpeed;
- // Prevent vehicle from moving if trying to move more cargo than pre-defined max
- if(_totalCargoCount > _maxTowedCargo) then {
- _newMaxSpeed = 0;
- };
- _currentMaxSpeed = _vehicle getVariable ["SA_Max_Tow_Speed",_maxVehicleSpeed];
- if(_currentMaxSpeed != _newMaxSpeed) then {
- _vehicle setVariable ["SA_Max_Tow_Speed",_newMaxSpeed];
- };
- sleep 0.1;
- };
- };
- SA_Simulate_Towing = {
- params ["_vehicle","_vehicleHitchModelPos","_cargo","_cargoHitchModelPos","_ropeLength"];
- private ["_lastCargoHitchPosition","_lastCargoVectorDir","_cargoLength","_maxDistanceToCargo","_lastMovedCargoPosition","_cargoHitchPoints"];
- private ["_vehicleHitchPosition","_cargoHitchPosition","_newCargoHitchPosition","_cargoVector","_movedCargoVector","_attachedObjects","_currentCargo"];
- private ["_newCargoDir","_lastCargoVectorDir","_newCargoPosition","_doExit","_cargoPosition","_vehiclePosition","_maxVehicleSpeed","_vehicleMass","_cargoMass","_cargoCanFloat"];
- private ["_cargoCorner1AGL","_cargoCorner1ASL","_cargoCorner2AGL","_cargoCorner2ASL","_cargoCorner3AGL","_cargoCorner3ASL","_cargoCorner4AGL","_cargoCorner4ASL","_surfaceNormal1","_surfaceNormal2","_surfaceNormal"];
- private ["_cargoCenterASL","_surfaceHeight","_surfaceHeight2","_maxSurfaceHeight"];
- _maxVehicleSpeed = getNumber (configFile >> "CfgVehicles" >> typeOf _vehicle >> "maxSpeed");
- _cargoCanFloat = if( getNumber (configFile >> "CfgVehicles" >> typeOf _cargo >> "canFloat") == 1 ) then { true } else { false };
- private ["_cargoCenterOfMassAGL","_cargoModelCenterGroundPosition"];
- SA_Find_Surface_AGL_Under_Model(_cargo,getCenterOfMass _cargo,_cargoCenterOfMassAGL,_cargoCanFloat);
- _cargoModelCenterGroundPosition = _cargo worldToModelVisual _cargoCenterOfMassAGL;
- _cargoModelCenterGroundPosition set [0,0];
- _cargoModelCenterGroundPosition set [1,0];
- _cargoModelCenterGroundPosition set [2, (_cargoModelCenterGroundPosition select 2) - 0.05]; // Adjust height so that it doesn't ride directly on ground
- // Calculate cargo model corner points
- private ["_cargoCornerPoints"];
- _cargoCornerPoints = [_cargo] call SA_Get_Corner_Points;
- _corner1 = _cargoCornerPoints select 0;
- _corner2 = _cargoCornerPoints select 1;
- _corner3 = _cargoCornerPoints select 2;
- _corner4 = _cargoCornerPoints select 3;
- // Try to set cargo owner if the towing client doesn't own the cargo
- if(local _vehicle && !local _cargo) then {
- [[_cargo, clientOwner],"SA_Set_Owner"] call SA_RemoteExecServer;
- };
- _vehicleHitchModelPos set [2,0];
- _cargoHitchModelPos set [2,0];
- _lastCargoHitchPosition = _cargo modelToWorld _cargoHitchModelPos;
- _lastCargoVectorDir = vectorDir _cargo;
- _lastMovedCargoPosition = getPos _cargo;
- _cargoHitchPoints = [_cargo] call SA_Get_Hitch_Points;
- _cargoLength = (_cargoHitchPoints select 0) distance (_cargoHitchPoints select 1);
- _vehicleMass = 1 max (getMass _vehicle);
- _cargoMass = getMass _cargo;
- if(_cargoMass == 0) then {
- _cargoMass = _vehicleMass;
- };
- _maxDistanceToCargo = _ropeLength;
- _doExit = false;
- // Start vehicle speed simulation
- [_vehicle] spawn SA_Simulate_Towing_Speed;
- while {!_doExit} do {
- _vehicleHitchPosition = _vehicle modelToWorld _vehicleHitchModelPos;
- _vehicleHitchPosition set [2,0];
- _cargoHitchPosition = _lastCargoHitchPosition;
- _cargoHitchPosition set [2,0];
- _cargoPosition = getPos _cargo;
- _vehiclePosition = getPos _vehicle;
- if(_vehicleHitchPosition distance _cargoHitchPosition > _maxDistanceToCargo) then {
- // Calculated simulated towing position + direction
- _newCargoHitchPosition = _vehicleHitchPosition vectorAdd ((_vehicleHitchPosition vectorFromTo _cargoHitchPosition) vectorMultiply _ropeLength);
- _cargoVector = _lastCargoVectorDir vectorMultiply _cargoLength;
- _movedCargoVector = _newCargoHitchPosition vectorDiff _lastCargoHitchPosition;
- _newCargoDir = vectorNormalized (_cargoVector vectorAdd _movedCargoVector);
- //if(_isRearCargoHitch) then {
- // _newCargoDir = _newCargoDir vectorMultiply -1;
- //};
- _lastCargoVectorDir = _newCargoDir;
- _newCargoPosition = _newCargoHitchPosition vectorAdd (_newCargoDir vectorMultiply -(vectorMagnitude (_cargoHitchModelPos)));
- SA_Find_Surface_ASL_Under_Position(_cargo,_newCargoPosition,_newCargoPosition,_cargoCanFloat);
- // Calculate surface normal (up) (more realistic than surfaceNormal function)
- SA_Find_Surface_ASL_Under_Model(_cargo,_corner1,_cargoCorner1ASL,_cargoCanFloat);
- SA_Find_Surface_ASL_Under_Model(_cargo,_corner2,_cargoCorner2ASL,_cargoCanFloat);
- SA_Find_Surface_ASL_Under_Model(_cargo,_corner3,_cargoCorner3ASL,_cargoCanFloat);
- SA_Find_Surface_ASL_Under_Model(_cargo,_corner4,_cargoCorner4ASL,_cargoCanFloat);
- _surfaceNormal1 = (_cargoCorner1ASL vectorFromTo _cargoCorner3ASL) vectorCrossProduct (_cargoCorner1ASL vectorFromTo _cargoCorner2ASL);
- _surfaceNormal2 = (_cargoCorner4ASL vectorFromTo _cargoCorner2ASL) vectorCrossProduct (_cargoCorner4ASL vectorFromTo _cargoCorner3ASL);
- _surfaceNormal = _surfaceNormal1 vectorAdd _surfaceNormal2;
- if(missionNamespace getVariable ["SA_TOW_DEBUG_ENABLED", false]) then {
- if(isNil "sa_tow_debug_arrow_1") then {
- sa_tow_debug_arrow_1 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
- sa_tow_debug_arrow_2 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
- sa_tow_debug_arrow_3 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
- sa_tow_debug_arrow_4 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
- };
- sa_tow_debug_arrow_1 setPosASL _cargoCorner1ASL;
- sa_tow_debug_arrow_1 setVectorUp _surfaceNormal;
- sa_tow_debug_arrow_2 setPosASL _cargoCorner2ASL;
- sa_tow_debug_arrow_2 setVectorUp _surfaceNormal;
- sa_tow_debug_arrow_3 setPosASL _cargoCorner3ASL;
- sa_tow_debug_arrow_3 setVectorUp _surfaceNormal;
- sa_tow_debug_arrow_4 setPosASL _cargoCorner4ASL;
- sa_tow_debug_arrow_4 setVectorUp _surfaceNormal;
- };
- // Calculate adjusted surface height based on surface normal (prevents vehicle from clipping into ground)
- _cargoCenterASL = AGLtoASL (_cargo modelToWorldVisual [0,0,0]);
- _cargoCenterASL set [2,0];
- _surfaceHeight = ((_cargoCorner1ASL vectorAdd ( _cargoCenterASL vectorMultiply -1)) vectorDotProduct _surfaceNormal1) / ([0,0,1] vectorDotProduct _surfaceNormal1);
- _surfaceHeight2 = ((_cargoCorner1ASL vectorAdd ( _cargoCenterASL vectorMultiply -1)) vectorDotProduct _surfaceNormal2) / ([0,0,1] vectorDotProduct _surfaceNormal2);
- _maxSurfaceHeight = (_newCargoPosition select 2) max _surfaceHeight max _surfaceHeight2;
- _newCargoPosition set [2, _maxSurfaceHeight ];
- _newCargoPosition = _newCargoPosition vectorAdd ( _cargoModelCenterGroundPosition vectorMultiply -1 );
- _cargo setVectorDir _newCargoDir;
- _cargo setVectorUp _surfaceNormal;
- _cargo setPosWorld _newCargoPosition;
- _lastCargoHitchPosition = _newCargoHitchPosition;
- _maxDistanceToCargo = _vehicleHitchPosition distance _newCargoHitchPosition;
- _lastMovedCargoPosition = _cargoPosition;
- _massAdjustedMaxSpeed = _vehicle getVariable ["SA_Max_Tow_Speed",_maxVehicleSpeed];
- if(speed _vehicle > (_massAdjustedMaxSpeed)+0.1) then {
- _vehicle setVelocity ((vectorNormalized (velocity _vehicle)) vectorMultiply (_massAdjustedMaxSpeed/3.6));
- };
- } else {
- if(_lastMovedCargoPosition distance _cargoPosition > 2) then {
- _lastCargoHitchPosition = _cargo modelToWorld _cargoHitchModelPos;
- _lastCargoVectorDir = vectorDir _cargo;
- };
- };
- // If vehicle isn't local to the client, switch client running towing simulation
- if(!local _vehicle) then {
- [_this,"SA_Simulate_Towing",_vehicle] call SA_RemoteExec;
- _doExit = true;
- };
- // If the vehicle isn't towing anything, stop the towing simulation
- SA_Get_Cargo(_vehicle,_currentCargo);
- if(isNull _currentCargo) then {
- _doExit = true;
- };
- sleep 0.01;
- };
- };
- SA_Get_Corner_Points = {
- params ["_vehicle"];
- private ["_centerOfMass","_bbr","_p1","_p2","_rearCorner","_rearCorner2","_frontCorner","_frontCorner2"];
- private ["_maxWidth","_widthOffset","_maxLength","_lengthOffset","_widthFactor","_lengthFactor"];
- // Correct width and length factor for air
- _widthFactor = 0.75;
- _lengthFactor = 0.75;
- if(_vehicle isKindOf "Air") then {
- _widthFactor = 0.3;
- };
- if(_vehicle isKindOf "Helicopter") then {
- _widthFactor = 0.2;
- _lengthFactor = 0.45;
- };
- _centerOfMass = getCenterOfMass _vehicle;
- _bbr = boundingBoxReal _vehicle;
- _p1 = _bbr select 0;
- _p2 = _bbr select 1;
- _maxWidth = abs ((_p2 select 0) - (_p1 select 0));
- _widthOffset = ((_maxWidth / 2) - abs ( _centerOfMass select 0 )) * _widthFactor;
- _maxLength = abs ((_p2 select 1) - (_p1 select 1));
- _lengthOffset = ((_maxLength / 2) - abs (_centerOfMass select 1 )) * _lengthFactor;
- _rearCorner = [(_centerOfMass select 0) + _widthOffset, (_centerOfMass select 1) - _lengthOffset, _centerOfMass select 2];
- _rearCorner2 = [(_centerOfMass select 0) - _widthOffset, (_centerOfMass select 1) - _lengthOffset, _centerOfMass select 2];
- _frontCorner = [(_centerOfMass select 0) + _widthOffset, (_centerOfMass select 1) + _lengthOffset, _centerOfMass select 2];
- _frontCorner2 = [(_centerOfMass select 0) - _widthOffset, (_centerOfMass select 1) + _lengthOffset, _centerOfMass select 2];
- if(missionNamespace getVariable ["SA_TOW_DEBUG_ENABLED", false]) then {
- if(isNil "sa_tow_debug_arrow_1") then {
- sa_tow_debug_arrow_1 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
- sa_tow_debug_arrow_2 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
- sa_tow_debug_arrow_3 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
- sa_tow_debug_arrow_4 = "Sign_Arrow_F" createVehicleLocal [0,0,0];
- };
- sa_tow_debug_arrow_1 setPosASL AGLtoASL (_vehicle modelToWorldVisual _rearCorner);
- sa_tow_debug_arrow_2 setPosASL AGLtoASL (_vehicle modelToWorldVisual _rearCorner2);
- sa_tow_debug_arrow_3 setPosASL AGLtoASL (_vehicle modelToWorldVisual _frontCorner);
- sa_tow_debug_arrow_4 setPosASL AGLtoASL (_vehicle modelToWorldVisual _frontCorner2);
- };
- [_rearCorner,_rearCorner2,_frontCorner,_frontCorner2];
- };
- SA_Get_Hitch_Points = {
- params ["_vehicle"];
- private ["_cornerPoints","_rearCorner","_rearCorner2","_frontCorner","_frontCorner2","_rearHitchPoint"];
- private ["_frontHitchPoint","_sideLeftPoint","_sideRightPoint"];
- _cornerPoints = [_vehicle] call SA_Get_Corner_Points;
- _rearCorner = _cornerPoints select 0;
- _rearCorner2 = _cornerPoints select 1;
- _frontCorner = _cornerPoints select 2;
- _frontCorner2 = _cornerPoints select 3;
- _rearHitchPoint = ((_rearCorner vectorDiff _rearCorner2) vectorMultiply 0.5) vectorAdd _rearCorner2;
- _frontHitchPoint = ((_frontCorner vectorDiff _frontCorner2) vectorMultiply 0.5) vectorAdd _frontCorner2;
- //_sideLeftPoint = ((_frontCorner vectorDiff _rearCorner) vectorMultiply 0.5) vectorAdd _frontCorner;
- //_sideRightPoint = ((_frontCorner2 vectorDiff _rearCorner2) vectorMultiply 0.5) vectorAdd _frontCorner2;
- [_frontHitchPoint,_rearHitchPoint];
- };
- SA_Attach_Tow_Ropes = {
- params ["_cargo","_player"];
- _vehicle = _player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
- if(!isNull _vehicle) then {
- if(local _vehicle) then {
- private ["_towRopes","_vehicleHitch","_cargoHitch","_objDistance","_ropeLength"];
- _towRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
- if(count _towRopes == 1) then {
- /*
- private ["_cargoHitchPoints","_distanceToFrontHitch","_distanceToRearHitch","_isRearCargoHitch"];
- _cargoHitchPoints = [_cargo] call SA_Get_Hitch_Points;
- _distanceToFrontHitch = player distance (_cargo modelToWorld (_cargoHitchPoints select 0));
- _distanceToRearHitch = player distance (_cargo modelToWorld (_cargoHitchPoints select 1));
- if( _distanceToFrontHitch < _distanceToRearHitch ) then {
- _cargoHitch = _cargoHitchPoints select 0;
- _isRearCargoHitch = false;
- } else {
- _cargoHitch = _cargoHitchPoints select 1;
- _isRearCargoHitch = true;
- };
- */
- _cargoHitch = ([_cargo] call SA_Get_Hitch_Points) select 0;
- _vehicleHitch = ([_vehicle] call SA_Get_Hitch_Points) select 1;
- _ropeLength = (ropeLength (_towRopes select 0));
- _objDistance = ((_vehicle modelToWorld _vehicleHitch) distance (_cargo modelToWorld _cargoHitch));
- if( _objDistance > _ropeLength ) then {
- [["The tow ropes are too short. Move vehicle closer.", false],"SA_Hint",_player] call SA_RemoteExec;
- } else {
- [_vehicle,_player] call SA_Drop_Tow_Ropes;
- _helper = "Land_Can_V2_F" createVehicle position _cargo;
- _helper attachTo [_cargo, _cargoHitch];
- _helper setVariable ["SA_Cargo",_cargo,true];
- hideObject _helper;
- [[_helper],"SA_Hide_Object_Global"] call SA_RemoteExecServer;
- [_helper, [0,0,0], [0,0,-1]] ropeAttachTo (_towRopes select 0);
- [_vehicle,_vehicleHitch,_cargo,_cargoHitch,_ropeLength] spawn SA_Simulate_Towing;
- };
- };
- } else {
- [_this,"SA_Attach_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
- };
- };
- };
- SA_Take_Tow_Ropes = {
- params ["_vehicle","_player"];
- if(local _vehicle) then {
- diag_log format ["Take Tow Ropes Called %1", _this];
- private ["_existingTowRopes","_hitchPoint","_rope"];
- _existingTowRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
- if(count _existingTowRopes == 0) then {
- _hitchPoint = [_vehicle] call SA_Get_Hitch_Points select 1;
- _rope = ropeCreate [_vehicle, _hitchPoint, 10];
- _vehicle setVariable ["SA_Tow_Ropes",[_rope],true];
- _this call SA_Pickup_Tow_Ropes;
- };
- } else {
- [_this,"SA_Take_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
- };
- };
- SA_Pickup_Tow_Ropes = {
- params ["_vehicle","_player"];
- if(local _vehicle) then {
- private ["_attachedObj","_helper"];
- {
- _attachedObj = _x;
- {
- _attachedObj ropeDetach _x;
- } forEach (_vehicle getVariable ["SA_Tow_Ropes",[]]);
- deleteVehicle _attachedObj;
- } forEach ropeAttachedObjects _vehicle;
- _helper = "Land_Can_V2_F" createVehicle position _player;
- {
- [_helper, [0, 0, 0], [0,0,-1]] ropeAttachTo _x;
- _helper attachTo [_player, [-0.1, 0.1, 0.15], "Pelvis"];
- } forEach (_vehicle getVariable ["SA_Tow_Ropes",[]]);
- hideObject _helper;
- [[_helper],"SA_Hide_Object_Global"] call SA_RemoteExecServer;
- _player setVariable ["SA_Tow_Ropes_Vehicle", _vehicle,true];
- _player setVariable ["SA_Tow_Ropes_Pick_Up_Helper", _helper,true];
- } else {
- [_this,"SA_Pickup_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
- };
- };
- SA_Drop_Tow_Ropes = {
- params ["_vehicle","_player"];
- if(local _vehicle) then {
- private ["_helper"];
- _helper = (_player getVariable ["SA_Tow_Ropes_Pick_Up_Helper", objNull]);
- if(!isNull _helper) then {
- {
- _helper ropeDetach _x;
- } forEach (_vehicle getVariable ["SA_Tow_Ropes",[]]);
- detach _helper;
- deleteVehicle _helper;
- };
- _player setVariable ["SA_Tow_Ropes_Vehicle", nil,true];
- _player setVariable ["SA_Tow_Ropes_Pick_Up_Helper", nil,true];
- } else {
- [_this,"SA_Drop_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
- };
- };
- SA_Put_Away_Tow_Ropes = {
- params ["_vehicle","_player"];
- if(local _vehicle) then {
- private ["_existingTowRopes","_hitchPoint","_rope"];
- _existingTowRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
- if(count _existingTowRopes > 0) then {
- _this call SA_Pickup_Tow_Ropes;
- _this call SA_Drop_Tow_Ropes;
- {
- ropeDestroy _x;
- } forEach _existingTowRopes;
- _vehicle setVariable ["SA_Tow_Ropes",nil,true];
- };
- } else {
- [_this,"SA_Put_Away_Tow_Ropes",_vehicle,true] call SA_RemoteExec;
- };
- };
- SA_Attach_Tow_Ropes_Action = {
- private ["_vehicle","_cargo","_canBeTowed"];
- _cargo = cursorTarget;
- _vehicle = player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
- if([_vehicle,_cargo] call SA_Can_Attach_Tow_Ropes) then {
- _canBeTowed = true;
- // Enabled towing locked vehicles 170807
- if!(missionNamespace getVariable ["SA_TOW_LOCKED_VEHICLES_ENABLED",true]) then {
- if( locked _cargo > 1 ) then {
- ["Cannot attach tow ropes to locked vehicle",false] call SA_Hint;
- _canBeTowed = false;
- };
- };
- // Enabled towing in safe zones 170807
- if!(missionNamespace getVariable ["SA_TOW_IN_EXILE_SAFEZONE_ENABLED",true]) then {
- if(!isNil "ExilePlayerInSafezone") then {
- if( ExilePlayerInSafezone ) then {
- ["Cannot attach tow ropes in safe zone",false] call SA_Hint;
- _canBeTowed = false;
- };
- };
- };
- if(_canBeTowed) then {
- [_cargo,player] call SA_Attach_Tow_Ropes;
- };
- };
- };
- SA_Attach_Tow_Ropes_Action_Check = {
- private ["_vehicle","_cargo"];
- _vehicle = player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
- _cargo = cursorTarget;
- [_vehicle,_cargo] call SA_Can_Attach_Tow_Ropes;
- };
- SA_Can_Attach_Tow_Ropes = {
- params ["_vehicle","_cargo"];
- if(!isNull _vehicle && !isNull _cargo) then {
- [_vehicle,_cargo] call SA_Is_Supported_Cargo && vehicle player == player && player distance _cargo < 10 && _vehicle != _cargo;
- } else {
- false;
- };
- };
- SA_Take_Tow_Ropes_Action = {
- private ["_vehicle","_canTakeTowRopes"];
- _vehicle = cursorTarget;
- if([_vehicle] call SA_Can_Take_Tow_Ropes) then {
- _canTakeTowRopes = true;
- if!(missionNamespace getVariable ["SA_TOW_LOCKED_VEHICLES_ENABLED",false]) then {
- if( locked _vehicle > 1 ) then {
- ["Cannot take tow ropes from locked vehicle",false] call SA_Hint;
- _canTakeTowRopes = false;
- };
- };
- if!(missionNamespace getVariable ["SA_TOW_IN_EXILE_SAFEZONE_ENABLED",false]) then {
- if(!isNil "ExilePlayerInSafezone") then {
- if( ExilePlayerInSafezone ) then {
- ["Cannot take tow ropes in safe zone",false] call SA_Hint;
- _canTakeTowRopes = false;
- };
- };
- };
- if(_canTakeTowRopes) then {
- [_vehicle,player] call SA_Take_Tow_Ropes;
- };
- };
- };
- SA_Take_Tow_Ropes_Action_Check = {
- [cursorTarget] call SA_Can_Take_Tow_Ropes;
- };
- SA_Can_Take_Tow_Ropes = {
- params ["_vehicle"];
- if([_vehicle] call SA_Is_Supported_Vehicle) then {
- private ["_existingVehicle","_existingTowRopes"];
- _existingTowRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
- _existingVehicle = player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
- vehicle player == player && player distance _vehicle < 10 && (count _existingTowRopes) == 0 && isNull _existingVehicle;
- } else {
- false;
- };
- };
- SA_Put_Away_Tow_Ropes_Action = {
- private ["_vehicle","_canPutAwayTowRopes"];
- _vehicle = cursorTarget;
- if([_vehicle] call SA_Can_Put_Away_Tow_Ropes) then {
- _canPutAwayTowRopes = true;
- if!(missionNamespace getVariable ["SA_TOW_LOCKED_VEHICLES_ENABLED",false]) then {
- if( locked _vehicle > 1 ) then {
- ["Cannot put away tow ropes in locked vehicle",false] call SA_Hint;
- _canPutAwayTowRopes = false;
- };
- };
- if!(missionNamespace getVariable ["SA_TOW_IN_EXILE_SAFEZONE_ENABLED",false]) then {
- if(!isNil "ExilePlayerInSafezone") then {
- if( ExilePlayerInSafezone ) then {
- ["Cannot put away tow ropes in safe zone",false] call SA_Hint;
- _canPutAwayTowRopes = false;
- };
- };
- };
- if(_canPutAwayTowRopes) then {
- [_vehicle,player] call SA_Put_Away_Tow_Ropes;
- };
- };
- };
- SA_Put_Away_Tow_Ropes_Action_Check = {
- [cursorTarget] call SA_Can_Put_Away_Tow_Ropes;
- };
- SA_Can_Put_Away_Tow_Ropes = {
- params ["_vehicle"];
- private ["_existingTowRopes"];
- if([_vehicle] call SA_Is_Supported_Vehicle) then {
- _existingTowRopes = _vehicle getVariable ["SA_Tow_Ropes",[]];
- vehicle player == player && player distance _vehicle < 10 && (count _existingTowRopes) > 0;
- } else {
- false;
- };
- };
- SA_Drop_Tow_Ropes_Action = {
- private ["_vehicle"];
- _vehicle = player getVariable ["SA_Tow_Ropes_Vehicle", objNull];
- if([] call SA_Can_Drop_Tow_Ropes) then {
- [_vehicle, player] call SA_Drop_Tow_Ropes;
- };
- };
- SA_Drop_Tow_Ropes_Action_Check = {
- [] call SA_Can_Drop_Tow_Ropes;
- };
- SA_Can_Drop_Tow_Ropes = {
- !isNull (player getVariable ["SA_Tow_Ropes_Vehicle", objNull]) && vehicle player == player;
- };
- SA_Pickup_Tow_Ropes_Action = {
- private ["_nearbyTowVehicles","_canPickupTowRopes","_vehicle"];
- _nearbyTowVehicles = missionNamespace getVariable ["SA_Nearby_Tow_Vehicles",[]];
- if([] call SA_Can_Pickup_Tow_Ropes) then {
- _vehicle = _nearbyTowVehicles select 0;
- _canPickupTowRopes = true;
- if!(missionNamespace getVariable ["SA_TOW_LOCKED_VEHICLES_ENABLED",false]) then {
- if( locked _vehicle > 1 ) then {
- ["Cannot pick up tow ropes from locked vehicle",false] call SA_Hint;
- _canPickupTowRopes = false;
- };
- };
- if!(missionNamespace getVariable ["SA_TOW_IN_EXILE_SAFEZONE_ENABLED",false]) then {
- if(!isNil "ExilePlayerInSafezone") then {
- if( ExilePlayerInSafezone ) then {
- ["Cannot pick up tow ropes in safe zone",false] call SA_Hint;
- _canPickupTowRopes = false;
- };
- };
- };
- if(_canPickupTowRopes) then {
- [_nearbyTowVehicles select 0, player] call SA_Pickup_Tow_Ropes;
- };
- };
- };
- SA_Pickup_Tow_Ropes_Action_Check = {
- [] call SA_Can_Pickup_Tow_Ropes;
- };
- SA_Can_Pickup_Tow_Ropes = {
- isNull (player getVariable ["SA_Tow_Ropes_Vehicle", objNull]) && count (missionNamespace getVariable ["SA_Nearby_Tow_Vehicles",[]]) > 0 && vehicle player == player;
- };
- SA_TOW_SUPPORTED_VEHICLES = [
- "Tank", "Car", "Ship", "Air"
- ];
- SA_Is_Supported_Vehicle = {
- params ["_vehicle","_isSupported"];
- _isSupported = false;
- if(not isNull _vehicle) then {
- {
- if(_vehicle isKindOf _x) then {
- _isSupported = true;
- };
- } forEach (missionNamespace getVariable ["SA_TOW_SUPPORTED_VEHICLES_OVERRIDE",SA_TOW_SUPPORTED_VEHICLES]);
- };
- _isSupported;
- };
- SA_TOW_RULES = [
- ["Tank","CAN_TOW","Tank"],
- ["Tank","CAN_TOW","Car"],
- ["Tank","CAN_TOW","Ship"],
- ["Tank","CAN_TOW","Air"],
- ["Car","CAN_TOW","Tank"],
- ["Car","CAN_TOW","Car"],
- ["Car","CAN_TOW","Ship"],
- ["Car","CAN_TOW","Air"],
- ["Ship","CAN_TOW","Ship"]
- ];
- SA_Is_Supported_Cargo = {
- params ["_vehicle","_cargo"];
- private ["_canTow"];
- _canTow = false;
- if(not isNull _vehicle && not isNull _cargo) then {
- {
- if(_vehicle isKindOf (_x select 0)) then {
- if(_cargo isKindOf (_x select 2)) then {
- if( (toUpper (_x select 1)) == "CAN_TOW" ) then {
- _canTow = true;
- } else {
- _canTow = false;
- };
- };
- };
- } forEach (missionNamespace getVariable ["SA_TOW_RULES_OVERRIDE",SA_TOW_RULES]);
- };
- _canTow;
- };
- SA_Hint = {
- params ["_msg",["_isSuccess",true]];
- if(!isNil "ExileClient_gui_notification_event_addNotification") then {
- if(_isSuccess) then {
- ["Success", [_msg]] call ExileClient_gui_notification_event_addNotification;
- } else {
- ["Whoops", [_msg]] call ExileClient_gui_notification_event_addNotification;
- };
- } else {
- hint _msg;
- };
- };
- SA_Hide_Object_Global = {
- params ["_obj"];
- if( _obj isKindOf "Land_Can_V2_F" ) then {
- hideObjectGlobal _obj;
- };
- };
- SA_Set_Owner = {
- params ["_obj","_client"];
- _obj setOwner _client;
- };
- SA_Add_Player_Tow_Actions = {
- player addAction ["Deploy Tow Ropes", {
- [] call SA_Take_Tow_Ropes_Action;
- }, nil, 0, false, true, "", "call SA_Take_Tow_Ropes_Action_Check"];
- player addAction ["Put Away Tow Ropes", {
- [] call SA_Put_Away_Tow_Ropes_Action;
- }, nil, 0, false, true, "", "call SA_Put_Away_Tow_Ropes_Action_Check"];
- player addAction ["Attach To Tow Ropes", {
- [] call SA_Attach_Tow_Ropes_Action;
- }, nil, 0, false, true, "", "call SA_Attach_Tow_Ropes_Action_Check"];
- player addAction ["Drop Tow Ropes", {
- [] call SA_Drop_Tow_Ropes_Action;
- }, nil, 0, false, true, "", "call SA_Drop_Tow_Ropes_Action_Check"];
- player addAction ["Pickup Tow Ropes", {
- [] call SA_Pickup_Tow_Ropes_Action;
- }, nil, 0, false, true, "", "call SA_Pickup_Tow_Ropes_Action_Check"];
- player addEventHandler ["Respawn", {
- player setVariable ["SA_Tow_Actions_Loaded",false];
- }];
- };
- SA_Find_Nearby_Tow_Vehicles = {
- private ["_nearVehicles","_nearVehiclesWithTowRopes","_vehicle","_ends","_end1","_end2"];
- _nearVehicles = [];
- {
- _nearVehicles append (position player nearObjects [_x, 30]);
- } forEach (missionNamespace getVariable ["SA_TOW_SUPPORTED_VEHICLES_OVERRIDE",SA_TOW_SUPPORTED_VEHICLES]);
- _nearVehiclesWithTowRopes = [];
- {
- _vehicle = _x;
- {
- _ends = ropeEndPosition _x;
- if(count _ends == 2) then {
- _end1 = _ends select 0;
- _end2 = _ends select 1;
- if(((position player) distance _end1) < 5 || ((position player) distance _end2) < 5 ) then {
- _nearVehiclesWithTowRopes pushBack _vehicle;
- }
- };
- } forEach (_vehicle getVariable ["SA_Tow_Ropes",[]]);
- } forEach _nearVehicles;
- _nearVehiclesWithTowRopes;
- };
- if(!isDedicated) then {
- [] spawn {
- while {true} do {
- if(!isNull player && isPlayer player) then {
- if!( player getVariable ["SA_Tow_Actions_Loaded",false] ) then {
- [] call SA_Add_Player_Tow_Actions;
- player setVariable ["SA_Tow_Actions_Loaded",true];
- };
- };
- missionNamespace setVariable ["SA_Nearby_Tow_Vehicles", (call SA_Find_Nearby_Tow_Vehicles)];
- sleep 2;
- };
- };
- };
- SA_RemoteExec = {
- params ["_params","_functionName","_target",["_isCall",false]];
- if(!isNil "ExileClient_system_network_send") then {
- ["AdvancedTowingRemoteExecClient",[_params,_functionName,_target,_isCall]] call ExileClient_system_network_send;
- } else {
- if(_isCall) then {
- _params remoteExecCall [_functionName, _target];
- } else {
- _params remoteExec [_functionName, _target];
- };
- };
- };
- SA_RemoteExecServer = {
- params ["_params","_functionName",["_isCall",false]];
- if(!isNil "ExileClient_system_network_send") then {
- ["AdvancedTowingRemoteExecServer",[_params,_functionName,_isCall]] call ExileClient_system_network_send;
- } else {
- if(_isCall) then {
- _params remoteExecCall [_functionName, 2];
- } else {
- _params remoteExec [_functionName, 2];
- };
- };
- };
- if(isServer) then {
- // Adds support for exile network calls (Only used when running exile) //
- SA_SUPPORTED_REMOTEEXECSERVER_FUNCTIONS = ["SA_Set_Owner","SA_Hide_Object_Global"];
- ExileServer_AdvancedTowing_network_AdvancedTowingRemoteExecServer = {
- params ["_sessionId", "_messageParameters",["_isCall",false]];
- _messageParameters params ["_params","_functionName"];
- if(_functionName in SA_SUPPORTED_REMOTEEXECSERVER_FUNCTIONS) then {
- if(_isCall) then {
- _params call (missionNamespace getVariable [_functionName,{}]);
- } else {
- _params spawn (missionNamespace getVariable [_functionName,{}]);
- };
- };
- };
- 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"];
- ExileServer_AdvancedTowing_network_AdvancedTowingRemoteExecClient = {
- params ["_sessionId", "_messageParameters"];
- _messageParameters params ["_params","_functionName","_target",["_isCall",false]];
- if(_functionName in SA_SUPPORTED_REMOTEEXECCLIENT_FUNCTIONS) then {
- if(_isCall) then {
- _params remoteExecCall [_functionName, _target];
- } else {
- _params remoteExec [_functionName, _target];
- };
- };
- };
- // Install Advanced Towing on all clients (plus JIP) //
- publicVariable "SA_Advanced_Towing_Install";
- remoteExecCall ["SA_Advanced_Towing_Install", -2,true];
- };
- diag_log "Advanced Towing Loaded";
- };
- if(isServer) then {
- [] call SA_Advanced_Towing_Install;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement