Jump to content
HallyG

[CODE SNIPPET] Visualise target practice hits

Recommended Posts

Here's a script snippet to play around with that can be used to visualise your shots during target practice. At the moment this only works in singleplayer (I haven't tested it in multiplayer).

 

init.sqf

Spoiler

HALs_hits_fnc_targetOffset = {
	params [
		["_classname", "", [""]],
		["_default", [0, 0, 0], [[]]]
	];
	
	switch (_classname) do {
		case "TargetP_Inf_Acc2_F": {[0.00488281, -0.161133, 0.0170088]};//[0, -0.161621, 0]};
		default {_default};
	}
};

HALs_hits_fnc_addTarget = {
	params [
		["_target", objNull, [objNull]]
	];
	
	if (isNull _target) exitWith {};
	if ((_target getVariable ["HALs_hits_hitPartID", -1]) > 0) exitWith {};

	_target animateSource ["terc", 0];

	_target setVariable ["HALs_hits_hitID",
		_target addEventHandler ["Hit", {
			_this spawn {
				params ["_unit"];
				
				waitUntil {_unit animationPhase "terc" > 0};
				_unit animateSource ["terc", 0, true];
			}
		}]
	];

	_target setVariable ["HALs_hits_hitPartID",
		_target addEventHandler ["HitPart", {
			(_this select 0) params ["_tgt", "_shooter", "", "_position", "", "", "", "", "", "", "_isDirect"];

			if (_isDirect) then {
				if (_shooter == _tgt getVariable ["HALs_hits_currentShooter", objNull]) then {
					_position = _position vectorAdd [0, 0, - (getTerrainHeightASL _position)];
					_offset = [typeOf _tgt] call HALs_hits_fnc_targetOffset;
					_pos = (_tgt worldToModelVisual _position) vectorAdd _offset;
						
					if (count _pos > 0) then {
						_arr = _tgt getVariable ["HALs_hits_array", []];
						_arr pushBack _pos;
						
						if (count _arr > HALs_hits_target_history) then {
							_amt = count _arr - HALs_hits_target_history;
							_arr = _arr select [_amt, count _arr];
						};
						
						_tgt setVariable ["HALs_hits_array", _arr, true];
					};
				};
			};
		}]
	];
};

HALs_hits_fnc_removeTarget = {
	params [
		["_target", objNull, [objNull]]
	];
	
	if (isNull _target) exitWith {};
	if ((_target getVariable ["HALs_hits_hitPartID", -1]) < 0) exitWith {};
	
	_target removeEventHandler ["HitPart", _target getVariable ["HALs_hits_hitPartID", -1]];
	_target setVariable ["HALs_hits_hitPartID", nil];

	_target removeEventHandler ["Hit", _target getVariable ["HALs_hits_hitID", -1]];
	_target setVariable ["HALs_hits_hitID", nil];
	
	(_target getVariable ["HALs_hits_currentShooter", objNull]) setVariable ["HALs_hits_currentTarget", nil, true];
	_target setVariable ["HALs_hits_currentShooter", nil, true];
};

HALs_hit_fnc_setTargetShooter = {
	params [
		["_target", objNull, [objNull]],
		["_shooter", objNull, [objNull]]
	];
	
	if (isNull _target) exitWith {};
	
	(_shooter getVariable ["HALs_hits_currentTarget", objNull]) setVariable ["HALs_hits_currentShooter", nil, true];
	_shooter setVariable ["HALs_hits_currentTarget", objNull, true];

	_target setVariable ["HALs_hits_currentShooter", _shooter, true];
	_shooter setVariable ["HALs_hits_currentTarget", _target, true];
};

HALs_hits_fnc_ui = {
	params [
		["_mode", "init", [""]],
		["_params", [], [[]]]
	];
	
	if (!hasInterface) exitWith {};

	private _w = pixelW * 250;
	private _h = pixelH * 250;
	private _max = 50;

	switch (toLower _mode) do {
		case "init": {
			private _display = uiNamespace getVariable ["HALs_hits_display",  findDisplay 46];

			if (!isNull (_display getVariable ["ctrlGroup", controlNull])) exitWith {};

			private _ctrlGroup = _display ctrlCreate ["RscControlsGroupNoScrollbars", 13001];
			_ctrlGroup ctrlSetPosition [safeZoneX + (safeZoneW/2 - _w/2), safeZoneY + pixelH * safeZoneH, _w, _h];
			_ctrlGroup ctrlEnable false;
			_ctrlGroup ctrlShow false;
			_ctrlGroup ctrlCommit 0;
			
			_display setVariable ["ctrlGroup", _ctrlGroup];
			_ctrlGroup setVariable ["_max", _max max 1];
			_ctrlGroup setVariable ["_ctrls", []];

			private _ctrlRings = _display ctrlCreate ["RscPictureKeepAspect", -1, _ctrlGroup];
			_ctrlRings ctrlSetPosition [0, 0, _w, _h];
			_ctrlRings ctrlSetText "a3\structures_f\training\data\target_longrange_co.paa";
			_ctrlRings ctrlSetTextColor [1, 1, 1, 1];
			_ctrlRings ctrlCommit 0;
			
			HALs_hits_old = [];
			HALs_hits_target = objNull;
			HALs_hits_tick = diag_tickTime;
			HALs_hits_evh = addMissionEventHandler ["EachFrame", {
				_display = uiNamespace getVariable ["HALs_hits_display",  findDisplay 46];
				_ctrlGroup = _display getVariable ["ctrlGroup", controlNull];

				_obj = player getVariable ["HALs_hits_currentTarget", objNull];	
				if (_obj != HALs_hits_target) then {
					_ctrlGroup ctrlEnable (!isNull _obj);
					_ctrlGroup ctrlShow (!isNull _obj);
					
					HALs_hits_target = _obj;
					HALs_hits_old = [];
					["clearHits"] call HALs_hits_fnc_ui;
				};

				if (!isNull _obj) then {
					if (diag_tickTime > HALs_hits_tick) then {
						_ctrls = _ctrlGroup getVariable ["_ctrls", []];
						_max = _ctrlGroup getVariable ["_max", 10];
						_cnt = count _ctrls;

						// Delete oldest first
						if (_cnt > _max) then {
							_amt = _cnt - _max;
							{
								_x params ["_ctrl", "_ctrlBG"];
								
								ctrlDelete _ctrl;
								ctrlDelete _ctrlBG;
							} forEach (_ctrls select [0, _amt]);

							_ctrls = _ctrls select [_amt, count _ctrls];
						};
						
						// Update colour
						{
							_x params ["_ctrl", "_ctrlBG", "_start", "_end"];
							
							_colour = linearConversion [_start, _end, time, 0, 1];
							_ctrl ctrlSetTextColor [1, _colour, _colour, 1];
						} count _ctrls;
				
						_ctrlGroup setVariable ["_ctrls", _ctrls];		
						
						_hits = _obj getVariable ["HALs_hits_array", []];
						_hitsDiff = _hits - HALs_hits_old;

						if (count _hitsDiff > 0 && !(_hits isEqualTo HALs_hits_old)) then {
							// To avoid drawing more than the _max value, we get the _max from the end.
							_cnt = count _hitsDiff;			
							_start = _cnt - _max; 
							_amt = _max min _cnt;
						
							{
								["addhit", [_x]] call HALs_hits_fnc_ui;
							} forEach (_hitsDiff select [_start max 0, _amt]);
							
							HALs_hits_old = +_hits;
						};
						
						HALs_hits_tick = HALs_hits_tick + 0.1;		
					};
				} else {
					["clearHits"] call HALs_hits_fnc_ui;
				};

				if (isNull _ctrlGroup) then {
					removeMissionEventHandler ["EachFrame", _thisEventHandler];
				};
			}];
		};
		
		case "addhit": {
			_params params [
				["_pos", [], [[]], [3]]
			];
			
			if (_pos isEqualTo []) exitWith {};
			
			_display = uiNamespace getVariable ["HALs_hits_display",  findDisplay 46];
			_ctrlGroup = _display getVariable ["ctrlGroup", controlNull];
			_ctrls = _ctrlGroup getVariable ["_ctrls", []];
			
			// Dot size
			_wDot = pixelW * 28;
			_hDot = pixelH * 28;
			// Image size
			_w2 = (ctrlPosition _ctrlGroup select 2) / 2;
			_h2 = (ctrlPosition _ctrlGroup select 3) / 2;
			// Image coords
			_x = (_w2 - _wDot/2) + linearConversion [-0.30, 0.30, _pos select 0, -_w2, _w2, false];
			_y = (_h2 - _hDot/2) + linearConversion [-0.33, 0.27, _pos select 2, _h2, -_h2, false];
	
			_ctrlDotBG = _display ctrlCreate ["RscPicture", -1, _ctrlGroup];
			_ctrlDotBG ctrlSetPosition [_x, _y, _wDot, _hDot];
			_ctrlDotBG ctrlSetText "A3\ui_f\data\map\markers\military\dot_CA.paa";
			_ctrlDotBG ctrlSetTextColor [0, 0, 0, 1];
			_ctrlDotBG ctrlCommit 0;

			_ctrlDot = _display ctrlCreate ["RscPicture", -1, _ctrlGroup];
			_ctrlDot ctrlSetPosition [_x + pixelW * 5, _y + pixelH * 5, pixelW * 18, pixelH * 18];
			_ctrlDot ctrlSetText "A3\ui_f\data\map\markers\military\dot_CA.paa";
			_ctrlDot ctrlSetTextColor [1, 0, 0, 1];
			_ctrlDot ctrlCommit 0;

			_ctrls pushBack [_ctrlDot, _ctrlDotBG, time, time + 1.5];
			_ctrlGroup setVariable ["_ctrls", _ctrls];
		};
		
		case "clearhits": {
			_display = uiNamespace getVariable ["HALs_hits_display",  findDisplay 46];
			_ctrlGroup = _display getVariable ["ctrlGroup", controlNull];
			
			if (isNull _ctrlGroup) exitWith {};
			
			{
				_x params ["_ctrl", "_ctrlBG"];
				
				ctrlDelete _ctrl;
				ctrlDelete _ctrlBG;
			} forEach (_ctrlGroup getVariable ["_ctrls", []]);
			
			_ctrlGroup setVariable ["_ctrls", []];
		};
		
		case "toggle": {
			_display = uiNamespace getVariable ["HALs_hits_display",  findDisplay 46];
			_ctrlGroup = _display getVariable ["ctrlGroup", controlNull];
			
			if (isNull _ctrlGroup) exitWith {};
			
			_ctrlGroup ctrlEnable !(ctrlEnabled _ctrlGroup);
			_ctrlGroup ctrlShow !(ctrlShown _ctrlGroup);
		};
	};
};

HALs_hits_fnc_init = {
	HALs_hits_target_history = 100;
	
	if (hasInterface) then {
		waitUntil {!isNull findDisplay 46};
		
		["init"] call HALs_hits_fnc_ui;
	};
};

h = [] spawn {
	[] spawn HALs_hits_fnc_init;

	private _unit = player;
	private _dir = getDir _unit;
	private _pos = _unit getPos [25, getDir _unit];
	private _target = createVehicle ["TargetP_Inf_Acc2_F", _pos, [], 0, "NONE"];
	_target setDir _dir;
		
	[_target] call HALs_hits_fnc_addTarget;
	// Set _unit as the active shooter on this target 
	[_target, _unit] call HALs_hit_fnc_setTargetShooter;
};

 

 

  • The classname of the target used in the video is "TargetP_Inf_Acc2_F".
  • Change HALs_hits_target_history to change how many previous hits that each target remembers.
  • Change _w, _h in HALs_hits_fnc_ui to adjust the width and height of the ui.
  • Change _max in HALs_hits_fnc_ui to change the maximum number hits that can be shown (on the ui) at once.
  • Add a target object with [<obj>] call HALs_hits_fnc_removeTarget.
  • Add a target object with [<obj>] call HALs_hits_fnc_addTarget.
  • Set the target object's active shooter with [<obj>, <unit>] call HALs_hit_fnc_setTargetShooter.
  • Add your own target types in HALs_hits_fnc_targetOffset.
  • Like 3
  • Thanks 4

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×