bertram 11 Posted September 27, 2014 (edited) I've been working on a multiplayer gearscript and I'm having a few problems. First off, everyone spawns with the correct gear in their uniform and vest. The problem I'm having is that people spawn with no gear in their backpack, and for some reason people lose their magazines when someone joins the server. I understand there is a global version of addmagazine, addweapon, etc but I'm not sure if I need to use those as my script should be executed globally. I should note that this script works in Arma 2 without issues. (Also as a non-essential issue, I have no idea how to add multiple items in one command the same way you can add magazines for instance.) gear.sqf // ==================================================================================== // // Defined loadouts: // SL - Platoon/Squad Leader // FL - Fireteam Leader // MD - Medic // AR - Auto. Rifleman // AAR - Assistant Auto. Rifleman // LAT - Rifleman (AT) // RIF - Rifleman // MG - Machinegunner // AMG - Assistant Machinegunner // CREW - Vehicle Crewman // PIL - Pilot // // ==================================================================================== private ["_type", "_unit"]; _type = _this select 0; _unit = _this select 1; removeallweapons _unit; removeAllAssignedItems _unit; removebackpack _unit; removeVest _unit; removeUniform _unit; removeHeadGear _unit; removeGoggles _unit; //Defines basic gear for all units, MUST GO LAST IN CASE #define BASIC \ _unit linkItem "ItemMap"; \ _unit linkItem "ItemWatch"; \ _unit linkItem "ItemCompass"; \ _unit linkItem "ACRE_PRC343"; \ _unit additem "AGM_Earbuds";\ _unit additem "AGM_Epipen";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage";\ _unit additem "AGM_Bandage"; //Defines Uniform for all units #define UNIFORM \ _unit adduniform "U_mas_mar_B_IndUniform1_v"; \ _unit addvest "V_mas_mar_PlateCarrier2_rgr_d"; \ _unit addheadgear "H_mas_mar_HelmetBind_v"; switch (_type) do { case "SL": { UNIFORM; _unit addweapon "arifle_mas_m16_gl"; _unit addbackpack "B_mas_AssaultPack_mul"; _unit addmagazines ["30Rnd_mas_556x45_Stanag",14]; _unit addmagazines ["30Rnd_mas_556x45_T_Stanag",4]; (unitBackpack _unit) addmagazineCargo ["1Rnd_HE_Grenade_shell",10]; (unitBackpack _unit) addmagazineCargo ["1Rnd_Smoke_Grenade_shell",3]; (unitBackpack _unit) addmagazineCargo ["1Rnd_SmokeGreen_Grenade_shell",2]; (unitBackpack _unit) addmagazineCargo ["1Rnd_SmokeRed_Grenade_shell",2]; _unit addmagazines ["15Rnd_mas_9x21_Mag",3]; _unit addweapon "hgun_mas_m9_F"; _unit addmagazines ["HandGrenade",2]; _unit addmagazines ["SmokeShell",4]; _unit addmagazines ["SmokeShellGreen",2]; _unit addWeapon "Rangefinder"; _unit linkItem "ItemGPS"; _unit additem "ACRE_PRC148"; BASIC; }; case "FL": { UNIFORM; _unit addweapon "arifle_mas_m16_gl"; _unit addbackpack "B_mas_AssaultPack_mul"; _unit addmagazines ["30Rnd_mas_556x45_Stanag",14]; _unit addmagazines ["30Rnd_mas_556x45_T_Stanag",4]; (unitBackpack _unit) addmagazineCargo ["1Rnd_HE_Grenade_shell",10]; (unitBackpack _unit) addmagazineCargo ["1Rnd_Smoke_Grenade_shell",3]; (unitBackpack _unit) addmagazineCargo ["1Rnd_SmokeGreen_Grenade_shell",2]; (unitBackpack _unit) addmagazineCargo ["1Rnd_SmokeRed_Grenade_shell",2]; _unit addmagazines ["15Rnd_mas_9x21_Mag",3]; _unit addweapon "hgun_mas_m9_F"; _unit addmagazines ["HandGrenade",2]; _unit addmagazines ["SmokeShell",4]; _unit addmagazines ["SmokeShellGreen",2]; _unit addWeapon "Rangefinder"; _unit linkItem "ItemGPS"; BASIC; }; case "MD": { UNIFORM; _unit addweapon "arifle_mas_m16"; _unit addbackpack "B_TacticalPack_mcamo"; _unit addmagazines ["30Rnd_mas_556x45_Stanag",10]; (unitBackpack _unit) additemCargo ["AGM_Bandage",30]; (unitBackpack _unit) additemCargo ["AGM_Epipen",7]; (unitBackpack _unit) additemCargo ["AGM_Morphine",12]; (unitBackpack _unit) additemCargo ["AGM_Bloodbag",4]; _unit addmagazines ["SmokeShell",7]; _unit addmagazines ["SmokeShellGreen",2]; _unit linkItem "ItemGPS"; BASIC; }; case "AR": { UNIFORM; _unit addweapon "LMG_mas_M249a_F"; _unit addbackpack "B_mas_AssaultPack_mul"; _unit addmagazines ["200Rnd_mas_556x45_T_Stanag",5]; _unit addmagazines ["15Rnd_mas_9x21_Mag",3]; _unit addweapon "hgun_mas_m9_F"; _unit additem "AGM_SpareBarrel"; _unit addmagazines ["HandGrenade",2]; _unit addmagazines ["SmokeShell",4]; _unit addmagazines ["SmokeShellGreen",2]; BASIC; }; case "AAR": { UNIFORM; _unit addweapon "arifle_mas_m16"; _unit addbackpack "B_mas_AssaultPack_mul"; _unit addmagazines ["30Rnd_mas_556x45_Stanag",12]; (unitBackpack _unit) addmagazineCargo ["200Rnd_mas_556x45_T_Stanag",2]; (unitBackpack _unit) addmagazineCargo ["30Rnd_mas_556x45_Stanag",6]; _unit addmagazines ["15Rnd_mas_9x21_Mag",3]; _unit addweapon "hgun_mas_m9_F"; _unit addmagazines ["HandGrenade",2]; _unit addmagazines ["SmokeShell",4]; _unit addmagazines ["SmokeShellGreen",2]; BASIC; }; case "LAT": { UNIFORM; _unit addweapon "arifle_mas_m16"; _unit addbackpack "B_mas_AssaultPack_mul"; _unit addweapon "mas_launch_M136_F"; _unit addmagazines ["30Rnd_mas_556x45_Stanag",12]; (unitBackpack _unit) addmagazineCargo ["30Rnd_mas_556x45_Stanag",2]; (unitBackpack _unit) addmagazineCargo ["mas_M136",1]; _unit addmagazines ["HandGrenade",2]; _unit addmagazines ["SmokeShell",4]; _unit addmagazines ["SmokeShellGreen",2]; BASIC; }; case "RIF": { UNIFORM; _unit addweapon "arifle_mas_m16"; _unit addPrimaryWeaponItem "optic_mas_acog_rd"; _unit addbackpack "B_mas_AssaultPack_mul"; _unit addmagazines ["30Rnd_mas_556x45_Stanag",12]; (unitBackpack _unit) addmagazineCargo ["30Rnd_mas_556x45_Stanag",18]; _unit addmagazines ["HandGrenade",2]; _unit addmagazines ["SmokeShell",4]; _unit addmagazines ["SmokeShellGreen",2]; BASIC; }; case "MG": { UNIFORM; _unit addweapon "LMG_mas_m240_F"; _unit addbackpack "B_mas_AssaultPack_mul"; _unit addmagazines ["100Rnd_mas_762x51_T_Stanag",5]; _unit addmagazines ["15Rnd_mas_9x21_Mag",3]; _unit addweapon "hgun_mas_m9_F"; _unit additem "AGM_SpareBarrel"; _unit addmagazines ["HandGrenade",2]; _unit addmagazines ["SmokeShell",4]; _unit addmagazines ["SmokeShellGreen",2]; BASIC; }; case "AMG": { UNIFORM; _unit addweapon "arifle_mas_m16"; _unit addbackpack "B_Carryall_mcamo"; _unit addmagazines ["30Rnd_mas_556x45_Stanag",12]; (unitBackpack _unit) addmagazineCargo ["100Rnd_mas_762x51_T_Stanag",3]; (unitBackpack _unit) addmagazineCargo ["30Rnd_mas_556x45_Stanag",6]; _unit addmagazines ["HandGrenade",2]; _unit addmagazines ["SmokeShell",4]; _unit addmagazines ["SmokeShellGreen",2]; BASIC; }; case "CREW": { _unit adduniform "U_mas_mar_B_IndUniform1_v"; _unit addvest "V_mas_mar_ChestrigB_rgr"; _unit addheadgear "H_HelmetCrew_I"; _unit addweapon "arifle_mas_m4"; _unit addmagazines ["30Rnd_mas_556x45_Stanag",6]; _unit addmagazines ["SmokeShell",2]; _unit addmagazines ["SmokeShellGreen",1]; _unit additem "ACRE_PRC148"; BASIC; }; case "PIL": { _unit adduniform "U_mas_mar_B_pilot"; _unit addvest "V_mas_mar_Rangemaster_belt"; _unit addheadgear "H_PilotHelmetHeli_O"; _unit addweapon "arifle_mas_mp5"; _unit addPrimaryWeaponItem "optic_Aco_smg"; _unit addmagazines ["30Rnd_mas_9x21_Stanag",6]; _unit addmagazines ["SmokeShell",2]; _unit addmagazines ["SmokeShellGreen",1]; _unit additem "ACRE_PRC148"; BASIC; }; }; Script is called in the init if the unit. id = ["CASE", this] call compile preprocessFileLineNumbers "gearscript\gear.sqf"; Case being replaced with any defined case in the gear script. Edited September 27, 2014 by Bertram Share this post Link to post Share on other sites
Beerkan 71 Posted September 27, 2014 Solved... Jona-s-Easy-Redress-Functions Edit as you need Share this post Link to post Share on other sites
bertram 11 Posted September 27, 2014 (edited) Solved... Jona-s-Easy-Redress-FunctionsEdit as you need I will probably end up using that if I can't figure my gear script out, but I would like to try and work out the kinks in this. I managed to get items being added to the backpack properly by using "addMagazineGlobal", "addWeaponGloabal", etc. However now, the gear in the backpack doubles when a new player joins so I suspect either something in my script is local and being executed every time a player joins. I'm still not really sure of the issue still but I'm trying to work it out. The thing I can't really understand is why this only applies to the backpacks of a unit. The gear in the uniform and vest work perfectly. Edited September 27, 2014 by Bertram Share this post Link to post Share on other sites
Beerkan 71 Posted September 27, 2014 I will probably end up using that if I can't figure my gear script out, but I would like to try and work out the kinks in this.I managed to get items being added to the backpack properly by using "addMagazineGlobal", "addWeaponGloabal", etc. However now, the gear in the backpack doubles when a new player joins so I suspect either something in my script is local and being executed every time a player joins. I'm still not really sure of the issue still but I'm trying to work it out. The thing I can't really understand is why this only applies to the backpacks of a unit. The gear in the uniform and vest work perfectly. in your script replace adduniform with forceadduniformSee also addItemToUniform addItemToBackpack addItemToVest Share this post Link to post Share on other sites
bertram 11 Posted September 27, 2014 I did some research and found out that the init of a unit is re-executed when a player JIPs resulting in gear duplicating. All entries reporting this issue on the bug tracker seem to say that this is not a bug and by design. This is really frustrating as there doesn't seem to be an obvious way to execute a script or call a function in a unit's init in the same way as Arma 2. I turned my script into a function and it is now called via ["CASE", this] call GEARSCRIPT; This still yields the same locality issues. Share this post Link to post Share on other sites
iceman77 19 Posted September 27, 2014 If it's duplicating gear when someone JIPs, then the code is being ran for all clients. Use if (isDedicated) exitWith {}; waitUntil {!isNull player}; if (!local player) exitWith {}; at the top of your loadout script(s) and see if that helps the duplicate gear issue. Or if (isDedicated) exitWith {}; waitUntil {!isNull player}; if (local player) then {["CASE", this] call GEARSCRIPT;}; Share this post Link to post Share on other sites
bertram 11 Posted September 30, 2014 If it's duplicating gear when someone JIPs, then the code is being ran for all clients. I'll try this as soon as I get a chance. Any idea why these locality issues don't happen with this gearscript in Arma 2? Share this post Link to post Share on other sites
bertram 11 Posted October 11, 2014 (edited) Putting if (isDedicated) exitWith {}; around my code makes the gear script work for initial spawns, and JIPs do not cause the gear to be duplicated. However, JIPs do not get the gear. As I mentioned before, it seems like there are locality issues with the unit initializations in multipalyer in Arma 3. I am not really sure how to get Arma 3 unit inits to act as the Arma 3 ones or make the my script be run locally for all players including JIPs. Does anyone know how I might be able to call a function with BIS_fnc_MP and my case parameters? Edited October 11, 2014 by Bertram Share this post Link to post Share on other sites
iceman77 19 Posted October 11, 2014 (edited) Does anyone know how I might be able to call a function with BIS_fnc_MP and my case parameters? [ [ [ "CASE", player ] , GEARSCRIPT ], "BIS_fnc_Call", player, true ] call BIS_fnc_MP; Edited October 11, 2014 by Iceman77 Share this post Link to post Share on other sites
bertram 11 Posted October 12, 2014 (edited) I put [ [ [ "CASE", this ] , GEARSCRIPT ], "BIS_fnc_Call", this, true ] call BIS_fnc_MP; in the init of my units and the script was not even called in multiplayer. I'm positive I'm implementing it wrong though. Edited October 15, 2014 by Bertram Share this post Link to post Share on other sites
menelaos16 10 Posted October 15, 2014 I'm a bit new to making scripts in Arma 3 (did some Arma 2), and I've noticed some of these locality issues. Is there a fix for this? Share this post Link to post Share on other sites
bertram 11 Posted October 16, 2014 I've continued to mess with BIS_fnc_mp being used to call the gear script function and I'm still unable to get it to work in multiplayer. Putting [ [ [ "CASE", this ] , GEARSCRIPT ], "BIS_fnc_Call", this, true ] call BIS_fnc_MP; works fine in singleplayer but not even remotely on a dedicated server. I even made a test function that just displays a hint in case the actual contents of my gear script was messed up and still nothing is called by BIS_fnc_MP. Share this post Link to post Share on other sites
menelaos16 10 Posted October 17, 2014 Is there a way to make JIP run only locally for Arma 3? Share this post Link to post Share on other sites
bertram 11 Posted October 17, 2014 Is there a way to make JIP run only locally for Arma 3? There probably is, but I've exhausted my abilities trying to figure it out. Share this post Link to post Share on other sites
dreadedentity 278 Posted October 17, 2014 Is there a way to make JIP run only locally for Arma 3? What do you mean? init.sqf runs for all JIP players so it already runs locally Share this post Link to post Share on other sites
bertram 11 Posted October 17, 2014 The problem we seem to be having is that unit initializations are executed globally and are re-executed when someone JIPs. While running a script in the init.sqf makes it local it doesn't really suit my needs as I can't have parameters that are different for each unit set in the init.sqf without naming every unit and executing the gear script by the name of the unit in the init.sqf, which would just be too ridiculous and defeat the purpose of a simple gear script. Share this post Link to post Share on other sites
jshock 513 Posted October 17, 2014 The problem we seem to be having is that unit initializations are executed globally and are re-executed when someone JIPs. While running a script in the init.sqf makes it local it doesn't really suit my needs as I can't have parameters that are different for each unit set in the init.sqf without naming every unit and executing the gear script by the name of the unit in the init.sqf, which would just be too ridiculous and defeat the purpose of a simple gear script. I'm just going to throw this out there, it seemed to solve some issues I had similar to this way back a few months ago, put it above all the rest of the code in the init.sqf: if (!isServer && isNull player) then {isJIP=true;} else {isJIP=false;}; if (!isDedicated) then { waitUntil {!isNull player && isPlayer player}; sidePlayer = side player; }; Share this post Link to post Share on other sites
bertram 11 Posted October 17, 2014 I'm not actually running any scripts or functions I'm having issues with through the init.sqf but I'll try it anyway. Share this post Link to post Share on other sites
TKTom 10 Posted October 17, 2014 The reason your bis_fnc_mp calls aren't working is your implementation of the third parameter (call where the unit is local.) This is being evaluated on the fnc_mp call NOT the gear.sqf call. I would suspect that your JIPs are joining into a slot that was not AI before? Thereby creating the character. When you called your fnc mp this char didn't exist, so it is trying to call gear.sqf where objnull is local (nowhere, it falsifies almost any boolean evaluation). Consider setting the mp call to run for all clients on jip (TRUE in third param) and operating only on a local unit. Share this post Link to post Share on other sites
bertram 11 Posted October 17, 2014 I think I see what you're getting at. I won't be able to test it out for a few hours but would your suggestion look something like this? [ [ [ "CASE", this ] , GEARSCRIPT ], "BIS_fnc_Call", this, true, true ] call BIS_fnc_MP; Share this post Link to post Share on other sites
TKTom 10 Posted October 17, 2014 (edited) To follow on from my previous input. I would recommend two changes to the way you are going about solving this problem. 1. DONT call the script from init field or init.sqf: I find both of the above to be highly unreliable (last time I checked, which was perhaps 6-8 months ago.) Quoted from https://community.bistudio.com/wiki/Functions_Library_%28Arma_3%29#Initialization_Order: Initialization OrderWhen mission is starting, its components are initialized in the following order: Functions with recompile param set to 1 are recompiled Functions with preInit param set to 1 are called (client + server) Object Init Event Handlers are called Object initialization fields are called init.sqs is executed in singleplayer init.sqf is executed in singleplayer Persistent multiplayer functions are called (client only) Modules are initialized initServer.sqf is executed (server only) initPlayerLocal.sqf is executed initPlayerServer.sqf is executed (server only) Functions with postInit param set to 1 are called (client + server) "BIS_fnc_init" variable is set to true init.sqs is executed in multiplayer init.sqf is executed in multiplayer Notice init.sqf shifts depending on single or multiplayer mission, I also believe that it will fire for any player that joins within the first 30 seconds (maybe 3 minutes, some time anyway) of the mission. INSTEAD: Call from a reliable join in progress structure. For instance, initServer.sqf executes ONCE on the server right at the start of the mission. Set up initServer.sqf to include a line: [[nil,"JIPinit.sqf"],"BIS_fnc_execVM",true,true] call BIS_fnc_MP; This executes a script called "JIPinit.sqf" on ANY client that joins (red bit) every time they join (blue bit) and ALSO once on the server. But ONLY ONCE for each time they join (and NEVER again on the server.) This is a reliable structure from which to launch your script. You might be thinking at this point "My script won't call correctly from this structure", well that's my next suggestion. 2. REMOVE the "CASE" parameter: It seems to me that the "CASE" is only determined by the role of the character. Why not use the typeOf the character instead? This is the classname seen in the upper corner of the unit placement box in the editor. You can change your switch section to: switch (typeOf _this) do { case "B_Soldier_TL_F": {<equipment stuff>}; }; Which reduces the parameters you need to just the unit that the script needs to work on. Now you can call your script in the initServer.sqf like this: { if( side _x == west && local _x) then { _x execVM "gear.sqf"; }; } forEach allUnits; // Or whatever you need to identify the men in the group (units group player) is probably better, but you can work it out And then in the JIPinit.sqf like this: player execVM "gear.sqf"; Obviously, these are suggestions that are how I would personally go about doing this. You can feel free to think them inadequate. EDIT: Also, you worked out why the backpack stuff wasn't working, right? addBackpackCargo is for adding BACKPACKS to VEHICLES (as cargo). addItemToBackpack is for adding ITEMS to BACKPACKS Edited October 17, 2014 by TKTom Share this post Link to post Share on other sites
bertram 11 Posted October 17, 2014 (edited) Your post really helped TKTom, I have it working nearly exactly how I want it. I can deal with this but the only thing is that anyone that has died, aborts, and re-joins in a role without leaving the server they don't get their gear. I can have people leave fully before re-spawning that way but it works well otherwise. Also I'm not having a backpack issue. Edited October 17, 2014 by Bertram Share this post Link to post Share on other sites