Jump to content
scottb613

SCO SP Stupid Little Squad Status Script

Recommended Posts

Hi Folks,

 

For today's contribution - a stupid little status screen to help manage your SP Squad a little better.

 

Copy the code into your own SQF - call it however you like (no args) - it should work fine... 

 

I gotta say - seeing a DOA Unit Status staring you in the face for the duration - especially if you did something to cause it - seems to add some gravity to the mission. 

 

 

  • // Overview: A basic status report of units in player squad - Fitness, First Aid Kits, and primary weapon Magazines.

 

  • // Requires: Simply call SCOsquadStat.sqf by whatever means you choose - I use addAction to player.

 

  • // Note: Only tested in single player.

 

  • // Given: First Run - records all player units in a global variable for DOA reference. 
  • // Given: You should run SCOsquadStat.sqf once at mission start - before losses - or DOA records won't be valid.
  • // Given: Queries the status of alive player units - for Fitness, First Aid Kits, and Magazines.
  • // Given: Fit - statistic quantified so you don't focus on the numbers.
  • // Given: Fit - based on damage - 100/75 AOK | 75/50 LGT | 50/25 SER | 25/0 CRT | 0/0 DOA.
  • // Given: Fit - AOK = All Good or Just a Scratch | LGT = Lightly Injured | SER = Seriously Injured | CRT = Critically Injured | DOA = Dead On Arrival.
  • // Given: Fit - LGT indicates in Green | SER indicates in Yellow | CRT indicates in Red status lines.
  • // Given: Fit - DOA drops Fak/Mag count and dims status line - memorializes the unit's last name.
  • // Given: Fak - pulled from "401" configFile entry (panther42).
  • // Given: Mag - only counts Primary Weapon Magazines.
  • // Given: Added Primary Weapon Name to alive units.

 

  • // Suggestion: Place this in one of your initialization scripts to run it once at startup: [] execVM "Scripts\SCOsquadStat.sqf";

 

 

 

Hint Output looks like this:

 

STAT.jpg

 

 

Regards,
Scott

 

 

FULL SCRIPT:

Spoiler

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

// FILE NAME: SCOsquadStat.sqf
// ARGS: None
// AUTHOR: Scottb613

// OVERVIEW: A basic status report of units in player squad - Health, Faks, and primary weapon Mags.

// REQUIRES: Simply call SCOsquadStat.sqf by whatever means you choose - I use addAction to player.

// NOTE: Only tested in single player.

// GIVEN: First Run - records all player units in a global variable for DOA reference. 
// GIVEN: You should run SCOsquadStat once at mission start (init) - before losses - or DOA not valid.
// GIVEN: Queries the status of alive player units - for Health, Faks, and Mags.
// GIVEN: Fit - stat numbers rounded off so you don't focus on chasing numbers.
// GIVEN: Fit - AOK = All Good or a Mere Scratch | LGT = Lightly Injured | SER = Seriously Injured.
// GIVEN: Fit - CRT = Critically Injured | DOA = Dead On Arrival.
// GIVEN: Fit - based on damage - 100/75 AOK | 75/50 LGT | 50/25 SER | 25/0 CRT | DOA.
// GIVEN: Fit - LGT indicates in Green | SER indicates in Yellow | CRT indicates in Red - status lines.
// GIVEN: Fit - DOA drops Fak/Mag count and dims the units status line - memorializes last name.
// GIVEN: Fak - First Aid Kits pulled from 401 configFile entry (panther42).
// GIVEN: Mag - only count Primary Weapon Magazines.
// GIVEN: Added Primary Weapon Name to alive units.

// SUGGESTION: Add to init file to validate squad members:    [] execVM "Scripts\SCOsquadStat.sqf";

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Check if the global variable `SCOplayerUnits` exists
if (isNil "SCOplayerUnits") then {
    // On first run, store all player units in the global variable
    SCOplayerUnits = [];
    SCOplayerUnitsLastNames = []; // Add a global list to store last names
    // {
        SCOplayerUnits pushBack _x;

        // Extract the last name and store it
        private _fullName = name _x;
        private _nameParts = _fullName splitString " ";
        private _lastName = if (count _nameParts > 1) then {_nameParts select 1} else {_nameParts select 0}; 
        SCOplayerUnitsLastNames pushBack _lastName;

    } forEach units group player;
};

// Initialize local variables
private _hint = "";
private _unitCnt = 0;

// Function to pad numbers (as per your original)
_fnc_stringPadding = {
    params[
        [ "_string", "", [ "", 0 ] ],
        [ "_numDigits", 0, [ 0 ] ]
    ];

    if (_string isEqualType 0) then {
        _string = str _string;
    };

    private _padding = "000";
    _padding select[0, _numDigits - count _string];
};

// Function to get unit position ID
_fnc_getUnitPositionId = {
    params[ "_unit" ];
    private _vvn = vehicleVarName _unit;
    _unit setVehicleVarName "";
    private _str = str _unit;
    _unit setVehicleVarName _vvn;
    _str select[(_str find ":") + 1];
};

// Iterate over all units in the global list
{
    _unit = _x;

    // Get unit's last name from the stored list
    private _lastName = SCOplayerUnitsLastNames select _forEachIndex;

    if (!alive _unit) then {
        // Only mark DOA and do not remove the unit from the list
        _unitCnt = _unitCnt + 1;

        // Format DOA status with padding and include last name
        private _unitFormPos = format["%1%2", [_unitCnt, 2] call _fnc_stringPadding, _unitCnt];
        _hint = format[
            "%1<t align='left' color='#474747'>%2 || Fit: DOA || %3</t><br/>%4",
            _hint,
            _unitFormPos,
            _lastName,
            ""
        ];
    } else {
        // Fit - If the unit is alive, update the status
        _unitCnt = _unitCnt + 1;

        // Get unit health and convert to fitness label
        private _health = round((1 - damage _unit) * 100);
        private _fitLabel = switch true do {
            case (_health >= 75): { "AOK" };
            case (_health >= 50): { "LGT" };
            case (_health >= 25): { "SER" };
            default { "CRT" };
        };

        // Set color based on fitness label
        private _fitColor = switch _fitLabel do {
            case "AOK": { "#7D7F7C" };  // Medium Grey
            case "LGT": { "#98fb98" };  // Pastel Green
            case "SER": { "#FFFF99" };  // Pastel Yellow
            case "CRT": { "#FF9999" };  // Pastel Red
            default { "#7D7F7C" };  // Default Medium Grey
        };

        // Mag - Count Primary Weapon Magazines
        private _priWeapon = primaryWeapon _unit;
        private _compMags = compatibleMagazines _priWeapon;
        private _magCnt = { _x in _compMags } count magazines _unit;
        _magCnt = format["%1%2", [_magCnt, 2] call _fnc_stringPadding, _magCnt];

        // Fak - Count FirstAidKits without using classnames
        private _fakCnt = {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 401} count (items _unit + assignedItems _unit);
        _fakCnt = format["%1%2", [_fakCnt, 2] call _fnc_stringPadding, _fakCnt];

        // Get unit formation position
        private _unitFormPos = format["%1%2", [_unitCnt, 2] call _fnc_stringPadding, _unitCnt];

        // Get the primary weapon's display name and process it
        private _priWeaponName = getText(configFile >> "cfgWeapons" >> _priWeapon >> "displayName");

        // Remove any text after "(" and the "(" itself
        private _parenPos = _priWeaponName find "(";
        if (_parenPos > -1) then {
            _priWeaponName = _priWeaponName select [0, _parenPos];
        };

        // Split the display name into parts
        private _priWeaponNameParts = _priWeaponName splitString " ";

        // Take the first two parts and concatenate, limiting total length to 8 characters
        private _shortPriWeaponName = (_priWeaponNameParts select 0);
        if (count _priWeaponNameParts > 1) then {
            _shortPriWeaponName = format["%1 %2", _shortPriWeaponName, _priWeaponNameParts select 1];
        };
        _shortPriWeaponName = _shortPriWeaponName select [0, 8];

        // Format Output with color and add the processed primary weapon name
        _hint = format[
            "%1<t align='left' color='%2'>%3 || Fit: %4 || Fak: %5 || Mag: %6 || %7</t><br/>",
            _hint,
            _fitColor,
            _unitFormPos,
            _fitLabel,
            _fakCnt,
            _magCnt,
            _shortPriWeaponName
        ];
    };

} forEach SCOplayerUnits;  // Use the global list of player units

// Display Status
hint parseText _hint;

 

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
20 hours ago, scottb613 said:

Hi Folks,

 

For today's contribution - a stupid little status screen to help manage your SP Squad a little better. At this time - I am only counting vanilla first aid kits. If someone gives me a complete list of valid class names of FAK's - from major DLC/Mods - I could count them as well.

 

 

What I'm using for my Heal & revive module:
 

allFAK = ["FirstAidKit","CSLA_Ob80","gm_ge_army_gauzeCompress","gm_gc_army_medkit","gm_gc_army_gauzeBandage","gm_ge_army_gauzeBandage","US85_FAK","vn_b_item_firstaidkit","vn_o_item_firstaidkit","gm_ge_army_burnBandage","r3f_soins_item_bandage","SPE_GER_FirstAidKit","SPE_US_FirstAidKit"];

allMedKit = ["Medikit","US85_MediKit","gm_ge_army_medkit_80","vn_b_item_medikit_01","gm_gc_army_medbox","r3f_soins_item_defibrillateur","CSLA_MediKit_Z80","r3f_soins_item_sang","SPE_GER_Medkit","SPE_US_Medkit"];

 

Covering all official DLCs so far,  and mods like Unsung, CUP, RHS, R3F, IFA3 (some of them uses vanilla class names of these items)
I'm also interested in other exotic FAK or Medikit, if any.

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

Hi Pierre,

 

Thank you kindly for your fine help.

😉

 

Updated the script in my first post.

 

  • Added an array of FAK classnames - easily editable.
  • Added DOA units last name - to make you feel even more responsible for them. They're just a number until you pull their dog tags. 

 

Regards,
Scott

Share this post


Link to post
Share on other sites

You shouldn't need to keep arrays of fak or medikit.  This becomes more labor than needed if/when names are changed or new DLC added.  They should all inherit correctly in order to work properly and you can just read from the config:

Spoiler

lass ItemInfo: InventoryFirstAidKitItem_Base_F
class InventoryFirstAidKitItem_Base_F: InventoryItem_Base_F
		{
			type = 401;
		};
		
class ItemInfo: MedikitItem
class MedikitItem: InventoryItem_Base_F
		{
			type = 619;
			allowedSlots[] = {801, 701, 901};
		};

 

Just use the following or similar. You can adjust as needed

_hasFAK = ((((assignedItems _unit) + (items _unit)) findIf {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 401}) > -1);
_hasMedikit = ((((assignedItems _unit) + (items _unit)) findIf {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 619}) > -1);

  • Like 6

Share this post


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

You shouldn't need to keep arrays of fak or medikit.  This becomes more labor than needed if/when names are changed or new DLC added.  They should all inherit correctly in order to work properly and you can just read from the config:

  Reveal hidden contents


lass ItemInfo: InventoryFirstAidKitItem_Base_F
class InventoryFirstAidKitItem_Base_F: InventoryItem_Base_F
		{
			type = 401;
		};
		
class ItemInfo: MedikitItem
class MedikitItem: InventoryItem_Base_F
		{
			type = 619;
			allowedSlots[] = {801, 701, 901};
		};

 

Just use the following or similar. You can adjust as needed

_hasFAK = ((((assignedItems _unit) + (items _unit)) findIf {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 401}) > -1);
_hasMedikit = ((((assignedItems _unit) + (items _unit)) findIf {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 619}) > -1);

 

Hi...

 

Thanks for the interest - let me look into this. I'm always looking for better ways of doing things.

 

Regards,

Scott

Share this post


Link to post
Share on other sites
15 hours ago, panther42 said:

You shouldn't need to keep arrays of fak or medikit.  This becomes more labor than needed if/when names are changed or new DLC added.  They should all inherit correctly in order to work properly and you can just read from the config:

  Reveal hidden contents


lass ItemInfo: InventoryFirstAidKitItem_Base_F
class InventoryFirstAidKitItem_Base_F: InventoryItem_Base_F
		{
			type = 401;
		};
		
class ItemInfo: MedikitItem
class MedikitItem: InventoryItem_Base_F
		{
			type = 619;
			allowedSlots[] = {801, 701, 901};
		};

 

Just use the following or similar. You can adjust as needed

_hasFAK = ((((assignedItems _unit) + (items _unit)) findIf {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 401}) > -1);

_hasMedikit = ((((assignedItems _unit) + (items _unit)) findIf {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 619}) > -1);

 

Hi...

 

Gracias Amigo - much better - tested on Vanilla and SOG - looks good to me.

😉

 

  • Eliminated FAK class names.
  • Updated code in initial post. 

 

 

Regards,

Scott

  • Like 1

Share this post


Link to post
Share on other sites
10 hours ago, panther42 said:

You shouldn't need to keep arrays of fak or medikit.  This becomes more labor than needed if/when names are changed or new DLC added.  They should all inherit correctly in order to work properly and you can just read from the config:

  Reveal hidden contents


lass ItemInfo: InventoryFirstAidKitItem_Base_F
class InventoryFirstAidKitItem_Base_F: InventoryItem_Base_F
		{
			type = 401;
		};
		
class ItemInfo: MedikitItem
class MedikitItem: InventoryItem_Base_F
		{
			type = 619;
			allowedSlots[] = {801, 701, 901};
		};

 

Just use the following or similar. You can adjust as needed

_hasFAK = ((((assignedItems _unit) + (items _unit)) findIf {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 401}) > -1);
_hasMedikit = ((((assignedItems _unit) + (items _unit)) findIf {getNumber (configFile >> "cfgWeapons" >> _x >> "ItemInfo" >> "type") == 619}) > -1);

 

wow nice!

Any list of itemInfo types? I didn't find that on web.

Share this post


Link to post
Share on other sites

Hi Folks,

 

Just a quick question - I can manipulate size and color - in hints - can I not use a "fixed width font" as well?

 

I had tried and it failed - perhaps it was me?

 

Not having perfectly aligned columns - does bother me.

 

Thanks.

 

Regards,

Scott

Share this post


Link to post
Share on other sites
9 hours ago, pierremgi said:

 

wow nice!

Any list of itemInfo types? I didn't find that on web. 

There are multiple ways to do this.  I use the following:

Spoiler

ItemInfoArrayHash = createHashMap;  
ItemInfoArray = [];  
   
"true" configClasses (configFile >>"cfgWeapons") apply {   
    
 ItemInfoArrayHash insert [[configName _x, getNumber (_x >> "ItemInfo" >> "type")]]; 
 ItemInfoArray pushBackUnique (getNumber (_x >> "ItemInfo" >> "type")); 
};   
  
 
diag_log format ["types: %1",ItemInfoArray];
{if (_y == 401) then { diag_log format ["%1",[_x,_y]] }} forEach ItemInfoArrayHash;

 

This can be used in the Debug console.  I gave example of using "type" equals 401 (FAK).

The reason I made a separate array with pushBackUnique just for the "type" is the immense number of cfgWeapons, especially if you have many mods/dlc's added.  If you tried to list all it exceeds the clipboard and diag_log character limits.  The code will make it easier for you to see the entire list of "type" numbers.

I wanted to create the hashmap using the "type" number, as there are less, but this does not work as "Inserting an element with a key that already exists inside the HashMap will overwrite the existing key."

You can still work multiple ways with the hashmap as created above.

 

Sorry Scott, I see your post above but I normally don't mess around with what you are asking...

  • Like 3

Share this post


Link to post
Share on other sites
On 8/25/2024 at 5:32 PM, panther42 said:

There are multiple ways to do this.  I use the following:

This can be used in the Debug console.  I gave example of using "type" equals 401 (FAK).

 

What I didn't find, this list:

cfgWeapons itemInfo types are :

[0,620,619,401,616,801,701,605,101,201,301,302,621]

 

0: weapons + some itemRadio ... difficult to say

620: toolkits repairKits,US85 PRC77, R3F brouilleur, GM boltcutter, CSLA RF10  , so that repairs in most of the cases

619: MediKits  most of the time + R3F thingies 😏

401: FAK bandages, CSLA_Documents_item

616: NVGs most of the time, but also several LIB_GER_Gloves, LIB_Mohawk or SPE_Flashlight_base...

801: uniforms... a lot!

701: vests

605: headgears , headsets, helmets...

101: silencers, suppressors, bayonets, and mounted pieces on muzzles

201: optics

301: lasers, flashlights

302: grips, bipods and miscelaneous items low mounted

621: UAV terminals

 

So, 401, 616, 619 , 620 (mainly) are sometimes used for other item types than what you are waiting for, especially on mods (less for DLCs). If you don't want to keep some precise lists updated (as I did), aiming for a Swiss knife code, you risk to script some weird use for some inadequate item.

  • Like 1

Share this post


Link to post
Share on other sites

Hi Folks,

 

Added the primary weapon name to alive units - just to keep track of what you have.

 

Script updated.

 

Regards,
Scott

  • Like 1

Share this post


Link to post
Share on other sites

Hi Folks,

 

Just an updated image on the current state of the status screen - 1 lightly injured - 1 critically injured - 1 dead. Code in first post updated.

 

Status-Screen.jpg

 

Regards,
Scott

  • Like 1

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

×