Tuesday 15 October 2013

Auomatic Gear Box - Part 2

EDIT: Sorry for the late post, the coding used within the scripts was slightly incorrect and this lead to a long time trying different solutions until it finally clicked. Sorry for any inconvenience, the next post should be up on time, with a bit of luck!

Last time we looked at adding in the script to manually assign gear to a unit, this was done through the use of if statements. Now we will be looking at making the whole thing look better by adding in an animation. This will be a simply tutorial on the basic animation command. A full look into the Animation Viewer will be up at a later date. So now onto the animation. We will be using a simple animation that looks as though the unit is altering his scope mount. The animation we are using is called:

"DismountOptic"

This animation is about 4 seconds long, so won't intrude on our gameplay much. Now we have the animation, it's time to look at the command to use it. The easiest way to test this is in the debug console. Simply start up the editor, get into the map, hit pause then type into the box on the top right [Shown below]

The line of code we will be using is this:

unitname playMoveNow "AnimationName";

Breaking it down, we have unitname, this corresponds to whatever unit you want to perform the animation. playMoveNow is the main command. This, quite literally, forces the animation to be played. "AnimationName" refers to the classname of the animation, for example, our "DismountOptic" name.

Lets practice this in the editor. If you named your unit then simply type the command above, subbing in your unit name and the animation name, it should look similar to this:

s_marksman playMoveNow "DismountOptic";

Didn't give your unit a name? Don't worry, simply replace the unit name with player. We can see how this can be used later to save us some time:

player playMoveNow "DismountOptic";

So now we can force a single unit to perform an animation. But what if we want an entire squad of players to do it? As mentioned before, we can simply sub in the unit name for player. This will result in any non-NPC performing the action. But there is one issue. What if we have NPC's or AI units? They won't perform the action as they aren't players. This is where we will need to further out coding skills a little. We will be looking at forEach loops:

forEach loops are great ways to force certain actions upon an entire range of units, without having to copy and paste the code over and over again. It will look something like this:

{ code/commands } forEach Array;

Breaking that down, we have a code/command area, this is where we will right all the coding to be performed. forEach is the main command that specifies to perform the code/command segment on the array. Array, arrays are a data storage method, it's easiest to think of them like tables in a database or spreadsheet. We can create arrays very easily in game using a single line of code. The Array relates to the group of units or objects that we wish the action to be performed on. But how do we create arrays?

ARRAYNAME = [name1, name2, name3];

It is that simply. All we have to do is sub in the values and put this code onto any unit's INIT line or even the *.sqf file itself (but more on those in part 3). An example to create a small team array could be:

TEAM = [s_marksman, s_rifleman, s_engineer, s_medic];

This will create an array containing those four units. Now we can implement this in our forEach loop:

 { code/commands } forEach TEAM;

Let's test this with the animation. Let's add four units then call them s_marksman, s_engineer, s_medic and s_rifleman. Now under any of the units INIT line. Type:

TEAM = [s_marksman, s_rifleman, s_engineer, s_medic];

That's created our array. So start up the game and inside the debug line we can type this forEach loop:

{ _x playMoveNow "DismountOptic" } forEach TEAM;

_x is a local variable, or temporary variable that represents each unit of the array. In short, that line of code will be performed on every unit within the TEAM array, regardless of whether they are a human player or not.

So they should all have performed the action, if they didn't try setting up a trigger with the same code over the units, when they move it should trigger the animation.

Now for an event handler. This will allow us to add an action to any object that when selected will call our animation and gear change code. This is that code:

objectname addAction ["ActionName","Code",[ARRAY],1,false,true,"","(_target distance _this) < 3"];

Let's break down the main components. objectname refers to the name of the object to have the action added to. addAction is the main command that adds the action parameters to the object. "Action name" refers to the text that will be displayed under the action menu of the item. Code is where we will be adding our re-arm coding. [ARRAY] refers to the array that the action will be visible to. "(_target distance this) < 3" refers to the the minimum distance that the action will appear from, in this case, a 3 metre diameter.

Now lets create the script. First off, make sure that an object is placed, the best object would be an ammo box from Unit->Empty->Ammo->"Object, make sure to name it Box1.

Add this line to the gearbox's INIT line:

Box1 addAction ["Re-Arm","Code",[TEAM],1,false,true,"","(_target distance _this) < 3"];

What we are going to do now is create the *.sqf file, we are going to look at this now instead of in part 3 because it just becomes too messy otherwise. Best to get into good practices now rather than make errors later.

First things first, we will need to save the mission. This is so we have somewhere to actually place the files. At the top of the editor we can see the buttons for saving, If we highlight them then a small tool-tip appears explaining what it does. We want the Save As option. This will open a new dialog, select user missions and give it a name. Now our mission is saved we can add the script into it's directory. Alt+Tab or close ArmA III and go open file explorer. Head to this location:

C:\Users\XXX\Documents\Arma 3\XXX\missions\YOURMISSION
 
C:\Users\XXX\Documents\Arma 3 - Other Profiles\XXX\YOURMISSION

If you create a second profile, then you will need to navigate to the Other profiles directory to find your mission. Once here, there should be a mission.sqm file. All we need to do is copy or save our *.sqf file (Created in notepad or another text editor) into one of our mission folders here:

Can't remember the actual file? All the coding will be at the bottom of this post. So now for the final part, to call the script. Go back to ArmA III or re-open it. From here go to the Box1 INIT line and change the code section to something similar to this:

Box1 addAction ["Re-Arm","DynamicReam.sqf",[TEAM],1,false,true,"","(_target distance _this)<3"];

Simply change to "DynamicReam.sqf" to whatever the name of the *.sqf file is. Now that we have that done. Run the level and check that the action is visible when you approach the box like this:
Hopefully when the action is selected the unit's gear changed and the animation was performed. If it didn't check here for all the coding used in this post.
_______________________________________________________________________
playMoveNow command
unitname playMoveNow "AnimationName";

 forEach loop

{ code/commands } forEach Array;


Creating simple arrays
ARRAYNAME = [name1, name2, name3];

Basic array example
TEAM = [s_marksman, s_rifleman, s_engineer, s_medic];

 forEach loop example
{ _x playMoveNow "DismountOptic" } forEach TEAM;

 addAction command
objectname addAction ["ActionName","Code",[ARRAY],1,false,true,"","(_target distance _this) < 3"];  

 addAction example
Box1 addAction ["Re-Arm","DynamicReam.sqf",[TEAM],1,false,true,"","(_target distance _this)<3"]; 

Example paths for saved missions
C:\Users\XXX\Documents\Arma 3\XXX\missions\YOURMISSION
C:\Users\XXX\Documents\Arma 3 - Other Profiles\XXX\YOURMISSION
 
 Full *.sqf file for an automatic gearbox

 Event Handler
Box1 addAction ["Re-Arm","DynamicReam.sqf",[TEAM],1,false,true,"","(_target distance _this)<3"];

Main file
{ _x playmoveNow "DismountOptic"} forEach TEAM
sleep 3;
if (IsPlayer s_marksman) then
{
    removeHeadgear s_marksman;
    removeVest s_marksman;
    removeGoggles s_marksman;
    removeBackpack s_marksman;
    removeAllWeapons s_marskman;
    removeUniform s_marksman;
   
    s_marksman addheadgear "H_Watchcap_camo";
    s_marksman addUniform "U_I_CombatUniform";
    s_marksman addVest "V_PlateCarrierIA1_dgtl";
    s_marksman addBackpack "B_AssaultPack_ocamo";
    s_marksman addGoggles "G_Shades_Black";

    s_marksman addMagazine "20Rnd_762x51_Mag";
    s_marksman addMagazine "20Rnd_762x51_Mag";
    s_marksman addMagazine "20Rnd_762x51_Mag";
    s_marksman addMagazine "20Rnd_762x51_Mag";
    s_marksman addMagazine "20Rnd_762x51_Mag";
    s_marksman addWeapon "srifle_EBR_MRCO_pointer_F";
    s_marksman addPrimaryWeaponItem "muzzle_snds_B";
    s_marksman addMagazine "16Rnd_9x21_Mag";
    s_marksman addMagazine "16Rnd_9x21_Mag";
    s_marksman addWeapon "hgun_P07_snds_F";
};

if (IsPlayer s_rifleman) then
{
    removeHeadgear s_rifleman;
    removeVest s_rifleman;
    removeGoggles s_rifleman;
    removeBackpack s_rifleman;
    removeAllWeapons s_rifleman;
    removeUniform s_rifleman;

    s_rifleman addheadgear "H_Booniehat_dgtl";
    s_rifleman addUniform "U_I_CombatUniform";
    s_rifleman addVest "V_PlateCarrierIA1_dgtl";
    s_rifleman addBackpack "B_Carryall_oli";
    s_rifleman addGoggles "G_Tactical_Clear";

    s_rifleman addMagazine "30Rnd_556x45_Stanag";
    s_rifleman addMagazine "30Rnd_556x45_Stanag";
    s_rifleman addMagazine "30Rnd_556x45_Stanag";
    s_rifleman addMagazine "30Rnd_556x45_Stanag";
    s_rifleman addMagazine "30Rnd_556x45_Stanag";
    s_rifleman addWeapon "arifle_Mk20_MRCO_F";
    s_rifleman addPrimaryWeaponItem "muzzle_snds_M";
    s_rifleman addMagazine "16Rnd_9x21_Mag";
    s_rifleman addMagazine "16Rnd_9x21_Mag";
    s_rifleman addWeapon "hgun_P07_snds_F";
};

if (IsPlayer s_spot) then
{   
    removeHeadgear s_spot;
    removeVest s_spot;
    removeGoggles s_spot;
    removeBackpack s_spot;
    removeAllWeapons s_spot;
    removeUniform s_spot;

    s_spot addheadgear "H_Cap_grn_BI";
    s_spot addUniform "U_I_GhillieSuit";
    s_spot addVest "V_BandollierB_oli";
    s_spot addBackpack "B_AssaultPack_khk";

    s_spot addMagazine "5Rnd_127x108_Mag";
    s_spot addMagazine "5Rnd_127x108_Mag";
    s_spot addMagazine "5Rnd_127x108_Mag";
    s_spot addMagazine "5Rnd_127x108_Mag";
    s_spot addMagazine "5Rnd_127x108_Mag";
    s_spot addWeapon "srifle_GM6_SOS_F";
    s_spot addPrimaryWeaponItem "acc_Pointer_IR";
    s_spot addMagazine "16Rnd_9x21_Mag";
    s_spot addMagazine "16Rnd_9x21_Mag";
    s_spot addWeapon "hgun_P07_snds_F";
   
};

if (IsPlayer s_medic) then
{

    s_medic addHeadgear "H_Cap_blk_Raven";
    s_medic addUniform "U_I_CombatUniform_tshirt";
    s_medic addVest "V_PlateCarrierIA1_dgtl";
    s_medic addBackpack "B_AssaultPack_rgr_ReconMedic";
    s_medic addGoggles "G_Tactical_Black";


    s_medic addMagazine "30Rnd_556x45_Stanag";
    s_medic addMagazine "30Rnd_556x45_Stanag";
    s_medic addMagazine "30Rnd_556x45_Stanag";
    s_medic addMagazine "30Rnd_556x45_Stanag";
    s_medic addMagazine "30Rnd_556x45_Stanag";
    s_medic addWeapon "arifle_Mk20C_F";
    s_medic addPrimaryWeaponItem "optic_MRCO";
    s_medic addPrimaryWeaponItem "muzzle_snds_M";
    s_medic addMagazine "16Rnd_9x21_Mag";
    s_medic addMagazine "16Rnd_9x21_Mag";   
    s_medic addMagazine "16Rnd_9x21_Mag";
    s_medic addWeapon "hgun_P07_snds_F";"

}

if (IsPlayer s_auto) then
{
    s_auto addheadgear "H_HelmetIA_camo";
    s_auto addUniform "U_I_CombatUniform_shortsleeve";
    s_auto addVest "V_PlateCarrierIA2_dgtl";
    s_auto addBackpack "B_AssaultPack_khk";
    s_auto addGoggles "G_Combat";
   
    s_auto addMagazine "200Rnd_65x39_cased_Box";
    s_auto addMagazine "200Rnd_65x39_cased_Box";
    s_auto addMagazine "200Rnd_65x39_cased_Box";
    s_auto addWeapon "LMG_Mk200_F";
    s_auto addMagazine "16Rnd_9x21_Mag";
    s_auto addMagazine "16Rnd_9x21_Mag";
    s_auto addWeapon "hgun_P07_snds_F";
   
};

if (IsPlayer s_engineer) then
{
    s_engineer addHeadgear "H_MilCap_dgtl";
    s_engineer addUniform "U_I_CombatUniform";
    s_engineer addVest "V_PlateCarrier_IA2_dgtl"
    s_engineer addBackpack "B_AssualtPack_rgr_Repair";
    s_engineer addGoggles "G_Combat";

    s_engineer addMagazine "30Rnd_556x45_Stanag";
    s_engineer addMagazine "30Rnd_556x45_Stanag";
    s_engineer addMagazine "30Rnd_556x45_Stanag";
    s_engineer addMagazine "30Rnd_556x45_Stanag";
    s_engineer addMagazine "30Rnd_556x45_Stanag";
    s_engineer addWeapon "arifle_Mk20C_F";
    s_engineer addPrimaryWeaponItem "optic_ACO_grn";
    s_engineer addMagazine "16Rnd_9x21_Mag";
    s_engineer addMagazine "16Rnd_9x21_Mag";
    s_engineer addMagazine "16Rnd_9x21_Mag";
    s_engineer addWeapon "hgun_P07_snds_F";

};

_______________________________________________________________________
And that is how to create an automatic gearbox that will, well, automatically arm troops using an event handler. This can be used in a variety of ways and the coding can be tweaked and utilised practically anywhere to any result. Want to make a repair station for vehicles, why not use the automatic gearbox code (tweaked of course)? The basics taught here are very valuable to any missions that feature dynamic systems. What about those animations? Well, the next tutorial will be looking at the Animation viewer and different uses for custom placed animations in depth.

1 comment:

  1. if (IsPlayer s_engineer) exitWith { ... } is executed a lot quicker by the server. More efficient

    ReplyDelete