Jump to content
Undeceived

Weapon Pool duplicates itself in campaign progress

Recommended Posts

Hi guys!

I'm using the weapon pool in my campaign but I'm experiencing a weird bug... When I add something to the weapon pool (e.g. one rifle), in the next mission there will be 2 available in the briefing. In the third one there will be 4 rifles, and so on...

How can that happen?! The only time I interacted with the WP was adding the rifle to it in the first mission ( addWeaponPool ["srifle_EBR_F",1]; ), but that was it.

Do you have an idea why it duplicates itself? Am I doing something wrong? Any hint would certainly help a lot - thank you!

Share this post


Link to post
Share on other sites

I never really interacted with the weapon pool, but maybe adding a check with queryWeaponPool would help? Obviously a bit tedious, but a temporary workaround nonetheless. The BIKI documentation itself is a bit lacking unfortunately.

Share this post


Link to post
Share on other sites

I looked at the BIS campaign, they call these 3 lines before adding anything to the pool at the end of a mission:

clearWeaponPool;
clearMagazinePool;
clearItemPool;

Try that if you haven't done it already, otherwise I think it would double up.

Share this post


Link to post
Share on other sites

Tryteyker, no matter how tedious it is, I'd do it. :D

But the query commands seem to be broken too, at least according to my tests... If anyone got them working, please tell me how you did it!

AZCoder, could you please show me an example in BIS campaign? In which scripts they use these clear commands before adding stuff to the pool?

I'm surprised by the use because as far as I know (and in my campaign as well) these clearing commands completely erase the pool! So how do they do that...?

Share this post


Link to post
Share on other sites

I think the query command only works when running in campaign mode, or maybe it doesn't work at all, not sure.

If you simply want that one rifle to appear once per mission, I'd suggest just clearing the pool and adding it back at the end of each mission. Or check weapons player at the end, and if the player has it, add it back into the pool (after clearing).

The BIS function is in a shared folder in the 'epa' [first] campaign => \missions_f_epa\Campaign_shared\Functions\fn_camp_onMissionExit.sqf

There is a lot going on in that file, and lots of custom 'campaign' functions are called. It appears they are pulling together different possibilities, like weapons and ammo left in vehicles, storing into global variables, and then clearing out the pools and rebuilding them as the mission exits. So in a similar fashion, you could check 'vehicle player' at the end, and any other vehicle you want, save them into an array or saveVar on them, clear the pool, then re-add what you want into it. And it is tedious for sure.

This may be more complex than what you need, and please feel free to ignore what I wrote below if it's off-track, but I wrote a couple functions about 3 years ago that saves all weapons, ammo, gear, and packs for a list of units. It has nothing to do with pools, but if you wanted to persist the exact same items on each character from mission to mission, this should do it.

First is the save used at end of mission:

private ["_unit","_mags","_weaps","_gear","_pack"];

AZC_GEAR_ARRAY = [];

{
if (!(_x isKindOf "MAN")) exitWith {};
_unit = format["%1",_x];
_mags = magazines _x;
_weaps = weapons _x;
_pack = typeOf unitBackpack _x;
_gear = [_unit,_mags,_weaps,_pack];
AZC_GEAR_ARRAY set [count AZC_GEAR_ARRAY, _gear];
} forEach _this;

saveVar "AZC_GEAR_ARRAY";

Example use: [unit1,player,some_dude] call AZC_fnc_saveGear;

Here is the load function. As written, you would use it at the start of a mission to ensure each "saved" character has

the same exact loadout as before. Word of caution: it has to execute before the briefing pops up.

private ["_unit","_mags","_weaps","_pack"];

if (!(isNil "AZC_GEAR_ARRAY")) then
{
{
 		_unit 	= call compile (_x select 0);  // revert from string back to object name
	_mags 	= _x select 1;
	_weaps 	= _x select 2;
	_pack 	= _x select 3;

	if ((isNil "_unit") || (isNil "_mags") || (isNil "_weaps")) exitWith { diag_log format["unit: %1, mag: %2, weap: %3", _unit,_mags,_weaps] };
	removeAllItems _unit;
	removeAllWeapons _unit;
	removeBackpack _unit;
	{ _unit addMagazine _x } forEach _mags;
	{ _unit addWeapon _x } forEach _weaps;
	if (count(toArray(_pack)) > 0) then
	{
			_unit addBackpack _pack;
	};
	_unit selectWeapon (primaryWeapon _unit);
} forEach AZC_GEAR_ARRAY;
};

I would highly recommend pre-compiling these into functions (or add them into CfgFunctions).

AZC_fnc_loadGear = compileFinal preprocessFileLineNumbers;

Then use the 'call' statement to force execution before the thread continues.

call AZC_fnc_loadGear;

After which I would place the createDiaryRecord commands so that the gear/weapons are loaded before the briefing screen is shown. Or hopefully. It did work for me in Arma 2.

Share this post


Link to post
Share on other sites

Thanks, AZCoder. Unfortunately none of the ideas worked or gave me an idea for a workaround... No matter what you (resp. I) do - the "jump" from one mission to the next causes the WP to duplicate itself.

And the query commands didn't work too, even in the campaign environment. Even though I have added stuff into the WP, a query command always returns 0.

I uploaded a mini campaign with only the relevant scripts. I would highly appreciate it if you guys could take a look at it. Maybe you can find a way to prevent this bug (or confirm that it exists and that there's no workaround - so I can create a ticket in the AFT).

Just give the campaign a run. I added some hints to explain, what is happening.

Thanks!

http://www.mediafire.com/download/dyt1t19ncnzqz50/WPcampaign.7z

Edited by Undeceived

Share this post


Link to post
Share on other sites

I ran the test campaign, verified the problem. I reverted back to mission 2, entered "clearWeaponPool" in debug, continued to mission 3, the pool was empty!

I again reverted to mission 2, 1 rifle as expected. clearWeaponPool. Then addWeaponPool ["srifle_EBR_F",1]; and continued to mission 3. There was 1 rifle as I expected.

So add those commands in that order before ending mission 2, rebuild the pbo and see what happens.

Share this post


Link to post
Share on other sites

It should work like you did it in the debug console. But I still didn't get the idea behind it, I think. :o

The WP will not only consist of the one rifle, but of dozens of weapons, magazines and items which the player can collect. And since I don't know which gear he will collect, I can't clear the WP and put stuff in the pool, as you suggested. Or am I missing the point completely? (could very well be because I'm pretty "worn out" because of that problem already. :D :D).

IndeedPete, thx for the confirmation!

Share this post


Link to post
Share on other sites

What about a template for your base weapon pool, then a function that gets the current player equipment and subtracts it from the WP? After that you clear and add using your modified WP. Just an idea.

Share this post


Link to post
Share on other sites

In my long winded reply earlier, I was trying to suggest doing like BIS did, which is to collect everything the player may have picked up, store it in a global variable as an array, clear the pools, then add everything back into the pool from the global array. The global array will persist between missions with the saveVar "VARNAME" command, in the event that you want to pull from the array in the next mission (which is what my 2 code samples earlier show). As a reminder, the first sample I posted earlier shows you how to collect everything on any given unit (as tryteyker is suggesting) ... although my code was written for A2 and I'm not 100% sure if it's quite right for A3 due to inventory changes to the game.

I would throw something together for you, but time is limited right now and I usually work late, sucking the life force out of me :eek:

Share this post


Link to post
Share on other sites

Thanks, guys, for your input!

AZCoder - ok, but how can I know (and then remove) from that array what the player has taken out of the pool for himself and his group members for the next mission?

If I'm not mistaken, this is what tryteyker is suggesting, am I right?

Damn - now why is my scripting knowledge so limited! :D

Edited by Undeceived

Share this post


Link to post
Share on other sites

Well since each unit can only have one primary weapon each, you just use commands like primaryWeapon, primaryWeaponMagazine, secondaryWeapon and secondaryWeapnMagazine to save it all, then compare it to the template and subtract from the template. AZCoder provided some example code on the first page as to how it can look like (although using ArmA 2 code, so it could probably be done more efficient considering these commands got added in ArmA3, atleast some of them)

Share this post


Link to post
Share on other sites

No, that's not the problem. I can get all equipment and save it as array, I have some scripts for that - Larrow for example helped me to retrieve stuff from containers in crates (backpacks, uniforms and vests) (http://forums.bistudio.com/showthread.php?182394-Detect-container-its-content-in-container) and bardosy helped me with the rest (http://forums.bistudio.com/showthread.php?177988-Items-and-Weapons-Saving).

The complicated for me is now that part to compare it to the template and subtract from the template. I think I still didn't get what you mean with template. :)

Share this post


Link to post
Share on other sites

Template is just the weapons you have available from Mission 1 - to compare the current weapons with thesse you started with, use in. I cant really give you a good example, CS course starting soon so time is limited :P But I'll edit in an example when I get home if you need it.

Share this post


Link to post
Share on other sites

Yeah, I'd appreciate it, as I'm quite a noob when it comes to arrays, etc.. :D Thanks, tryteyker!

Share this post


Link to post
Share on other sites

I'm assuming you already have a template and a function, both saving their respective results in a global variable. Lets just say that the template is DCV_WEAPON_TEMPLATE and the current gear is DCV_CURRENT_GEAR.

I'm going to be using getVariable a lot as I assume your saving scripts already utilize some nameSpace (in this example profile as it's the easiest to use)

// We run a basic loop that will iterate through the current gear array, and compare it to the weapon template.

for "_w" from 0 to ((count DCV_CURRENT_GEAR)) do { // Counting the amount of things we have in our current gear, so the loop doesn't run into errors along the way.
_template = profileNameSpace getVariable DCV_WEAPON_TEMPLATE; // Fetching the template from profileNamespace.
_gearsel = DCV_CURRENT_GEAR select _w; // Selecting the current gear piece (whether that be a weapon or magazine, aslong as it's a string)

   if (_gearsel in _template) then { // Since we have the template on hand and selected a piece of the current gear, we simply compare it and subtract if it's in there.
       _template = _template - _gearsel;
   };

       with profileNameSpace do { // Here we set DCV_WEAPON_TEMPLATE to the new variable. It's bad to do it inside the loop, but we're using a local variable here so it's necessary.
           DCV_WEAPON_TEMPLATE = _template;
       };
};

This is really untested and I just wrote it up in a few minutes, You'll have to see if it works, but just make sure your current gear and template are named properly etc. I suggest saving this to CfgFunctions aswell so you'll be able to call it anywhere.

Share this post


Link to post
Share on other sites

Thanks, tryteyker.

I'm still trying to understand it :j: :

This script is launched after the briefing of mission 2, is that right?

So it

  • checks what the weapon pool was between mission 1 and mission 2
  • then checks what the player has taken from the pool in the briefing of mission 2
  • and then substracts the taken equipment from the pool.

Is that right? :o

And after that I have to clear the whole pool and add DCV_WEAPON_TEMPLATE to the pool at the end of mission 2 again - together with the stuff, which the player has collected in mission 2. Is that correct?

EDIT:

I'm trying to implement the above system, but when I use your script, the following error appears: Error Undefined variable in expression: _gearsel I showed you the exact position of the error in the script (see below).

I changed your script a little bit by replacing the profileNamespace code by simple saveVar (I want to avoid the profileNamespace). It currently looks like this:

(btw. I'll launch the script three times. 1: for the weapons, 2: for the mags, 3: for the items.)

//POOL_MAGAZINES is the template for the magazines. It was saveVar'd in the previous mission.
MAGAZINES_PLAYER = magazines player; //These are the actual magazines of the player, after having taken stuff from the briefing weapon pool.

for "_w" from 0 to ((count MAGAZINES_PLAYER)) do {
_template = POOL_MAGAZINES; 
_gearsel = MAGAZINES_PLAYER select _w; 

   if (_gearsel in _template) then {   //This is the line which returns the error.
       _template = _template - _gearsel;
   };

POOL_MAGAZINES = _template;
};

saveVar "POOL_MAGAZINES";

Why is that undefined? I did define MAGAZINES_PLAYER at the beginning of the script, didn't I?

I feel that the solution really is near!!! :yay:

Edited by Undeceived

Share this post


Link to post
Share on other sites

Unless you're giving the player the option to choose weapons in mission 1, you're pretty much correct. The thing is, you'll have to subtract guns/magazines taken on mission 1 from the mission 2 weapon pool aswell, so these scripts will technically have to be run before the player can access the mission 2 weapon pool.

As for the script itself, it's simply telling you that magazines_player select _w is nonexistant. Try using (count MAGAZINES_PLAYER) - 1 in the script, that should prevent it. count is actually 1-index based, whilst the for loop is starting 0-index based. Alternatively, use from 1 to ((count MAGAZINES_PLAYER) to accomodate the count command.

Share this post


Link to post
Share on other sites

tryteyker, the script still gives an error. This time one line later. :)

Error -: Type String, expected Number,Array

MAGAZINES_PLAYER = magazines player;

for "_w" from 0 to ((count MAGAZINES_PLAYER) -1) do {
_template = POOL_MAGAZINES; 
_gearsel = MAGAZINES_PLAYER select _w; 

   if (_gearsel in _template) then {
       _template = _template - _gearsel; //The error position is right after the - (probably means the _gearsel).
   };

POOL_MAGAZINES = _template;
};

saveVar "POOL_MAGAZINES";

Any idea how to solve this?

Thanks!

Share this post


Link to post
Share on other sites

["30Rnd_65x39_caseless_green","30Rnd_65x39_caseless_green","30Rnd_65x39_caseless_green"]

Share this post


Link to post
Share on other sites

And MAGAZINES_PLAYER is also an array with strings, right?

Share this post


Link to post
Share on other sites

Yes, that's right.

["nameofmag","nameofmag","nameofmag2","nameofmag3"] (etc...)

Share this post


Link to post
Share on other sites

And you're sure it lies in if (_gearsel in _template)? The error, I mean.

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

×