[FA Addon Making] Weapon Selector - beta testing / Collab

All Party-approved topics welcome
Post Reply
Black Mamba
Posts: 335
Joined: Sun May 27, 2012 12:11 pm

[FA Addon Making] Weapon Selector - beta testing / Collab

Post by Black Mamba »

Beware: this is not a finished addon. I DO NOT recommend you use it in the regular sessions in its current state! (Although you do what you wanna do)

After much bangin my head against walls, I think I've come up with a (decent?) way to do what I wanted to do, i.e revamp the current Weapon Selection system in arma.
Yup, I got bored of having to scroll through all the weapons to get from Full auto to semi auto, or 203 to auto.
So my goal here was to separate the weapon selection from the fire-mode selection, and make it so if you're in full auto, throw a grenade, you don't get back to a semi auto gun.

In practice, what it does (wants to do):

- Uses two keyboard keys and the mousewheel
- One of those keys, when pressed, brings a up a menu (action menu style) containing every weapon you have.
- You can use your mousewheel to scroll through that menu, as you do with the Action Menu, and select a weapon using the middle button. It'll switch to that weapon.
- When the key is released, the menu disappears.
- The other key browse through the firemodes if you're carrying a pistol or a primary weapon. Note that the 203 launcher (or GP25) is considered a weapon on its own, so it will not be toggled by the fire mode selector.
- When you switch weapons, it'll remember which firemode you were in before.
- It ignores the mines/IEDs/Satchels so you don't blow yourself up while trying to change the color of your smoke.
- It also removes the default "Weapon: stuff" you get in your action menu.
- (it will be compatible with my other addon, the one with one button for the nades?) // Not done yet.

Now, it's not perfect because:

- it's ugly as hell (but who cares, right?)
- it doesn't make any difference between the different colors of smoke/type of grenades
- even though it looks like a light script, it's still a scripted solution and is dependant on scriptload/FPS.
- the implementation of it all might be retarded. It can certainly be optimized.
- it might mess up with some mods (although it shouldn't with what you can use in the regular sessions and ASR_AI)
- it doesn't work into vehicles. My current way of using it makes me unbind the "F" key (switch weapons/modes) but I use Ctrl+F to switch between guns in vehicles.
- it still contains development/unused code.

Why do I post this here:

- first, to gauge the interest for such a thing.
- because, if somebody can look at the code with fresh eyes and tell me what's messed up, what's retarded, how to do things in a better/more efficient way etc. it'll be better.
- because, if somebody knows his way around User Interface in Arma, design, etc. it'll be even cooler.
- because, every person who tests it can report bugs / unwanted features / needed features.

If interest for a collaborative work on this is shown, I might throw in a GitHub repository (although GitHub still drives me mad).

So here's the addon in its current beta form (0.2). You will need Eliteness to look into it, probably.
You can stick that in any modfolder to test it, as usual.
To use it, you'll have to bind one key (FireMode Selector) to Custom Controls / Use Action 18, and the other (Weapon Selection) to Custom Controls / Use Action 19.

Planning to do:
- Document the code (yes, I'm lazy).
- Stick the key Bindings in a new group of controls in the Arma/Options/Controls to make it more user friendly.
- fix game breaking bugs
- optimize the code as well as possible.

Known/reported bugs:

- Doesn't remember the firemode when switching back to some weapons having odd default muzzle (e.g G36K)
- Doesn't remember the firemode when automatically switching back to the main weapon (e.g after throwing your last grenade)
- For some reason, the last version here doesn't ignore the binos. Will fix.
Last edited by Black Mamba on Wed Feb 06, 2013 11:13 am, edited 6 times in total.

User avatar
harakka
Posts: 365
Joined: Fri Jul 29, 2011 3:35 pm
Location: Finland

Re: [FA Addon Making] Weapon Selector - beta testing / Colla

Post by harakka »

This looks very promising! Watching with interest.
Me and him, we're from different ancient tribes. Now we're both almost extinct. Sometimes you gotta stick with the ancient ways, the old school ways. I know you understand me.

User avatar
wolfenswan
Posts: 1209
Joined: Wed May 25, 2011 4:59 pm

Re: [FA Addon Making] Weapon Selector - beta testing / Colla

Post by wolfenswan »

Sweet stuff Mamba. Would you mind putting it on GIT?

Black Mamba
Posts: 335
Joined: Sun May 27, 2012 12:11 pm

Re: [FA Addon Making] Weapon Selector - beta testing / Colla

Post by Black Mamba »

Will do!
Although be advised, this is really anoying to see how retarded all those configs are.
Also I'll take some time to document the code first.

For the time being, here is the global script (I'll ignore the config for now, as it doesn't contain anything interesting. Diving further into configs might help solve the issues, but then again, it would more than probably ruin any compatibility with a lot of mods).

As specified in the OP, my objectives for now:
- make it work first (Yup. Seriously). With ALL vanilla weapons, even though the config is retarded.
- start optimizing :
probably cut more stuff into separate functions, for repeated operations + less dependencies between functions
use the preprocessor in a clever way if I can

As a rule of thumb, I try to get a minimum of hardcoded stuff to keep as much inter-mods compatibility as possible (although for now, the grenades stuff is not good).

Code: Select all

/* ============================================================================

BM Weapon and Fire Mode Selector

Open Source project for collaborative development.

Author : 
	FOLK ARPS

============================================================================ */

#define __cfg(NAME) configFile >> "CfgWeapons" >> NAME
#define __cfgm(NAME) configFile >> "CfgMagazines" >> NAME

/* ----------------------------------------------------------------------------
BM_fn_checkWps

Description: Checks if the weapon is to be added to the menu. (excludes binos, and all non-weapon items)

Parameters: 
	_w : weapon, String

Returns:
		boolean
		
---------------------------------------------------------------------------- */

BM_fn_checkWps = {
	_w = _this;
	_str = inheritsFrom (__cfg(_w)); 
	_st = [str(_str), "/"] call CBA_fnc_split;
	_s = _st select 2;
	_r = true;
	if (_s == "Binocular" || _s == "ItemCore") then {
		if (_w == "Laserdesignator") then { _r = true} else {
		_r = false; };
	};
	_r
};

/* ----------------------------------------------------------------------------
BM_fn_checkMuzzles

Description: Deprecated.

Parameters: 
	_w : weapon, String

Returns:
		array
		
---------------------------------------------------------------------------- */

BM_fn_checkMuzzles = {
	_w = _this;
	_mz = [];
	if (isArray (__cfg( _w >> "muzzles"))) then {
		_mz = getArray (__cfg( _w >> "muzzles"));
		if (_mz select 0 == "this") then {
			_mz set [0, [_w, getText (__cfg(_w >> "displayName"))]];
		};
		if (count _mz > 1) then {
			_cmz = _mz select 1;
			_mz set [1, [_cmz, getText (__cfg(_w >> _cmz >> "displayName"))]];
			_mz resize 2;
		};
	} else {
		_mz = [_w, getText (__cfg(_w >> "displayName"))];
	};
	_mz
};

/* ----------------------------------------------------------------------------
BM_fn_checkMuzzlesAlt

Description: Checks if the weapon has several muzzles, and which can be used by players.

Parameters: 
	_w : weapon, String

Returns:
		Array, nested : [[<weapon>, <displayName>], ..., [<muzzle>, <displayName>]]

Note: the _i = _i+1; should be moved to the end of the forEach loop. I'm tired.
---------------------------------------------------------------------------- */

BM_fn_checkMuzzlesAlt = {
	private ["_i"];
	_w = _this;
	_mz = [];
	if (isArray (__cfg( _w >> "muzzles"))) then {
		_i = 0;
		_mz = getArray (__cfg( _w >> "muzzles"));
		{
			if (_x == "this") then {
				_mz set [_i, [_w, getText (__cfg(_w >> "displayName"))]];
				_i = _i + 1;
			} else {
				_st = (getNumber (__cfg(_w >> _x >> "showtoplayer")) == 1);
				if _st then {
					_mz set [_i, [_x, getText (__cfg(_w >> _x >> "displayName"))]];
					_i = _i + 1;
				} else {
					_mz set [_i, -1];
					_i = _i + 1;
				};
			};
		} forEach _mz;
		_mz = _mz - [-1];
	} else {
		_mz = [_w, getText (__cfg(_w >> "displayName"))];
	};
	_mz
};

/* ----------------------------------------------------------------------------
BM_fn_getWeapons

Description: Retrieve all the weapons in the player's inventory.

Parameters: 
	
Returns:
		Array, nested : [[<weapon>, <displayName>], ..., [<muzzle>, <displayName>]]
		
---------------------------------------------------------------------------- */

BM_fn_getWeapons = {
	private ["_i"];
	_wps = [];
	_i = 0;
	{
		_b = _x call BM_fn_checkWps;
		if  (_b) then {
			_mz = _x call BM_fn_checkMuzzlesAlt;
			{
				_wps set [_i, _x]; 
				_i = _i + 1;
			} forEach _mz;
		};
	} forEach weapons player;
	_g = call BM_fn_getNadesAlt;
	_wps = _wps + _g;
	_wps
};

/* ----------------------------------------------------------------------------
BM_fn_getNadesAlt

Description: Check the player's inventory for different types of throwable weapons:
	- IR strobe
	- Smoke grenades
	- HE grenades

Parameters: 
	
Returns:
		Array, nested : [[<weapon>, <displayName>], ..., [<muzzle>, <displayName>]]
		
---------------------------------------------------------------------------- */

BM_fn_getNadesAlt = {
	private ["_sm"];
	_m = magazines player;
	_gar = [];
	_dar = [];
	_i = 0;
	_j = 0;
	_h = true;
	_sm = true;
	{
		if !(_x in _dar) then {
			_dar set [_j, _x];
			if (_x == "IR_Strobe_Target") then {
				_gar set [_i, ["IRStrobe", "IR Strobe"]];
				_i = _i + 1;
			} else {
				_str = inheritsFrom (__cfgm(_x)); 
				_st = [str(_str), "/"] call CBA_fnc_split;
				_s = _st select 2;
				if ((_s == "SmokeShell" || _x == "SmokeShell") && _sm) then {
						_sm = false;
						_gar set [_i, ["SmokeShellMuzzle", "Smoke Grenade"]];
						_i = _i + 1;
				} else {
					if ((_s == "HandGrenade" || _s == "HandGrenade_West") && _h) then {
						_h = false;
						_gar set [_i, ["HandGrenadeMuzzle", "HE Grenade"]];
						_i = _i + 1;
					};
				};
			};
		};
	} forEach _m;
	_gar
};

/* ----------------------------------------------------------------------------
BM_fn_ScrollOn

Description: Creates a scroll menu containing all the player's weapons.

Parameters: 
	
Returns:

---------------------------------------------------------------------------- */

BM_fn_ScrollOn = {
	_isOn = player getVariable ["BM_WpMenuOn", false];
	if (_isOn) exitwith {};
	if (vehicle player != player) exitWith {};
	player setVariable ["BM_WpMenuOn", true];
	_m2 = [];
	_wp = call BM_fn_getWeapons;
	{
		_m2 set [_forEachIndex, _x select 1];
	} forEach _wp;

	_m0 = "Weapon Selector";
	_m1 = "Weap_Sel";
	_m3 = "";
	_m4 = "[%2, %3] call BM_fn_SwWeap";
	_m5 = _wp;
	_m6 = false;

	[_m0, _m1, _m2, _m3, _m4, _m5, _m6] call BIS_FNC_createmenu;  
	showCommandingMenu "#USER:Weap_Sel_0"; 
};

/* ----------------------------------------------------------------------------
BM_fn_SwWeap

Description: Makes the player switch to the desired weapon, with the correct muzzle and firemode.

Parameters: 
	_wid: menu id (Useless?)
	_war: Array  [<muzzle>, <displayName>]  // Second half is useless.
	
Returns:

Note:
	Switching back to a G36A/K won't remember the fire mode
---------------------------------------------------------------------------- */

BM_fn_SwWeap = {
	_wid = _this select 0;
	_war = _this select 1;
	_w = (_war select _wid) select 0;
	player selectWeapon _w;
	_isPw = (_w == primaryWeapon player);
	_isP = ((getNumber (__cfg( _w >> "Type"))) == 2);
	if (_isPw || _isP) then {
		_mstr = "BM_FireModeP";
		if (_w == primaryWeapon player) then {_mstr = "BM_FireMode";};
		_mar = getArray (__cfg(_w >> "modes"));
		if (count _mar == 1) exitWith {};
		_cm = player getVariable [_mstr, (_mar select 0)];
		if (_cm in _mar) then {
			_mid = 0;
			while{(currentWeaponMode player) != _cm} do {_mid = _mid + 1; player action ["SWITCHWEAPON", player, player, _mid];};
		};
	};
};

/* ----------------------------------------------------------------------------
BM_fn_ScrollOff

Description: Deletes the scroll menu

Parameters: 
	
Returns:

---------------------------------------------------------------------------- */

BM_fn_ScrollOff = {
	player setVariable ["BM_WpMenuOn", false];
	showCommandingMenu "";
};

/* ----------------------------------------------------------------------------
BM_fn_checkModesAlt

Description: Checks a weapon's fire modes, removes those reserved to AI.

Parameters: 
	_mar:  Array containing the weapon's firemodes
	_w: String, weaponName
	
Returns:
	Array of player-compatible fire modes
---------------------------------------------------------------------------- */

BM_fn_checkModesAlt = {
	_mar = _this select 0;
	_w = _this select 1;
	{
		_st = (getNumber (__cfg(_w >> _x >> "showtoplayer")) == 0);
		if _st then {
			_mar set [_forEachIndex, -1];
		};
	} forEach _mar;
	_mar = _mar - [-1];
	_mar
};	

/* ----------------------------------------------------------------------------
BM_fn_FselOn

Description: Set player's variable containing the next firemode on the list.
	Variable can be either BM_FireModeP for the pistol or BM_FireMode for the primary weapon.

Parameters: 
	
Returns:

Note:
	The fix for odd configs (G36A/K weapons) is rather ugly.
---------------------------------------------------------------------------- */

BM_fn_FselOn = {
	_isFOn = player getVariable ["BM_FSelOn", false];
	if (_isFOn) exitwith {};
	player setVariable ["BM_FSelOn", true];
	_w = currentWeapon player;
	_pw = (_w == primaryWeapon player);
	_p = ((getNumber (__cfg( _w >> "Type"))) == 2);
	if (!(_pw) && !(_p)) exitWith {};
	_mstr = "BM_FireMode";
	_muz = currentMuzzle player;
	if _p then {_mstr = "BM_FireModeP";};
	_mar = getArray (__cfg(_w >> "modes"));

	if (_muz == "MuzzleFar") then {
		_mar = ["single", "fullauto"];
	} else {
		_mar = [_mar, _muz] call BM_fn_checkModesAlt;
	};					
	_cm = player getVariable [_mstr, (_mar select 0)];
	if !(_cm in _mar) then {_cm = _mar select 0;};
	_id = 0;
	for "_i" from 1 to (count _mar) do {
		if (_cm == (_mar select (_i-1))) exitWith {_id = _i;};
	};
	if (_id >= count _mar) then {_id = 0;};
	_cm = _mar select _id;
	player setVariable [_mstr, _cm];
};

/* ----------------------------------------------------------------------------
BM_fn_FselOff

Description: Switch player's weapon's fire mode as specified in the BM_FireModeP and BM_FireMode variables

Parameters: 
	
Returns:

Note:

---------------------------------------------------------------------------- */

BM_fn_FselOff = {
	_mstr = "BM_FireModeP";
	_w = currentWeapon player;
	if (_w == primaryWeapon player) then {_mstr = "BM_FireMode";};
	_cm = player getVariable _mstr;
	_mid = 0;
	player selectWeapon (currentMuzzle player);
	while{(currentWeaponMode player) != _cm} do {_mid = _mid + 1; player action ["SWITCHWEAPON", player, player, _mid];};
	player setVariable ["BM_FSelOn", false];
};

/* ----------------------------------------------------------------------------
BM_fn_kM

Description: Key Manager. Checks which key is pressed or released and orients towards the relevant function.

Parameters: 
	
Returns:

Note:
	Check with the script gurus what's more efficient: displayEventHandler or waintUntil {inputAction} ?
---------------------------------------------------------------------------- */

BM_fn_kM = {
	_k = _this select 0;
	_s = (_k == (actionKeys 'User19') select 0);
	_f = (_k ==(actionKeys 'User18') select 0);
	if !(_s || _f) exitWith {};
	_u = _this select 1;
	if _s then {
		if _u then {
			call BM_fn_ScrollOn;
		} else { 
			call BM_fn_ScrollOff;
		};
	} else {
		if _f then {
			if _u then {
				call BM_fn_FselOn;
			} else { 
				call BM_fn_FselOff;
			};
		};
	};
};

	
["KeyDown", "[_this select 1, true] call BM_fn_kM;"] call CBA_fnc_addDisplayHandler;
["KeyUp", "[_this select 1, false] call BM_fn_kM;"] call CBA_fnc_addDisplayHandler;

Black Mamba
Posts: 335
Joined: Sun May 27, 2012 12:11 pm

Re: [FA Addon Making] Weapon Selector - beta testing / Colla

Post by Black Mamba »

Changed OP's download link to beta version 0.2.
Seems stable and working, even though there are two non-game breaking bugs that I know of.

Added GitHub repo.

Post Reply