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