[Guide] Using ws_fnc_createGarrison

Party-approved future science plus handbooks for the revolution
Post Reply
User avatar
wolfenswan
Posts: 1208
Joined: Wed May 25, 2011 4:59 pm

[Guide] Using ws_fnc_createGarrison

Post by wolfenswan » Wed Feb 19, 2014 11:57 am

Introduction
ws_fnc_createGarrison, similarly to the older ws_fnc_taskDefend, aims to provide a convenient and perfomance-friendly solution to one of the more annoying tasks in editing: fortifying towns and buildings. It creates the units directly inside the building and sets them up to engage independently. That way you can fill up an entire block of buildings (or even town if you feel ambitious) at once and don't have to do it on a building-per-building basis.

Usage
To use the function, simply call it with the desired parameters, making sure that it only runs on the server (or headless client if you are using one). I have a preferred and streamlined way of implementing it in my missions which I'll detail below, under Implementation.

Parameters
[center,radius,side,units,threshold,classes] call ws_fnc_createGarrison
Red are mandatory, blue are optional.
1. center - Indicates the center around which units are placed. Can be an object or a marker.
2. radius - Indicates the radius around the center in which units to place. Needs to cover at least one building!
3. side - Which side the units will belong to (east, west, independent, civilian).
4. units - number of units that will be placed. Default value is (# of buildings in radius / 4). Tip: Keep this number between 6 and 20.
5. threshold - percentage of building positions that can max be occupied in any building. Default value can be set at top of fn_createGarrison.sqf, below classes.
6. classes - an array from which the unit classes will be picked. If left out they default classes defined in fn_createGarrison.sqf are used (lines 26 - 32).

Implementation Example
In-Editor
1. In the editor, place a Gamelogic > Location in the center of the group of buildings you want occupied, which one you pick does not matter. Name it garrisonLogic.

2. Double-click on the newly placed Logic and put the following into it's init field:

Code: Select all

this setVariable ["ws_garrisonSettings",[]]
This assigns a variable to the logic named ws_garrisonSettings from which createGarrison will later read the parameters.

Screenshot TBA

3. Modify the inner array to your liking, for example if we wanted to create a CSAT garrison of 1-5 units within 50m it would be:

Code: Select all

this setVariable ["ws_garrisonSettings",[this,50,east,(round random 5)]]
As you can tell, what we put into the array corresponds to the parameters outlined above. The this simply refers to the logic itself to make it the center around which houses will be occupied.

Tips:
* Use the placement radius for the logic to determine which radius createGarrison will cover. Screenshot tba

4. Select the gamelogic you just created and copy it once for every town/group of buildings you need occupied. They should all be numbered garrisonLogic_1,garrisonLogic_2,....,garrisonLogic_n etc. Make sure to only copy the original garrisonLogic, otherwise the numbering will be off. Then modify the setVariable values to your liking.

Script-side
1. In your mission root-folder (where the init.sqf is), create a new file named ws_garrisonControl.sqf. Open it and put at it's top:

Code: Select all

if !(isServer) exitWith {};
. This will make sure you don't end up with a bazillion AI accidentally.

2. Below that, add the line:

Code: Select all

_garrisons = [garrisonLogic] call ws_fnc_collectObjectsNum;
This is identical to writing

Code: Select all

_garrisons = [garrisonLogic,garrisonLogic_1,garrisonLogic_2,garrisonLogic_3,...,garrisonLogic_n]
but as you can probably tell it saves you some writing, as long as the numbering is coherent.

3. Below the part you just added, paste this section:

Code: Select all

_units = [];
{
_units append ((_x getVariable "ws_garrisonSettings") call ws_fnc_createGarrison);
} forEach _garrisons;

_units execVM "f\setAISkill\f_setAISkill.sqf";
This bit loops through the array containing all logics you placed earlier and read the ws_garrisonSettings-variable. Using these values it calls the garrison function.

The last line will make sure that the spawned AI are adjusted by the F3 AI Skill selector.

You can now close and save this file.

4. Next, open init.sqf in your root directy and at the very bottom add

Code: Select all

[] execVM "ws_garrisonControl.sqf";
And you're done!

Debugging
Enabling debug mode
Simply put

Code: Select all

ws_debug = true;
into any unit or logic init. It will cause all ws_fnc to place markers and output messages. For the garrison function you should see a central "HOLD" waypoint where your game logic is, as well as white and green dots in the buildings around it. White dots are bpos which were found, green dots are building positions which were occupied.

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

Equipping created units

Post by wolfenswan » Sun Apr 13, 2014 3:15 pm

If you don't want to use the default equipment of the created units you have two options:
1. F3 Assign Gear Component
2. BIS_fnc_addWeapon

The first you should know. It has the benefit of giving you great control over what equipment the unit will receive but also does a lot of stuff you might actually not need if you just want to change the primary weapon, wasting the server's resources.

The second is a neat little function provided by BIS, which allows you to add any Weapon to a given unit along with a number of magazines. It's the ideal solution if you just want to mix up the weapon selection.

Following the example from above, we have access to a local variable _units, an array. As the output of the createGarrison function is an array containing the created units, we're simply collecting all created units in one local array. This way you could do whatever with the created units, in our case equipping them with new gear.

Example #1: F3 Assign Gear component:
if !(isServer) exitWith {};

_garrisons = [garrisonLogic] call ws_fnc_collectObjectsNum;
_units = [];
{
_units append ((_x getVariable "ws_garrisonSettings") call ws_fnc_createGarrison);
} forEach _garrisons;

_gear = ["r","car","smg","r","car","ar"];
{
[_gear call BIS_fnc_selectRandom,_x] call f_fnc_assignGear;
} forEach _units;


_units execVM "f\setAISkill\f_setAISkill.sqf";
Two parts were added:
a) - a new local array _gear that contains various cases of "F3 gear". Some of them are doubled to heighten their chance of appearance (i.e. there should be more riflemen than assault riflemen).
b) - a forEach loop that processes all units collected in _units and equips them with a random pick from the _gear array.

Example #2: BIS_fnc_addWeapon:
if !(isServer) exitWith {};

_garrisons = [garrisonLogic] call ws_fnc_collectObjectsNum;
_units = [];
{
_units append ((_x getVariable "ws_garrisonSettings") call ws_fnc_createGarrison);
} forEach _garrisons;


_gear = [
["hgun_PDW2000_F",8],
["SMG_01_F",8],
["SMG_02_ACO_F",8],
["arifle_Mk20C_F",6]
];

{
_wp = _gear call ws_fnc_selectRandom;
[_x,_wp select 0,_wp select 1] call BIS_fnc_addWeapon;
} forEach _units;


_units execVM "f\setAISkill\f_setAISkill.sqf";
Two parts were added:
a) - a new local array _gear that contains a selection of arrays ["string",integer]. The string a weapon class, the integer the amount of magazines to be added.
b) - a forEach loop that processes all units collected in _units and selects a random weapon from the _gear array. Then it uses the BIS_fnc_addWeapon function to equip the unit.



So, which method to use?
Personally I prefer the second method as it is very straightforward and doesn't have the "weight" of the assign Gear component. Of course it requires you to know the weapon class (which can be easily obtained from here), but otherwise it's very simple to use. As long as you aren't processing hundreds of AI units at once the performance impact from using the F3 component should not be massive though. A tip: BIS_fnc_addWeapon works with every weapon, not only rifles/smgs!

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

Re: Guide to: ws_fnc_createGarrison

Post by wolfenswan » Wed May 07, 2014 4:32 pm

Updated first post to reflect new optional threshold value for createGarrison.

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

Re: Guide to: ws_fnc_createGarrison

Post by wolfenswan » Sat May 31, 2014 8:56 pm

Updated to reflect changes made in F3 3-1-0.

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

Re: [Guide] Using ws_fnc_createGarrison

Post by wolfenswan » Mon Jan 12, 2015 10:54 am

Updated the main guide to a more convenient method, updated the equipping-guide to reflect changes made in the first guide.

User avatar
SuicideKing
Host
Posts: 309
Joined: Wed Nov 27, 2013 1:29 pm
Location: India/Netherlands
Contact:

Re: [Guide] Using ws_fnc_createGarrison

Post by SuicideKing » Sat Aug 22, 2015 5:28 pm

Note about the default classes and sides:

If a Comrade should venture into fn_createGarrison.sqf, s/he will likely encounter the following lines of code:

Code: Select all

// Default classes (Arma 3)
// NATO
_garrisonNATO = ["B_Soldier_lite_F","B_Soldier_F"];
// CSAT
_garrisonCSAT = ["O_Soldier_lite_F","O_Soldier_F"];
// AAF
_garrisonAAF = ["I_Soldier_lite_F","I_Soldier_F"];
// FIA
_garrisonFIA = ["B_G_Soldier_lite_F","B_G_Soldier_F"];
// CIVILIAN
_garrisonCIV = [""];

Code: Select all

// If default classes are being used, select the corresponding array
if (count _classes == 0) then {
	switch (_side) do {
		case west: {_classes = _garrisonNATO};
		case blufor: {_classes = _garrisonNATO};
		case east: {_classes = _garrisonCSAT};
		case opfor: {_classes = _garrisonCSAT};
		case resistance: {_classes = _garrisonAAF};
		case independent: {_classes = _garrisonAAF};
		case civilian: {_classes = _garrisonCIV};
	};
};
As you may notice, there does not appear to be any side which corresponds to class _garrisonFIA. If, like me you're new to Arma, you may assume that making the following change will let you create a FIA garrison:

Code: Select all

case resistance: {_classes = _garrisonFIA};
Do not do this. :cop:

This "resistance" corresponds to Armas of yore, and will spawn FIA looking units with BLUFOR map markers and AAF weapons, but they will NOT be friendly to FIA. I'm not sure who they're friendly to (didn't try beyond witnessing them engage FIA units), but I guess they follow Independent's setting.

To correctly spawn FIA units, do this:

Code: Select all

case west: {_classes = _garrisonFIA};
:eng101:

Changing blufor to FIA doesn't seem to have any effect, and still spawns NATO units.

Now, I must head back to the War Room, the revolution beckons! :hist101:
Last edited by SuicideKing on Sun Aug 23, 2015 4:37 pm, edited 1 time in total.
themiddlevoid.wordpress.com

User avatar
Ferrard Carson
Host
Posts: 565
Joined: Sun Aug 12, 2012 6:08 am

Re: [Guide] Using ws_fnc_createGarrison

Post by Ferrard Carson » Sun Aug 23, 2015 1:41 am

SuicideKing wrote:Changing blufor to FIA doesn't seem to have any effect, and still spawns NATO units.
Something has gone wrong if you cannot spawn FIA units by changing "case west: {_classes = _garrisonNATO};" to "case west: {_classes = _garrisonFIA};" - in the meantime, your instructions are going to confuse the crap out of people who suddenly have a whole bunch of digi-camo kitted AAF troopers playing the role of NATO's scrappy resistance fighter nephew.
  • Have you set up your Game Logics correctly, or are they still calling for the "Resistance" faction from when you weren't aware that West = BLUFOR, East = OPFOR and Resistance = INDFOR?
  • Did you change "case blufor: {_classes = _garrisonNATO};" but call for "west" in the Game Logics instead of "blufor"?
  • Have you altered anything in fn_createGarrison.sqf except for the line I quoted above?
  • Have you created ws_garrisonControl.sqf exactly as instructed above?
If all else fails, wipe it and start with a fresh copy of the correct file, then make the change you need to make and nothing else.

~ Ferrard
"Take a boat in the air you don't love, she'll shake you off just as sure as the turnin' of the worlds. Love keeps her in the air when she oughta fall down, tells you she's hurtin' before she keels... makes her home."

User avatar
SuicideKing
Host
Posts: 309
Joined: Wed Nov 27, 2013 1:29 pm
Location: India/Netherlands
Contact:

Re: [Guide] Using ws_fnc_createGarrison

Post by SuicideKing » Sun Aug 23, 2015 4:44 pm

Lol no it was a typo. Sorry! Fixed it now.

I had simply meant:

This works, as you say:

Code: Select all

case west: {_classes = _garrisonFIA};
This spawns FIA-looking people with Independent friendly-ness and blue map markers:

Code: Select all

case resistance: {_classes = _garrisonFIA};
This won't work and just spawns NATO:

Code: Select all

case blufor: {_classes = _garrisonFIA};
Sorry for the confusion. I just copy-pasted the _garrisonAAF line twice in the post above and forgot to modify it the second time.
themiddlevoid.wordpress.com

Post Reply