Comrades in Arms Discussion Board

Full Version: Scripting (No Discussion, just posts)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
Hi.

Thought I'd share this. It's a python script that generates a bikb file and empty sound samples, the length of which are adjusted to the length of the text. I use it in all my missions to make radio messages, since it will have several distinct advantages over sideChat:

- kbTell and associated methods run without "sleep" or any other such measures. They're event-based, so you only need to have kbTell once and the event handlers can create a whole conversation for you.
- You can make menus, like in the Harvest Red campaign when you can decide whether to free the hostages or not
- It will not automatically capitalize all text, like sideChat does
- You can make real audio samples

How to use the script:

You will need to have the Python system installed, download it from Python.org (3.0 or later required). You will also need oggenc2. I've added it to the archive.

genBIBK works from a text file. The general syntax of the text file is.

[sentenceidbase] Text

sentenceidbase is what you get as sentenceId in your event handlers or in kbtell. It will automatically add a number to this. Text is what is going to be said. Example:

[radio] Eagle 2-1, this is Eagle Actual. We have incoming fast movers from the north-east. Over.
[radio] Roger, Eagle. Keeping our heads down. Out.

Put this into a file speech.txt and run the script as:

python genBIKB.py speech.txt

to generate three files:

speech.bikb
radio1.ogg
radio2.ogg

speech.bikb is the file with the sentence definitions:

Code:
// Autogenerated file.

class Sentences
{
   class radio1
   {
       /* Projected duration is 8 seconds */
      text =  "Eagle 2-1, this is Eagle Actual. We have incoming fast movers from the north-east. Over.";
      speech[] = {"\kb\radio1.ogg"};
      class Arguments {};
   };
   class radio1a
   {
       /* Empty token */
      text =  "";
      speech[] = {};
      class Arguments {};
   };
   class radio2
   {
       /* Projected duration is 4 seconds */
      text =  "Roger, Eagle. Keeping our heads down. Out.";
      speech[] = {"\kb\radio2.ogg"};
      class Arguments {};
   };
   class radio2a
   {
       /* Empty token */
      text =  "";
      speech[] = {};
      class Arguments {};
   };
};

class Arguments{};
class Special{};
startWithVocal[] = {hour};
startWithConsonant[] = {europe, university};

Once you kbAddTopic the file to a couple of units (say, Eagle21 and EagleHQ) you can just do an

EagleHQ kbTell [Eagle21, "speech", "radio1"];

to make EagleHQ radio Eagle21. You will need the appropriate script and/or FSM for Eagle21 to reply, I believe Varanon wanted to post his generic solution for this.

You'll notice there are two radio1 tokens, radio1 and radio1a. The script automatically generates an empty token with "a" appended. This can be used for "silent responses", for example, if you want EagleHQ to send more than one radio message, you can have Eagle21 reply with radio1a to make sure that EagleHQ can send the second line when it "hears" radio1a.

If you have any questions, just ask Smile
Comrades,

I've been asked before how we do the conversations in our missions. Some people simply use sideChat since that's easiest, but it doesn't allow you to synchronize correctly (you'd need to wait or similar bollocks).

With Alwarren's script it's easy to generate a speech bikb file that contains the sentences that you wish your guys to speak. Here, I wish to explain how the things work in Arma (applies to 2 and 3).

First of all, all characters (player and AI) need to be made aware of their lines. This is done via kbAddTopic. The syntax for this is:

Code:
unit kbAddTopic [topicName, filename.bikb, handler.fsm, eventhandler].

Note that the unit has to be local. I usually do this in the init.sqf, to make sure everyone (all clients and the server) do that. The appropriate line looks like this:

Code:
{
     _x addTopic ["speech", "kb\speech.bikb", "kb\bounce.fsm", compile preprocessFileLineNumbers "kb\bounce.sqf"];
} forEach ((if (isMultiplayer) then {playableUnits} else {switchableUnits}) + [HQ] + crew cerberus);

This example adds the topic "speech" to all units that can be played, as well as a unit HQ and the crew of the vehicle Cerberus.

I usually put everything speech related into a "kb" subfolder

The third and fourth array element, handler.fsm and eventhandler, are the handlers that are called when the unit hears a topic. The catch is, the handler.fsm is executed when the unit is an AI, and the eventhandler is executed when the unit is a player. This also means that if you want to have conversation between playable characters, you need to cope with the situation that the character might be currently played by a player, or not (in which case it's an AI).

To make this situation easier to handle, I use a script and an fsm that just "bounce" the incoming data to a combined script, kb\playerChatEvent.sqf. This script has to be executed once in init.sqf to make the code in it available.

The whole init.sqf fragment looks like this:

Code:
// Add this somewhere in your init.sqf:
// Example: Add topic to all players, an entity called "HQ", and the cew of an AI controlled APC

call compile preprocessFileLineNumbers "kb\playerChatEvent.sqf";

{
     _x addTopic ["speech", "kb\speech.bikb", "kb\bounce.fsm", compile preprocessFileLineNumbers "kb\bounce.sqf"];
} forEach ((if (isMultiplayer) then {playableUnits} else {switchableUnits}) + [HQ] + crew cerberus);

The bounce.fsm and bounce.sqf scripts are available in the example.zip file attached to this post. They call a function called FHQ_handleSpeech with the following parameters:

Code:
_to = _this select 0;
_from = _this select 1;
_sentenceId = _this select 2;
_topic = _this select 3;

_to is the unit that heard the sentence. _from is the speaker (the sender of the sentence). _sentenceId is the name of the sentence, which corresponds to the class name in the bikb. _topic is the topic name ("speech" in our example above.

The usual thing to do when hearing a sentence is to reply with an appropriate line. This is usually done via kbTell (see below). To make things easier, I use a macro defined in playerChatEvent that does that.

Here's an excerpt from an actual playerChatEvent.sqf. The script is run on the machine _to is local to:

Code:
   if (_to == leader FHQ_playerGroup1) then {
      switch (_sentenceId) do {
                         replycase("startAns1", _from, "start2");
                         replycase("startAns2", _from, "start3");
                         replycase("vehicleDown1", _from, "vehicleDownAns1");
          replycase("reachedHome1", _from, "reachedHomeAns1");
      };
   };

it checks if the recipient of the message is the leader of FHQ_playerGroup1 and then selects a reply according to the _sentenceId. Check the example.zip for a larger example.

As mentioned, kbTell is used to say something:
Code:
unit kbTell [receiver, topicName, sentence];

Note that, as usual, kbTell needs to be run on the machine unit is local to. I use the FHQ MP framework for this, but others work as well.

Hope that helps. if you need more information, just ask.

- V
Handling loadout scripts that only run once:

I have a method of adding custom loadouts that is quite safe. I have the following script in a function module, but you can also use it with
FHQ_fnc_safeAddLoadout = compile preprocessFileLineNumbers "safeAddLoadout.sqf";

Code:
_unit = _this select 0;
_scriptName = _this select 1;

if (!local _unit) exitWith {};

_isHandled = _unit getVariable "FHQ_loadout_handled";
   
if (isNil "_isHandled") then {
       
    _unit setVariable ["FHQ_loadout_handled", true, true];
   _unit call compile preprocessFileLineNumbers _scriptName;
};

Use as

[this, "scripts\loadout.sqf"] call FHQ_fnc_safeAddLoadout;

from the init field or anywhere else (init.sqf etc). That also prevents them from being re-applied when JIPing or being revived. "scripts\loadout.sqf" is the name of the loadout script that is saved from FHQ Debug console or the Virtual Arsenal.
I've been messing with a script to replace CAF Aggressors weapons and magazines with massi's weapons from his NATO and Spetznaz weapons addon. I initially used global commands just to be 110% sure, but removeAllWeapons is local, so I opted for local commands and server side execution.
After some testing on dedi it seems to work, the AI have the loadouts intended by the script and you can interact with them, though if the player is one of the units affected, the main weapon won't be replaced but magazines will be. Input appreciated.

The script (used as function otl7_fnc_replaceCAFaks):
Code:
{switch (typeOf _x) do
   {
   case "CAF_AG_ME_T_AK47" :
      {
      removeAllWeapons _x;
      _x addMagazine "SmokeShell";
      _x addMagazine "SmokeShell";
      _x addMagazine "HandGrenade";
      _x addMagazine "HandGrenade";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
                   _x addWeapon "arifle_mas_akms";
      };
   case "CAF_AG_ME_T_AK74" :
      {
      removeAllWeapons _x;
      _x addMagazine "SmokeShell";
      _x addMagazine "SmokeShell";
      _x addMagazine "HandGrenade";
      _x addMagazine "HandGrenade";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
                   _x addWeapon "arifle_mas_akm";
      };
   case "CAF_AG_ME_T_GL" :
      {
      removeAllWeapons _x;
      _x addMagazine "SmokeShell";
      _x addMagazine "SmokeShell";
      _x addMagazine "1Rnd_HE_Grenade_shell";
      _x addMagazine "1Rnd_HE_Grenade_shell";
      _x addMagazine "1Rnd_HE_Grenade_shell";
      _x addMagazine "1Rnd_HE_Grenade_shell";
      _x addMagazine "1Rnd_HE_Grenade_shell";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
                   _x addWeapon "arifle_mas_akms_gl";
      };
   case "CAF_AG_ME_T_PKM" :
      {
      removeAllWeapons _x;
      _x addBackpack "B_TacticalPack_rgr";
      _x addMagazine "SmokeShell";
      _x addMagazine "SmokeShell";
      _x addMagazine "HandGrenade";
      _x addMagazine "HandGrenade";
      _x addMagazine "100Rnd_mas_762x54_mag";
      _x addMagazine "100Rnd_mas_762x54_mag";
      _x addMagazine "100Rnd_mas_762x54_mag";
      _x addMagazine "100Rnd_mas_762x54_mag";
                   _x addWeapon "LMG_mas_pkm_F";
      };
   case "CAF_AG_ME_T_RPG" :
      {
      removeAllWeapons _x;
      //_x addBackpack "B_TacticalPack_rgr";
      _x addMagazine "SmokeShell";
      _x addMagazine "SmokeShell";
      _x addMagazine "HandGrenade";
      _x addMagazine "HandGrenade";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
      _x addMagazine "30Rnd_mas_762x39_mag";
                   _x addWeapon "arifle_mas_akms";
      _x addMagazine "mas_PG7V";
      _x addMagazine "mas_PG7V";
      _x addMagazine "mas_OG7";
      _x addMagazine "mas_OG7";
      _x addMagazine "mas_OG7";
                   _x addWeapon "mas_launch_RPG7_F";
      };
   case "CAF_AG_ME_T_RPK74" :
      {
      removeAllWeapons _x;
      _x addBackpack "B_TacticalPack_rgr";
      _x addMagazine "SmokeShell";
      _x addMagazine "SmokeShell";
      _x addMagazine "HandGrenade";
      _x addMagazine "HandGrenade";
      _x addMagazine "100Rnd_mas_545x39_mag";
      _x addMagazine "100Rnd_mas_545x39_mag";
      _x addMagazine "100Rnd_mas_545x39_mag";
      _x addMagazine "100Rnd_mas_545x39_mag";
                   _x addWeapon "LMG_mas_rpk_F";
      };
   case "CAF_AG_ME_T_SVD" :
      {
      removeAllWeapons _x;
      _x addMagazine "SmokeShell";
      _x addMagazine "SmokeShell";
      _x addMagazine "HandGrenade";
      _x addMagazine "HandGrenade";
      _x addMagazine "10Rnd_mas_762x54_mag";
      _x addMagazine "10Rnd_mas_762x54_mag";
      _x addMagazine "10Rnd_mas_762x54_mag";
      _x addMagazine "10Rnd_mas_762x54_mag";
      _x addMagazine "10Rnd_mas_762x54_mag";
      _x addMagazine "10Rnd_mas_762x54_mag";
                   _x addWeapon "srifle_mas_svd_h";
      };
         };
} forEach allUnits;

Exec in init.sqf:
Code:
if (isServer) then {call otl7_fnc_replaceCAFaks};
I forgot to post this, Variable I know you were asking how to remove chat spam from AI within missions. In your init file:
enableSentences false;

For ending missions you can also use https://community.bistudio.com/wiki/BIS_...sionServer



Quote:[size=1em]Now place a trigger near the first waypoint, and set its Condition field to true. Set the timer to
“Countdown” and set Min, Mid and Max all to 60. Synchronize the trigger with the first waypoint.
This will ensure that the convoy waits a minute before departing Mike-26.[/size]

[size=1em]Couldn't you just set the delay in waypoint's timeout field? Also doesn't a trigger synced to a waypoint need to be Switch type?[/size]


[size=1em]For some variables defined in init.sqf, a isNil check is needed otherwise JIPs will overwrite them.[/size]
Staying compatible with MP and SP, part I

In MP, playableUnits returns all units that can be played. In SP, this returns an empty array and instead switchableUnits should be used.

So in essence, to stay compatible, use this line whenever you would use either playableUnits or switchableUnits:

Code:
_units = (if (isMultiplayer) then {playableUnits} else {switchableUnits})

This can also be used in other constructions:

Code:
{
_x setCaptive true;
_x moveInCargo myVehicle;
} foreach  (if (isMultiplayer) then {playableUnits} else {switchableUnits})


I had recently used the Eastern European aggressors and adjusted the script to also handle that:

Code:
/*
* Fix loadout of CAF Aggressors with Massi weapons
* Script by Outlawz7
*/

{
    switch (typeOf _x) do
    {
    case "CAF_AG_ME_T_AK47" :
        {
        removeAllWeapons _x;
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
                    _x addWeapon "arifle_mas_akms";
        };
    case "CAF_AG_eeur_r_AK47":
    {
        removeAllWeapons _x;
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
                    _x addWeapon "arifle_mas_akms";
        };
    case "CAF_AG_ME_T_AK74" :
        {
        removeAllWeapons _x;
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
                    _x addWeapon "arifle_mas_akm";
        };
    case "CAF_AG_eeur_r_AK74":
    {
        removeAllWeapons _x;
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addWeapon "arifle_mas_akm";
        };
    case "CAF_AG_ME_T_GL" :
        {
        removeAllWeapons _x;
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
                    _x addWeapon "arifle_mas_akms_gl";
        };
    case "CAF_AG_EEUR_R_GL":
    {
        removeAllWeapons _x;
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "1Rnd_HE_Grenade_shell";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
                    _x addWeapon "arifle_mas_akms_gl";
        };
    case "CAF_AG_ME_T_PKM" :
        {
        removeAllWeapons _x;
        _x addBackpack "B_TacticalPack_rgr";
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "100Rnd_mas_762x54_mag";
        _x addMagazine "100Rnd_mas_762x54_mag";
        _x addMagazine "100Rnd_mas_762x54_mag";
        _x addMagazine "100Rnd_mas_762x54_mag";
                    _x addWeapon "LMG_mas_pkm_F";
        };
    case "CAF_AG_eeur_r_PKM":
    {
        removeAllWeapons _x;
        _x addBackpack "B_TacticalPack_rgr";
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "100Rnd_mas_762x54_mag";
        _x addMagazine "100Rnd_mas_762x54_mag";
        _x addMagazine "100Rnd_mas_762x54_mag";
        _x addMagazine "100Rnd_mas_762x54_mag";
                    _x addWeapon "LMG_mas_pkm_F";
        };
    case "CAF_AG_ME_T_RPG" :
        {
        removeAllWeapons _x;
        //_x addBackpack "B_TacticalPack_rgr";
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
                    _x addWeapon "arifle_mas_akms";
        _x addMagazine "mas_PG7V";
        _x addMagazine "mas_PG7V";
        _x addMagazine "mas_OG7";
        _x addMagazine "mas_OG7";
        _x addMagazine "mas_OG7";
                    _x addWeapon "mas_launch_RPG7_F";
        };
    case "CAF_AG_eeur_r_RPG":
    {
        removeAllWeapons _x;
        //_x addBackpack "B_TacticalPack_rgr";
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
        _x addMagazine "30Rnd_mas_762x39_mag";
                    _x addWeapon "arifle_mas_akms";
        _x addMagazine "mas_PG7V";
        _x addMagazine "mas_PG7V";
        _x addMagazine "mas_OG7";
        _x addMagazine "mas_OG7";
        _x addMagazine "mas_OG7";
                    _x addWeapon "mas_launch_RPG7_F";
        };
    case "CAF_AG_ME_T_RPK74" :
        {
        removeAllWeapons _x;
        _x addBackpack "B_TacticalPack_rgr";
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "100Rnd_mas_545x39_mag";
        _x addMagazine "100Rnd_mas_545x39_mag";
        _x addMagazine "100Rnd_mas_545x39_mag";
        _x addMagazine "100Rnd_mas_545x39_mag";
                    _x addWeapon "LMG_mas_rpk_F";
        };
    case "CAF_AG_eeur_r_RPK74":
    {
        removeAllWeapons _x;
        _x addBackpack "B_TacticalPack_rgr";
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "100Rnd_mas_545x39_mag";
        _x addMagazine "100Rnd_mas_545x39_mag";
        _x addMagazine "100Rnd_mas_545x39_mag";
        _x addMagazine "100Rnd_mas_545x39_mag";
        _x addWeapon "LMG_mas_rpk_F";
        };
    case "CAF_AG_ME_T_SVD" :
        {
        removeAllWeapons _x;
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
                    _x addWeapon "srifle_mas_svd_h";
        };
    case "CAF_AG_EEUR_R_SVD":
    {
        removeAllWeapons _x;
        _x addMagazine "SmokeShell";
        _x addMagazine "SmokeShell";
        _x addMagazine "HandGrenade";
        _x addMagazine "HandGrenade";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
        _x addMagazine "10Rnd_mas_762x54_mag";
                    _x addWeapon "srifle_mas_svd_h";
        };
};
} forEach allUnits;

My version with CUP. In this version they use AKM instead of AKS


Code:
            /*
             * Fix loadout of CAF Aggressors with CUP weapons
             * Script by Outlawz7
             */


            {
               switch (typeOf _x) do
               {
               case "CAF_AG_ME_T_AK47" :
                  {
                  removeAllWeapons _x;
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_AK74";
                  };
               case "CAF_AG_eeur_r_AK47":
               {
                  removeAllWeapons _x;
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_AK74";
                  };
               case "CAF_AG_ME_T_AK74" :
                  {
                  removeAllWeapons _x;
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_AK74";
                  };
               case "CAF_AG_eeur_r_AK74":
               {
                  removeAllWeapons _x;
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_AK74";
                  };
               case "CAF_AG_ME_T_GL" :
                  {
                  removeAllWeapons _x;
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_AK74_GL";
                  };
               case "CAF_AG_EEUR_R_GL":
               {
                  removeAllWeapons _x;
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_1Rnd_HE_GP25_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_AK74_GL";
                  };
               case "CAF_AG_ME_T_PKM" :
                  {
                  removeAllWeapons _x;
                  _x addBackpack "B_TacticalPack_rgr";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_100Rnd_TE4_LRT4_762x54_PK_Tracer_Green_M";
                  _x addMagazine "CUP_100Rnd_TE4_LRT4_762x54_PK_Tracer_Green_M";
                  _x addMagazine "CUP_100Rnd_TE4_LRT4_762x54_PK_Tracer_Green_M";
                  _x addMagazine "CUP_100Rnd_TE4_LRT4_762x54_PK_Tracer_Green_M";
                           _x addWeapon "CUP_lmg_Pecheneg_PScope";
                  };
               case "CAF_AG_eeur_r_PKM":
               {
                  removeAllWeapons _x;
                  _x addBackpack "B_TacticalPack_rgr";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_100Rnd_TE4_LRT4_762x54_PK_Tracer_Green_M";
                  _x addMagazine "CUP_100Rnd_TE4_LRT4_762x54_PK_Tracer_Green_M";
                  _x addMagazine "CUP_100Rnd_TE4_LRT4_762x54_PK_Tracer_Green_M";
                  _x addMagazine "CUP_100Rnd_TE4_LRT4_762x54_PK_Tracer_Green_M";
                           _x addWeapon "CUP_lmg_Pecheneg_PScope";
                  };
               case "CAF_AG_ME_T_RPG" :
                  {
                  removeAllWeapons _x;
                  //_x addBackpack "B_TacticalPack_rgr";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_AK74";
                  _x addMagazine "CUP_PG7V_M";
                  _x addMagazine "CUP_PG7V_M";
                  _x addMagazine "CUP_OG7_M";
                  _x addMagazine "CUP_OG7_M";
                  _x addMagazine "CUP_OG7_M";
                           _x addWeapon "CUP_launch_RPG7V";
                  };
               case "CAF_AG_eeur_r_RPG":
               {
                  removeAllWeapons _x;
                  //_x addBackpack "B_TacticalPack_rgr";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_AK74";
                  _x addMagazine "CUP_PG7V_M";
                  _x addMagazine "CUP_PG7V_M";
                  _x addMagazine "CUP_OG7_M";
                  _x addMagazine "CUP_OG7_M";
                  _x addMagazine "CUP_OG7_M";
                           _x addWeapon "CUP_launch_RPG7V";
                  };
               case "CAF_AG_ME_T_RPK74" :
                  {
                  removeAllWeapons _x;
                  _x addBackpack "B_TacticalPack_rgr";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_30Rnd_TE1_White_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Green_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                           _x addWeapon "CUP_arifle_RPK74";
                  };
               case "CAF_AG_eeur_r_RPK74":
               {
                  removeAllWeapons _x;
                  _x addBackpack "B_TacticalPack_rgr";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_30Rnd_TE1_White_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Red_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Green_Tracer_545x39_AK_M";
                  _x addMagazine "CUP_30Rnd_TE1_Yellow_Tracer_545x39_AK_M";
                  _x addWeapon "CUP_arifle_RPK74";
                  };
               case "CAF_AG_ME_T_SVD" :
                  {
                  removeAllWeapons _x;
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                           _x addWeapon "CUP_srifle_LeeEnfield";
                  };
               case "CAF_AG_EEUR_R_SVD":
               {
                  removeAllWeapons _x;
                  _x addMagazine "SmokeShell";
                  _x addMagazine "SmokeShell";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "HandGrenade";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                  _x addMagazine "CUP_10x_303_M";
                           _x addWeapon "CUP_srifle_LeeEnfield";
                  };
             };
            } forEach allUnits;
Expanded version of safeAddLoadout. Can name the variable, allowing more than one use, can pick execVM or execFSM with an optional argument, default is call compile preprocess.

Use as function recommended.

Code:
/*
Execute script in init field only once.

Example:
[this, "loadouts\loadout.sqf","OTL7_loadout_handled"] call OTL7_fnc_oneTimeInit;
[this, "loadouts\loadout.sqf","OTL7_loadout_handled",1] call OTL7_fnc_oneTimeInit;
*/

_unit = _this select 0;
_scriptName = _this select 1;
_customVariable = _this select 2;
_howToExec = if (count _this > 3) then {_this select 3} else {0};

if (!local _unit) exitWith {};

_isHandled = _unit getVariable _customVariable;
   
if (isNil "_isHandled") then {   
   _unit setVariable [_customVariable, true, true];
   switch (_howToExec ) do {
      case 0: { _unit call compile preprocessFileLineNumbers _scriptName };
          case 1: { _unit execVM _scriptName };
          case 2: { _unit execFSM _scriptName };
          default { ["Error: 4th argument must be 0,1 or 2. (%1)",_howToExec] call BIS_fnc_error; };
   };
};
Vehicle extractions. We all know that an extraction is a rewarding experience after a successful mission. Rather than have the player call it themselves, or get into a pre-positioned helicopter that just sits somewhere, this script creates the extraction vehicle on the fly, as well as all waypoints, it waits for a predefined group of players to get in, and then flies them off. All major "events" can run custom scripts (as demonstrated in the sample mission). The script is MP compatible and dedicated server tested.

Mission attached. Let me know if you have any questions.
After yesterdays Extraction example, here's the opposite of that: A script that creates an insertion. You pass it a vehicle, some waypoints and a group that needs to be unloaded, and the script takes care of the rest, including again hooks at key points in the process, as well as (by default) deleting the vehicle and it's crew after they reach an end point.

The vehicle can be of any type (the same is true for the extraction script, by the way).

Mission attached. Let me know if you have any questions.
This mission is an example for a patrol script I just wrote that uses markers instead of the uncertain radius that BIS_fnc_taskPtarol.


Parameters -
0: the group or leader of the group
1: [Optional] Name of the marker. Blank of "" to use the name of the group leader as the marker name
2: [Optional] Number of waypoints for the group. Default is 6
3: [Optional] If TRUE, generate a new route at the end of the patrol. If false (the default), cycle
4: [Optional] If TRUE, prefer waypoints on or near roads. Defaults to False
5: [Optional] if TRUE, delete all previous waypoints of the group. Default is TRUE


At the simplest, you place down a marker, give it a name, then put down a group, give the leader the same name, and put

[this] call FHQ_fnc_markerPatrol;

in the init field.
In the past in order to disable AI friendly chat, in other words to stop them reporting targets from across the map and fill up the chat text with non-sense, i used:


enableSentences false;


It works, but you won't hear enemy AI either, when they are close to you giving orders and stuff.
You can still used it if is an effect you desire.


However, if you still want to hear enemies you can disable playable units chat using this in init:



{
[[_x, "NoVoice"], "setSpeaker", true] call BIS_fnc_MP;
} foreach  (if (isMultiplayer) then {playableUnits} else {switchableUnits});


Tested on dedicated, but didn't test it for JIP.
A way to make sway bearable.
E.G. when players are on independent side:


{if (side _x == independent) then {_x setCustomAimCoef 0.35;}; } forEach allunits;
Pages: 1 2 3