fn_Quiksilver 1633 Posted April 10, 2023 Hi lads, had an interesting query over on the arma discord, thought I'd post the result for other modders: // QS Visible Lasers // Custom laser point offsets QS_laserOffset_array = [ // element format: ['arifle_mx_f',[0,0.25,0]], // element format: ['srifle_LRR_f',[0,0.25,0]], // element format: ['arifle_mx_f',[0,0.25,0]], // ETC ]; QS_laser_beamColor = [1000, 0, 0]; QS_laser_dotColor = [1000, 0, 0]; QS_laser_dotSize = 0.25; QS_laser_beamThickness = 0.25; QS_laser_beamMaxLength = 100; QS_laser_forceIR = FALSE; QS_fnc_updatePlayerWeaponObject = { if ((player getVariable ['QS_player_currentWeapon','']) isNotEqualTo '') then { player setVariable ['QS_player_currentWeapon','',FALSE]; }; if (!isNull (player getVariable ['QS_player_weaponObject',objNull])) then { player setVariable ['QS_player_weaponObject',objNull,FALSE]; }; if ((player getVariable ['QS_player_weaponMuzzlePos','']) isNotEqualTo '') then { player setVariable ['QS_player_weaponMuzzlePos','',FALSE]; }; if ((player getVariable ['QS_player_currentProxy','']) isNotEqualTo '') then { player setVariable ['QS_player_currentProxy','',FALSE]; }; _handPos = player modelToWorldWorld (player selectionPosition 'righthand'); _intersections = (lineIntersectsSurfaces [ _handPos vectorAdd [0,0,0.3], _handPos vectorAdd [0,0,-0.3] ]) + (lineIntersectsSurfaces [ _handPos vectorAdd [-0.3,0,0], _handPos vectorAdd [0.3,0,0] ]) + (lineIntersectsSurfaces [ _handPos vectorAdd [0,0.3,0], _handPos vectorAdd [0,-0.3,0] ]); if (_intersections isNotEqualTo []) then { private _weaponModel = toLowerANSI (getText (configFile >> 'CfgWeapons' >> (currentWeapon player) >> 'model')); _weaponModelArray = toArray _weaponModel; if ((_weaponModelArray select 0) isEqualTo 92) then { _weaponModelArray deleteAt 0; _weaponModel = toString _weaponModelArray; }; _intersections = _intersections apply { [_x # 2,toLowerANSI ((getModelInfo (_x # 2)) # 1),_weaponModel] }; private _weapon = objNull; { if (_weaponModel isEqualTo (_x # 1)) exitWith { _weapon = _x # 0; }; } forEach _intersections; if (!isNull _weapon) then { player setVariable ['QS_player_currentWeapon',toLowerANSI (currentWeapon player),FALSE]; player setVariable ['QS_player_weaponObject',_weapon,FALSE]; player setVariable ['QS_player_weaponMuzzlePos',toLowerANSI (getText (configFile >> "CfgWeapons" >> (currentWeapon player) >>'muzzleEnd')),FALSE]; private _customOffset = QS_hashmap_laserOffset getOrDefault [toLowerANSI (currentWeapon player),[0,0,0]]; private _currentProxy = ''; if ((currentWeapon player) isEqualTo (primaryWeapon player)) then { _currentProxy = ((player selectionNames 'memory') select { ['weapon.001',_x,FALSE] call BIS_fnc_inString }) select 0; if (_customOffset isEqualTo [0,0,0]) then { _customOffset = [0,0.3,0]; }; }; if ((currentWeapon player) isEqualTo (handgunWeapon player)) then { _currentProxy = ((player selectionNames 'memory') select { ['pistol.001',_x,FALSE] call BIS_fnc_inString }) select 0; if (_customOffset isEqualTo [0,0,0]) then { _customOffset = [0,0.25,0]; }; }; if ((currentWeapon player) isEqualTo (secondaryWeapon player)) then { _currentProxy = ((player selectionNames 'memory') select { ['launcher.001',_x,FALSE] call BIS_fnc_inString }) select 0; if (_customOffset isEqualTo [0,0,0]) then { _customOffset = [0,0.25,0]; }; }; player setVariable ['QS_player_laserCustomOffset',_customOffset,FALSE]; player setVariable ['QS_player_currentProxy',_currentProxy,FALSE]; }; }; }; QS_fnc_updateLaserPos = { _player = _this # 0; _weapon = _this # 1; [ (player modelToWorldVisualWorld ((player selectionPosition (player getVariable ['QS_player_currentProxy',''])) vectorAdd ((_weapon selectionPosition (player getVariable ['QS_player_weaponMuzzlePos',''])) vectorAdd (player getVariable ['QS_player_laserCustomOffset',[0,0,0]])))), (_player weaponDirection (currentWeapon _player)) ] }; if (!isNil 'QS_EH_94') then { removeMissionEventHandler ['Draw3D',QS_EH_94]; }; if (isNil 'QS_hashmap_laserOffset') then { QS_hashmap_laserOffset = createHashMapFromArray QS_laserOffset_array; }; player setVariable ['QS_toggle_visibleLaser',TRUE,FALSE]; player setVariable ['QS_player_currentWeapon','',FALSE]; player setVariable ['QS_player_weaponObject',objNull,FALSE]; QS_EH_94 = addMissionEventHandler [ 'Draw3D', { if (!isGameFocused) exitWith {}; if (isNull (objectParent player)) then { if ((player getVariable ['QS_player_currentWeapon','']) isNotEqualTo (toLowerANSI (currentWeapon player))) then { call QS_fnc_updatePlayerWeaponObject; } else { if ( (!isNull (player getVariable ['QS_player_weaponObject',objNull])) && ((player getVariable ['QS_player_currentProxy','']) isNotEqualTo '') && ((player getVariable ['QS_player_weaponMuzzlePos','']) isNotEqualTo '') ) then { ([player,(player getVariable ['QS_player_weaponObject',objNull])] call QS_fnc_updateLaserPos) params ['_laserStart','_weaponDirection']; if (player getVariable ['QS_toggle_visibleLaser',TRUE]) then { drawLaser [ (player getVariable ['QS_player_weaponObject',objNull]) modelToWorldVisualWorld _laserStart, _weaponDirection, QS_laser_beamColor, QS_laser_dotColor, QS_laser_dotSize, QS_laser_beamThickness, QS_laser_beamMaxLength, (((currentVisionMode player) isNotEqualTo 0) || QS_laser_forceIR) ]; }; }; }; }; } ]; removeAllUserActionEventHandlers ['headlights','activate']; addUserActionEventHandler ['headlights','activate',{ player setVariable ['QS_toggle_visibleLaser',!(player getVariable ['QS_toggle_visibleLaser',FALSE]),FALSE]; }]; 8 Share this post Link to post Share on other sites
pierremgi 4743 Posted April 10, 2023 Very nice application of what can be done the intersections and selections commands. (I have to dig for the ((_weaponModelArray select 0) isEqualTo 92) condition). Share this post Link to post Share on other sites
LSValmont 789 Posted April 10, 2023 13 hours ago, pierremgi said: Very nice application of what can be done the intersections and selections commands. (I have to dig for the ((_weaponModelArray select 0) isEqualTo 92) condition). Here is the improved version, with heavy credits towards @Leopard20 , @fn_Quiksilver and @POLPOX VAL_fn_drawLaser = { if !(isNil "V_PLAYERLASEREHID") exitWith {removeMissionEventHandler ["Draw3D", V_PLAYERLASEREHID]; V_PLAYERLASEREHID = nil; systemChat "Weapon Laser Off"; playSound3D ["A3\missions_f\data\sounds\click.wss", player];}; if (currentWeapon player isEqualTo secondaryWeapon player) exitWith {systemChat "Weapon Laser NOT AVAILABLE";}; playSound3D ["A3\missions_f\data\sounds\click.wss", player]; V_PLAYERLASEREHID = addMissionEventHandler ["Draw3D", { private _laserDir = (player weaponDirection (currentWeapon player)); private _w = currentWeapon player; if (_w != player getVariable ["last_weapon", "?"]) then { private _cfg = configFile >> "CfgWeapons" >> _w; private _m = getText(_cfg >> "model"); private _o = createSimpleObject [_m, [0,0,0], true]; private _off = _o selectionPosition [getText(_cfg >> "muzzlePos"), "memory"]; _off = _off apply {[_x]}; deleteVehicle _o; player setVariable ["offset", _off]; player setVariable ["last_weapon", _w]; player setVariable ["proxy", [ "proxy:\a3\characters_f\proxies\pistol.001", "proxy:\a3\characters_f\proxies\weapon.001", "proxy:\a3\characters_f\proxies\launcher.001", "proxy:\a3\characters_f\proxies\binoculars.001" ] select (([1, 4, 4096] find getNumber(_cfg >> "type")) + 1) ]; }; private _offset = player getVariable ["offset", []]; private _proxy = player getVariable ["proxy", ""]; player selectionVectorDirAndUp [_proxy, 1] params ["_vy", "_vz"]; private _pos = selectionPosition [player, _proxy, 0]; private _vx = _vy vectorCrossProduct _vz; private _mat = matrixTranspose [_vx, _vy, _vz]; _pos = _pos vectorAdd flatten (_mat matrixMultiply _offset); _pos = _pos vectorAdd [0.01,0.15,-0.05]; private _laserStart = player modelToWorldVisualWorld _pos; drawLaser [ _laserStart, _laserDir, [1000, 0, 0], [1000, 0, 0], 0.20, 0.25, 100, false ]; }]; systemChat "Weapon Laser ON"; }; Thank you guys, and enjoy! 5 Share this post Link to post Share on other sites
fn_Quiksilver 1633 Posted April 11, 2023 17 hours ago, LSValmont said: Here is the improved version, with heavy credits towards @Leopard20 , @fn_Quiksilver and @POLPOX VAL_fn_drawLaser = { if !(isNil "V_PLAYERLASEREHID") exitWith {removeMissionEventHandler ["Draw3D", V_PLAYERLASEREHID]; V_PLAYERLASEREHID = nil; systemChat "Weapon Laser Off"; playSound3D ["A3\missions_f\data\sounds\click.wss", player];}; if (currentWeapon player isEqualTo secondaryWeapon player) exitWith {systemChat "Weapon Laser NOT AVAILABLE";}; playSound3D ["A3\missions_f\data\sounds\click.wss", player]; V_PLAYERLASEREHID = addMissionEventHandler ["Draw3D", { private _laserDir = (player weaponDirection (currentWeapon player)); private _w = currentWeapon player; if (_w != player getVariable ["last_weapon", "?"]) then { private _cfg = configFile >> "CfgWeapons" >> _w; private _m = getText(_cfg >> "model"); private _o = createSimpleObject [_m, [0,0,0], true]; private _off = _o selectionPosition [getText(_cfg >> "muzzlePos"), "memory"]; _off = _off apply {[_x]}; deleteVehicle _o; player setVariable ["offset", _off]; player setVariable ["last_weapon", _w]; player setVariable ["proxy", [ "proxy:\a3\characters_f\proxies\pistol.001", "proxy:\a3\characters_f\proxies\weapon.001", "proxy:\a3\characters_f\proxies\launcher.001", "proxy:\a3\characters_f\proxies\binoculars.001" ] select (([1, 4, 4096] find getNumber(_cfg >> "type")) + 1) ]; }; private _offset = player getVariable ["offset", []]; private _proxy = player getVariable ["proxy", ""]; player selectionVectorDirAndUp [_proxy, 1] params ["_vy", "_vz"]; private _pos = selectionPosition [player, _proxy, 0]; private _vx = _vy vectorCrossProduct _vz; private _mat = matrixTranspose [_vx, _vy, _vz]; _pos = _pos vectorAdd flatten (_mat matrixMultiply _offset); _pos = _pos vectorAdd [0.01,0.15,-0.05]; private _laserStart = player modelToWorldVisualWorld _pos; drawLaser [ _laserStart, _laserDir, [1000, 0, 0], [1000, 0, 0], 0.20, 0.25, 100, false ]; }]; systemChat "Weapon Laser ON"; }; Thank you guys, and enjoy! awesome work lads that "selectionVectorDirAndUp" is a game changer for stuff like this 3 Share this post Link to post Share on other sites
stburr91 996 Posted April 15, 2023 On 4/10/2023 at 9:56 AM, LSValmont said: Here is the improved version, with heavy credits towards @Leopard20 , @fn_Quiksilver and @POLPOX VAL_fn_drawLaser = { if !(isNil "V_PLAYERLASEREHID") exitWith {removeMissionEventHandler ["Draw3D", V_PLAYERLASEREHID]; V_PLAYERLASEREHID = nil; systemChat "Weapon Laser Off"; playSound3D ["A3\missions_f\data\sounds\click.wss", player];}; if (currentWeapon player isEqualTo secondaryWeapon player) exitWith {systemChat "Weapon Laser NOT AVAILABLE";}; playSound3D ["A3\missions_f\data\sounds\click.wss", player]; V_PLAYERLASEREHID = addMissionEventHandler ["Draw3D", { private _laserDir = (player weaponDirection (currentWeapon player)); private _w = currentWeapon player; if (_w != player getVariable ["last_weapon", "?"]) then { private _cfg = configFile >> "CfgWeapons" >> _w; private _m = getText(_cfg >> "model"); private _o = createSimpleObject [_m, [0,0,0], true]; private _off = _o selectionPosition [getText(_cfg >> "muzzlePos"), "memory"]; _off = _off apply {[_x]}; deleteVehicle _o; player setVariable ["offset", _off]; player setVariable ["last_weapon", _w]; player setVariable ["proxy", [ "proxy:\a3\characters_f\proxies\pistol.001", "proxy:\a3\characters_f\proxies\weapon.001", "proxy:\a3\characters_f\proxies\launcher.001", "proxy:\a3\characters_f\proxies\binoculars.001" ] select (([1, 4, 4096] find getNumber(_cfg >> "type")) + 1) ]; }; private _offset = player getVariable ["offset", []]; private _proxy = player getVariable ["proxy", ""]; player selectionVectorDirAndUp [_proxy, 1] params ["_vy", "_vz"]; private _pos = selectionPosition [player, _proxy, 0]; private _vx = _vy vectorCrossProduct _vz; private _mat = matrixTranspose [_vx, _vy, _vz]; _pos = _pos vectorAdd flatten (_mat matrixMultiply _offset); _pos = _pos vectorAdd [0.01,0.15,-0.05]; private _laserStart = player modelToWorldVisualWorld _pos; drawLaser [ _laserStart, _laserDir, [1000, 0, 0], [1000, 0, 0], 0.20, 0.25, 100, false ]; }]; systemChat "Weapon Laser ON"; }; Thank you guys, and enjoy! I must be missing something, I put this in an init file, and it doesn't do anything. How does this work? Share this post Link to post Share on other sites
LSValmont 789 Posted April 16, 2023 19 hours ago, stburr91 said: I must be missing something, I put this in an init file, and it doesn't do anything. How does this work? Put the code in initPlayerLocal.sqf and a few lines after put: player call VAL_fn_drawLaser; Then inside the game you might need to call the function again to turn the laser ON/OFF. I do that by adding a keyPressed EH for when shift+L is pressed by the player but you can add an addaction or call it from the debug console too, whatever is easier for you. 1 Share this post Link to post Share on other sites