// by commy2 and esteldunedain #include "script_component.hpp" EXPLODE_3_PVT(_this,_unit,_range,_isGreen); _p0Pos = _unit modelToWorld (_unit selectionPosition "righthand"); // Convert _p0Pos to ASL _p0 = + _p0Pos; if (!surfaceIsWater _p0) then { _p0 = ATLtoASL _p0; }; // Find a system of orthogonal reference vectors // _v1 points in the direction of the weapon // _v2 points to the right of the weapon // _v3 points to the top side of the weapon _v1 = _unit weaponDirection currentWeapon _unit; _v2 = vectorNormalized (_v1 vectorCrossProduct [0,0,1]); _v3 = _v2 vectorCrossProduct _v1; // Offset over the 3 reference axis // This offset could eventually be configured by weapon in the config _offV1 = 0.31; _offV2 = 0; _offV3 = 0.08; // Offset _p0, the start of the laser _p0 = _p0 vectorAdd (_v1 vectorMultiply _offV1) vectorAdd (_v3 vectorMultiply _offV3) vectorAdd (_v2 vectorMultiply _offV2); _p0Pos = _p0Pos vectorAdd (_v1 vectorMultiply _offV1) vectorAdd (_v3 vectorMultiply _offV3) vectorAdd (_v2 vectorMultiply _offV2); // Calculate _p1, the potential end of the laser _p1 = _p0 vectorAdd (_v1 vectorMultiply _range); //Debugaaa = lineIntersectsObjs [_p0, _p1, objNull, _unit, false, 2]; _fnc_getDistanceToTerrain = { private "_distance"; _pX = + _p0; _line = [_p0, _pX]; _distance = _this; _iteration = _distance; while { _iteration > 0.05 / 2 } do { _iteration = _iteration / 2; _pX = _p0 vectorAdd (_v1 vectorMultiply _distance); _line set [1, _pX]; _distance = _distance + (([1, -1] select (lineIntersects (_line + [_unit]) || {terrainIntersectASL _line})) * _iteration); if (_distance > _this) exitWith {_distance = _this}; }; _distance }; // Get distance to nearest object or terrain (excluding men) _distance = _range call _fnc_getDistanceToTerrain; // Find all men potentially intercepted by the ray _intermediatePos = _p0 vectorAdd (_v1 vectorMultiply _distance/2); if (!surfaceIsWater _intermediatePos) then { _intermediatePos = ASLtoATL _intermediatePos; }; _units = nearestObjects [_intermediatePos, ["Man"], _distance/2]; _units deleteAt (_units find _unit); _fnc_doesIntersectWithMan = { _pX = _p0 vectorAdd (_v1 vectorMultiply (_this select 1)); if (!surfaceIsWater _pX) then { _pX = ASLtoATL _pX; }; count ([_this select 0, "FIRE"] intersect [_p0Pos, _pX]) > 0 }; // Test intersection with nearby men { if ([_x, _distance] call _fnc_doesIntersectWithMan) then { _distance = _distance min ((_unit distance _x) - _offV1); }; } forEach _units; //systemChat str _distance; if (_distance < 0.5) exitWith {}; _pL = _p0 vectorAdd (_v1 vectorMultiply _distance); _pL2 = _p0 vectorAdd (_v1 vectorMultiply (_distance - 0.5)); // Convert _pL to pos if (!surfaceIsWater _pL) then { _pL = ASLtoATL _pL; }; drawLine3D [ _p0Pos, _pL, [[1,0,0,1], [0,1,0,1]] select _isGreen ]; _size = 2 * (_range - (positionCameraToWorld [0,0,0] distance _pL)) / _range; _camPos = positionCameraToWorld [0,0,0.2]; if (count ([_unit, "FIRE"] intersect [_camPos, _pL]) > 0) exitWith {}; if (count ([ACE_player, "FIRE"] intersect [_camPos, _pL]) > 0) exitWith {}; // Convert _camPos to ASL if (!surfaceIsWater _camPos) then { _camPos = ATLtoASL _camPos; }; if ( terrainIntersectASL [_camPos, _pL2]) exitWith {}; if ( lineIntersects [_camPos, _pL2]) exitWith {}; drawIcon3D [ format ["\a3\weapons_f\acc\data\collimdot_%1_ca.paa", ["red", "green"] select _isGreen], [[1,0.25,0.25,0.5*_brightness], [0.25,1,0.25,0.5*_brightness]] select _isGreen, _pL, _size, _size, 45, "", 0, 0.05 ];