Jump to content
Blitzen88

Learning how to display text from scripted arrays in-game

Recommended Posts

I’ve been trying to learn how to display text from arrays in-game. 
 

For instance, I want to create a script that gathers all of the sectors on a map and then sorts them based off of distance.  The problem I’m having is learning how to display the results in-game.


How can I display the results in-game (via hint, etc.) when I might not even know, from mission to mission, how many Sectors exist on the map?

Share this post


Link to post
Share on other sites

If you have an array, no matter how many elements it contains, you can always iterate through it using various methods. 

 

However, and as always, I may be incorrect, I think this might be a case where using a hashmap might be better suited to the task, as well as more efficient.

 

Some reading: https://community.bistudio.com/wiki/HashMap

 

Another question:  what exactly do you mean by "displayed?" Do you want the data to be presented on command (like an addAction or keyPress that pops up a message) or continuously, like a HUD element?

Share this post


Link to post
Share on other sites

Yeah hard to answer without the knowledge bout what u exactly want to do.

But a whole array can be shown like this:

 

_array = [1, 8, "nine", true, "something"];

hint str _array;

 

Or just the 2nd element:

hint str _array select 1;

 

Or every element with a delay:

 

{

 hint str _x;

sleep 3;

} forEach _array;

Share this post


Link to post
Share on other sites
16 hours ago, Blitzen88 said:

For instance, I want to create a script that gathers all of the sectors on a map and then sorts them based off of distance.  The problem I’m having is learning how to display the results in-game.

How can I display the results in-game (via hint, etc.) when I might not even know, from mission to mission, how many Sectors exist on the map?

 

Sectors on map (placed modules if I'm right):

_modules = missionNamespace getVariable "bis_fnc_modulesector_sectors"

so,

sort by distance (from player) ,and hint:
 

private _modules = missionNamespace getVariable "bis_fnc_modulesector_sectors" apply {[_x distance2D player,_x]};
_modules sort TRUE;
hint str (_modules apply {(_x#1) getVariable "name"});

 

You can filter by owners,....

If you want to update the hint, you need o loop like:


 

[] spawn {
  private "_modules";
  while {true} do {
    _modules = missionNamespace getVariable "bis_fnc_modulesector_sectors" apply {[_x distance2D player,_x]};
    _modules sort TRUE;
    hint str (_modules apply {(_x#1) getVariable "name"});
    sleep 5;
  };
};

 

Share this post


Link to post
Share on other sites
1 hour ago, pierremgi said:

 


hint str (_modules apply {(_x#1) getVariable "name"});};

 

Thank you everyone that has responded. 
 

Im really trying to learn from a more basic level, focusing on something as simple as whats quoted above.  Im trying to learn how to display strings and how %1 works. 
 

My understanding is %1 refers to the first “element” within the array (which is weird because 0 usually refers to the first element) and %2 refers to the second and so on. However, how can you make a display work when you dont always know how many elements will be in the array?

 

Ultimately I want the display to look like:

1) Closest Sector

2) Next Closest Sector

3) etc. 

Share this post


Link to post
Share on other sites
43 minutes ago, Blitzen88 said:

My understanding is %1 refers to the first “element” within the array

 

https://community.bistudio.com/wiki/format

 

First element of the formatted text array's second element. 

_var1 = "Hello";
_var2 = "world";

hint format ["%1, %2!", _var1, _var2];

//returns "Hello, world!"

 

Share this post


Link to post
Share on other sites
49 minutes ago, Blitzen88 said:

the display

 

And again, do you want a HUD element or an on-command hint?

Share this post


Link to post
Share on other sites
5 minutes ago, Harzach said:

 

And again, do you want a HUD element or an on-command hint?

On command hint. 
 

As to your previous comment (Hello World), how do you display elements from an array when you dont know big the array will be? Ie you know there are only two words so therefore you only “need” %1 and %2. How do I make it work if, sometimes the array is 20 elements and sometimes its 5 elements, etc. 

Edited by Blitzen88

Share this post


Link to post
Share on other sites
31 minutes ago, Blitzen88 said:

ow do I make it work if, sometimes the array is 20 elements and sometimes its 5 elements, etc. 

 

Simplest way:

  1. Define a string variable to hold your message.
  2. Iterate over the array using some loop, forEach is particularly suitable in this case.
    • Each iteration you turn the current element into a string and add it at the end of the string from step 1.
  3. Display the string in your preferred i.e. hint.

A code example: 

// Example array
someArray = [1,2,3,4,5];

// Define string variable, in this case prefilled with some text, could also be empty "".
stringToDisplay = "Result: ";
{
	// Turn the current element '_x' into a string using the 'str' command and then add it to the variable using simple string addition.
	stringToDisplay = stringToDisplay + str _x;
} forEach someArray;

// Display the string as desired
hint stringToDisplay;

//Output: Result: 12345

 

Now if you want start introducing hints with colors, alignment and other pretty stuff hint also supports the data-type structured text instead.

It's a bit more involved so I'll just leave how I do it here in this spoiler if you want take a peek.

Spoiler

/* This is just an example ripped from an existing project. 
	
	format turns data into strings for each row of text
	joinString combines multiple rows of individual strings with a new line (<br/>) inbetween to create a combined long string.
	parseText turns this simple string into a structured text
	hint displays it.
  
  	Note this is for a dataset of known size. If you want to handle dynamic sets the array passed in as the first parameter to joinString has to be constructed using some loop-method.
*/
hint parseText (
	[
		"", // Empty rows results in 2 new lines in a row making quite neat vertical spacers
		format ["<img image='%1' color='#FFB000' size='3'/> ", getText (configFile >> "CfgVehicles" >> _gunType >> "icon")],
		"",
		format ["%1 loaded.", _magNameShort]
	] joinString "<br/>"
);

 

 

 

  • Like 2

Share this post


Link to post
Share on other sites

As mrcurry wrote in 2nd code:

 

aa = [123,"2","aString",player,321,findDisplay 46]; // or whatever you want as array
hint parseText (aa joinString "<br/>");  // <br/> is not mandatory, you can replace it by ", " or what you want.

  • Like 1

Share this post


Link to post
Share on other sites
On 7/14/2022 at 10:24 AM, Blitzen88 said:

how do you display elements from an array when you dont know big the array will be?

 

As demonstrated, that's the easy part. The real question is, how is your array structured and how do you want the information displayed?

 

For example, an array that is structured like this:

["Sector 1",50,"Sector 2",100,"Sector 3",150,"Sector 4",200,"Sector 5",250];

Can be displayed using either of these:

hint parseText (_array joinString "<br/>"); 
// OR
hint (format ["%1", _array joinString "\n"]);

and would look like this:

Quote

Sector 1

     50

Sector 2

    100

Sector 3

    150

Sector 4

    200

Sector 5

    250

 

Share this post


Link to post
Share on other sites
On 7/16/2022 at 2:36 AM, Harzach said:

 

As demonstrated, that's the easy part. The real question is, how is your array structured and how do you want the information displayed?

 

For example, an array that is structured like this:


["Sector 1",50,"Sector 2",100,"Sector 3",150,"Sector 4",200,"Sector 5",250];

Can be displayed using either of these:


hint parseText (_array joinString "<br/>"); 
// OR
hint (format ["%1", _array joinString "\n"]);

and would look like this:

 

 

This is a script that I am trying to implement displays:

 

Spoiler

/*==========================================================================================

                Arma III - AI Vehicle Monitor

Created by Blitzen

===========================================================================================

* Deletes empty vehicles, vehicles with dead crew members, and vehicles which cannot move/disabled

* Runs on initialization and loops in intervarls to account for vehicles spawned after the start of the mission

* After initialization the script will give a two minute warning to players before it loops and deletes vehicles

* This script does not check for the amount of fuel the vehicle has

* Helicopters and airplanes which are out of fuel will be considered disabled and will be deleted

* Script refuels and re-arms vehicles

* Parameters:
    
    - Amount of time (in seconds) that will pass before the script loops    

* Call with: Called via Init.sqf

===========================================================================================*/

//Define Variables
_Time = _this select 0;

//Check to see if the Loadout Init file has run - Need unit class designations to clear AI vehicle crew groups
If (isNil "LoadOutInitLoaded") then {

_LoadoutInitCheck = [] execVM "Scripts\Loadouts\Loadout_Init.sqf";
    
WaitUntil { scriptDone _LoadoutInitCheck };

};

_Warning = False;    // Set this to False so warning text will not be displayed on first loop/Init

//Create a list of vehicles that are empty at the start of the mission - Script will not delete those vehicles

_EmptyStartingVehicles = Vehicles select { ( (count crew _x) == 0 ) };

//Start the Loop

While {True} do {

    If (_Warning) then {
    
    Systemchat "Empty & Disabled Vehicles will be Deleted in Thirty Seconds";
    
    Sleep 30;
    
    };
    
    //Vehicle Check
    
    //Remove empty starting vehicles
    
    _AllVehicles = Vehicles - _EmptyStartingVehicles;                                                            
    
    //Remove static weapons and containers
    
    _AllVehicles = _AllVehicles select { !(_x isKindOf "staticWeapon") && (_x isKindOf "AllVehicles") };

    _AllVehicles = _AllVehicles select { !(_x isKindof "ParachuteBase") };    
    
    _AllVehicles = _AllVehicles select { (!canMove _x) || (!alive driver _x) || ( (count crew _x) == 0) || ( (!isNull gunner _x) && (!alive gunner _x) ) || ( (!isNull gunner _x) && (!canFire _x) ) };
    
    _PlayerGroupVehicles = [Group Player, true] call BIS_fnc_groupVehicles;
    
    _PlayerGroupVehicles = _PlayerGroupVehicles select { !( ((count crew _x) == 0) && ( (_x distance player) >= 500) )};
    
    _AllVehicles = _AllVehicles - _PlayerGroupVehicles;
    
    {
    
        {deletevehicle _x} foreach crew _x; deletevehicle _x; 
                    
    } foreach _AllVehicles;

    //Crew Check
    
    _AllCrewUnits = Allunits select { (typeOf _x in Loadouts_AllCrew) && (vehicle _x == _x) && !(group _x == group player) };
    
    {

        deletevehicle _x;

    } foreach _AllCrewUnits;
    
    //Refuel and Rearm Vehicles

    {_x setfuel 1; _x setVehicleAmmo 1} foreach Vehicles;
        
    Systemchat "AI Vehicle & Crew Monitor Loaded";

    _Warning = True;    // Set this to True so warning text will be displayed

    sleep _Time;

//End Loop
};

 

The script essentially deletes vehicles and crewmen that meet certain conditions.  The script loops and displays a message via SystemChat to confirm the loop.  How can I have the script display how many vehicles and crew were deleted?

 

For example: Systemchat "AI Vehicle & Crew Monitor Loaded - X | Y"

 

Where X is vehicles and Y is crewman..?

Share this post


Link to post
Share on other sites

Maybe set variables at the beginning holding the counts of vehicles and AI units, then compare those at the end to the current counts.

 

Psuedocode:

_startVehicles = count vehicles;
_startUnits = count allUnits;

//code

_endVehicles = _startVehicles - count vehicles;
_endUnits = _startUnits - count allUnits;

systemChat format ["AI Vehicle & Crew Monitor Loaded - %1 | %2", _endVehicles, _endUnits];

 

Keep in mind that vehicles also includes "weaponHolderSimulated." I'm assuming these will get picked up in your _EmptyStartingVehicles variable, but you might want to test it to make sure.

 

Anyway, what happened to the sectors?

 

  • Like 1

Share this post


Link to post
Share on other sites
3 hours ago, Harzach said:

Maybe set variables at the beginning holding the counts of vehicles and AI units, then compare those at the end to the current counts.

 

Psuedocode:


_startVehicles = count vehicles;
_startUnits = count allUnits;

//code

_endVehicles = _startVehicles - count vehicles;
_endUnits = _startUnits - count allUnits;

systemChat format ["AI Vehicle & Crew Monitor Loaded - %1 | %2", _endVehicles, _endUnits];

 

Keep in mind that vehicles also includes "weaponHolderSimulated." I'm assuming these will get picked up in your _EmptyStartingVehicles variable, but you might want to test it to make sure.

 

Anyway, what happened to the sectors?

 

 

Thank you for the suggestion - I will try to implement it next time I have some time.

 

I looked at the vehicles page and Im not sure what types of items/vehicles/etc "weaponHolderSimulated" applies to.  If it refers to dead bodies or weapons on the ground, then its not really applicable to how I make missions.

 

As for the Sectors....

 

From what I understand, SpawnAI modules which are linked to the SectorTactics module will attack sectors from closest to farthest.  Therefore, for play testing purposes, I wanted to make a script which would display sectors from closest to farthest.  I figured it would provide a good opportunity to learn how to do it.

 

I already have the ability to find and sort sectors - I use it to create a transport helicopter which takes infantry spawned by a SpawnAI module to the closest neutral/enemy sector.  I just dont know how to display it on the screen.

 

SpawnAI Sector Control Heli Transport:

Spoiler

/*==========================================================================================

                Arma III - Spawn AI Helicopter Transport

 

Created by Blitzen

===========================================================================================

 

* Creates a helicopter which transports infantry to the nearest neutral or enemy sector

 

* The helicopter's spawn position and return location is the same position as the spawn module

 

* Call with (Spawn Module): _this execVM "Scripts\SpawnAIModule\SpawnAI_Transport_Heli.sqf"

===========================================================================================*/

//Define Variables

 

params[ "_group", "_module", "_groupData" ];

 

//Create Variables to avoid scoping issues
_EnemySide1 = [];

 

_EnemySide2 = [];

 

_FriendlySide = [];

 

_SelectedSector = [];

 

_Helo = [];

 

_HeloCrew = [];

 

_SavedSelectedSector = [];

 

//Define Enemy/Friendly sides and Spawn Helicopter

 

//West
//---------------------------------------

if ( side _group isEqualTo West ) then {

 

    _EnemySide1 = East;

 

    _EnemySide2 = East;

 

    _FriendlySide = West;

 

    _HeloCrew = createGroup West;
    
    _Helo = [getPos _Module, getDir _Module, "B_Heli_Transport_01_F", WEST] call BIS_FNC_spawnVehicle;

};

 

//East
//---------------------------------------

if ( side _group isEqualTo East ) then {

 

    _EnemySide1 = West;

 

    _EnemySide2 = Resistance;

 

    _FriendlySide = East;

    

    _HeloCrew = createGroup East;

 

    _Helo = [getPos _module, getDir _module, "O_Heli_Light_02_F", EAST] call BIS_FNC_spawnVehicle;

};

//Independent
//---------------------------------------

if ( side _group isEqualTo Independent ) then {

 

    _EnemySide1 = East;

 

    _EnemySide2 = East;

 

    _FriendlySide = Resistance;

 

    _HeloCrew = createGroup Independent;
    
    _Helo = [getPos _module, getDir _module, "I_Heli_Transport_02_F", RESISTANCE] call BIS_FNC_spawnVehicle;
    
};

//Assign the crew to the Helicopter group & assign cargo to the Helicopter

 

{[_x] joinSilent _heloCrew;} forEach crew (_helo select 0);    

 

{_x assignAsCargo (_helo select 0); _x moveInCargo (_helo select 0);} forEach units _group;

 

(_helo select 0) setUnloadInCombat [false, false];

 

//Find the Closest Neutral or Enemy Sector

_sectors = +BIS_fnc_moduleSector_sectors apply{ [ _x distanceSqr _module, _x ] };

 

_sectors sort true;                                // Sort in Ascending order  (closest sector to farthest sector)

 

_index = _sectors findIf {

    _x params[ "", "_sector" ];
    
    _sectorOwner = _sector getVariable [ "owner", sideUnknown ];
    
    _sectorOwner isEqualTo sideUnknown || _sectorOwner isEqualTo _EnemySide1 || _sectorOwner isEqualTo _EnemySide2                    
};

//If the Helicopter Unit's side controls all the sectors at once then _index will return as -1; need to account for that in the script

if (_index < 0) then {
    
    _Sectors sort false;                            // Sort in descending order (farthest sector to closest sector)
    
    _index = _sectors findIf 
        
        {
        
        _x params[ "", "_sector" ];
        
        _sectorOwner = _sector getVariable[ "owner", sideUnknown ];        
        
        _sectorOwner isEqualTo _FriendlySide                // Include Friendly sectors in the sort since the Helicopter Unit's side owns them all
        
        };

    _SelectedSector = getPos ( _sectors select _index select 1 );


} else {

 

    _SelectedSector = getpos ( _sectors select _index select 1 );        // If the Helicopter Unit's side does not own all of the sectors then target the closest neutral/Enemy sector

 

};

//Save the Targeted Sector to avoid errors with the point changing mid target/scan

_SavedSelectedSector = _SelectedSector;

 

//Find a flat position around the LZ marker & create an HPad there.

 

_flatPos = [ _SavedSelectedSector, 0, 550, 10, 0, 0.3, 0] call BIS_fnc_findSafePos;

 

_hPad = createVehicle ["Land_HelipadEmpty_F", _flatPos, [], 0, "NONE"];

 

//Give the helicopter an unload waypoint onto the helipad

    _heloWp = _HeloCrew addWaypoint [_hPad, 0];

 

    _heloWp setWaypointType "TR UNLOAD";
   
    _heloWp setWaypointBehaviour "CARELESS";
   
    _heloWp setWaypointCombatMode "BLUE";
   
    _heloWp setWaypointSpeed "FULL";
   
    _heloWp setWaypointStatements ["true", "(vehicle this) LAND 'LAND';"];

 

//Wait until the helicopter is touching the ground before ejecting the cargo    

 

WaitUntil {isTouchingGround (_Helo select 0) || {!canMove (_Helo select 0)}};

 

//Eject the Infantry    

 

{unAssignVehicle _x; _x action ["eject", vehicle _x]; sleep 0.5;} forEach units _group; //Eject the cargo

 

//Wait Until the infantry group is no longer in the helicopter before assigning a new WP to the helicopter

 

WaitUntil {{!alive _x || !(_x in (_Helo select 0))} count (units _group) == count (units _group)};

 

//Delete the helipad

 

{deletevehicle _hPad};

 

//Give the helicopter a waypoint to return to base and then delete the helicopter and crew
   
    _heloWp = _HeloCrew addWaypoint [getpos _module, 0];
    
    _heloWp setWaypointType "MOVE";
    
    _heloWp setWaypointBehaviour "AWARE";
    
    _heloWp setWaypointCombatMode "BLUE";
    
    _heloWp setWaypointSpeed "FULL";
    
    _heloWp setWaypointStatements ["true", "{deleteVehicle _x;} forEach crew (vehicle this) + [vehicle this];"];

 

//End
 

 

 

Share this post


Link to post
Share on other sites
10 minutes ago, Blitzen88 said:

Im not sure

 

Weapon holders are proxy vehicles that hold inventory items when they are on the ground. For example, when you kill an AI, they drop their rifle, etc., and you can see it on the ground next to them. These items are being held in a weapon holder.

 

If at some point in your mission there are dead AI, then their weapon holders will be picked up in vehicles. I'm fairly certain that your filter for empty vehicles will catch them, though, as they will return a crew count of 0.

Share this post


Link to post
Share on other sites
36 minutes ago, Harzach said:

 

Weapon holders are proxy vehicles that hold inventory items when they are on the ground. For example, when you kill an AI, they drop their rifle, etc., and you can see it on the ground next to them. These items are being held in a weapon holder.

 

If at some point in your mission there are dead AI, then their weapon holders will be picked up in vehicles. I'm fairly certain that your filter for empty vehicles will catch them, though, as they will return a crew count of 0.

The EmptyStartingVehicles is not included in the loop. Its purpose is to capture empty vehicles at the mission start; those vehicles are often times used for decoration. 
 

Im not worried to much about the Weapon holders. I run the Vanilla Garbage Collector and I would think that it deletes these anyways..?

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

×