Jump to content

Recommended Posts

Hey.
I have one problem. How to make Insignia work properly. 

 

this works just fine as long as you're alive. But when the player dies and then spawn again that insignia is gone.

how to fix this bug?

Share this post


Link to post
Share on other sites

You need to add a respawn EH. The Bis_fnc_setUnitInsignia is rotten, false persistent on respawn but displaying nuts.

 

So, one possibility, in init field of the player:

 

[this,"MANW"] call BIS_fnc_setUnitInsignia;

this addEventHandler ["respawn", {

  [_this select 0,""] call BIS_fnc_setUnitInsignia;                 comment "you need to discard the previous invisible one!";

  [_this select 0,"MANW"] call BIS_fnc_setUnitInsignia

}];

 

In MP, not tested on clients. Not sure the setObjectTextureGlobal is OK now. So, should work as is, or try to add a locality condition:
if (local (this) then {<the code here>}

Never remoteExec this function.

  • Thanks 1

Share this post


Link to post
Share on other sites

I did not get to work in Multiplayer. Is it possible for it to build a script into a file?

 

Share this post


Link to post
Share on other sites
while {true} do {  

		_insignia = "YourInsignia";
		_texture = getText(configFile >> "CfgUnitInsignia" >> _insignia >> "texture");
		[player, ""] call BIS_fnc_setUnitInsignia; //need first to manual unset insignia 'cause BIS_fnc_setUnitInsignia is broken
		[player, _insignia] call BIS_fnc_setUnitInsignia;
		waitUntil {uiSleep 1;(((getObjectTextures player) find _texture) == -1)}; 
  
};

put this on init.sqf
this should also work on multiplayer, just pass your desired insignia class name as _insignia
it cycle continuosly because there are other situations than respawn where insignia could got reset (i.e.: entering virtual arsenal and changin the uniform)

Share this post


Link to post
Share on other sites

^^ Noo... A while loop is not needed. You should never use waitUntil inside a while loop. This is actually the first time I've seen it. You can add a conditional check instead if needed. It is also a good idea to have a sleep inside there. It is also pointless to define those variables over and over (loop) since they do not change. Define them before, above the while loop. As for the arsenal, you can detect when closed. Use InventoryClosed EH.

https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#InventoryClosed

  • Thanks 1

Share this post


Link to post
Share on other sites
12 hours ago, Casio91Fin said:

I did not get to work in Multiplayer. Is it possible for it to build a script into a file?

 

MP should work. Did you disable AI in lobby? What insignia did U test? Are U on dedicated or hosted server? What is the problem? What players can see , when?

Share this post


Link to post
Share on other sites
2 hours ago, HazJ said:

^^ Noo... A while loop is not needed. You should never use waitUntil inside a while loop. This is actually the first time I've seen it. You can add a conditional check instead if needed. It is also a good idea to have a sleep inside there.

 

Disagree. If no EH available a loop can be mandatory. Then one (or two if reverse condition is needed) waitUntil with pause inside its code is better than a running loop with several if then. This kind of endless loop is already scheduled anyway.

Share this post


Link to post
Share on other sites
4 hours ago, HazJ said:

It is also pointless to define those variables over and over (loop) since they do not change. Define them before, above the while loop.

you're right, i took this from script where i needed dynamic insignias without knowing OP intentions, consider it as a concept, but actually if you have static insignias it is a good advice

 

Quote

As for the arsenal, you can detect when closed. Use InventoryClosed EH.

yes, this is a valid alternative

i proposed a cycle 'cause as said there are various situations where insignia get lost, with this you're sure to cover every possibility with a single solution

 

Quote

You should never use waitUntil inside a while loop.

i'm self-educated on sqf and still learning, but i've seen this on various scripts

so, why this should be not used?

how do you would rewrite my function?

  • Like 1

Share this post


Link to post
Share on other sites

@pierremgi

1. Dedicated server.

 

2. Player cant see.

 

3. I forgot to remove it "disable AI". but did not help much.

 

@tRiKy_ch

1. I need at least two teams with their own insignia's (Blue team / Red Team) 

 

2.(If it is possible to add to a third party (Green team) optional)

 

And I forgot to mention that I use my own Insignia image.

Name "Blue_Team" and  "Red_Team".

 

Edited by Casio91Fin
Insignia image and name

Share this post


Link to post
Share on other sites

Since the original BIS function does not work in MP with non-addon based insignia image, I have modified them for proper MP/JIP. I have split them into a local and a global function:

/*
    MF_fnc_setUnitInsignia

    Argument: Global
    Effect: Local

    Description:
        Sets unit insignia (e.g., shoulder insignia on soldiers)

    Parameter(s):
        0: OBJECT - unit
        1: STRING - CfgUnitInsignia class. Use an empty string to remove current insignia.

    Returns:
        BOOL - true if insignia was set
*/

#define DEFAULT_MATERIAL "\a3\data_f\default.rvmat"
#define DEFAULT_TEXTURE "#(rgb,8,8,3)color(0,0,0,0)"

params ["_unit", "_class", ["_forceLoad", false]];

private _isRefresh = _class isEqualTo "REFRESH";

if (_isRefresh) then {
    _class = _unit getVariable ["MF_fnc_setUnitInsignia_class", ""];
};

// --- load texture from config.cpp or description.ext
private _cfgInsignia = [["CfgUnitInsignia", _class], configNull] call BIS_fnc_loadClass;

// --- check if insignia exists
if (configName _cfgInsignia != _class) exitWith {
    [
        "'%1' is not found in CfgUnitInsignia. Available classes: %2", 
        _class, 
        ("true" configClasses (configFile >> "CfgUnitInsignia") apply {configName _x}) 
        + 
        ("true" configClasses (missionConfigFile >> "CfgUnitInsignia") apply {configName _x})
        +
        ("true" configClasses (campaignConfigFile >> "CfgUnitInsignia") apply {configName _x})
    ] 
    call BIS_fnc_error; 
    false
};

private _set = false;

// --- find insignia index in hidden textures
{
    if (_x == "insignia") exitWith {
        // --- make it safe in scheduled
        isNil {
            // --- set insignia if not set
            if (_isRefresh or {_forceLoad} or {(_unit getVariable ["MF_fnc_setUnitInsignia_class", ""]) != _class}) then {
                _unit setVariable ["MF_fnc_setUnitInsignia_class", [_class, nil] select (_class isEqualTo ""), false];    
                _unit setObjectMaterial [_forEachIndex, getText (_cfgInsignia >> "material") call {[_this, DEFAULT_MATERIAL] select (_this isEqualTo "")}];
                _unit setObjectTexture [_forEachIndex, getText (_cfgInsignia >> "texture") call {[_this, DEFAULT_TEXTURE] select (_this isEqualTo "")}];
                _set = true;
            };
        };
    };
} forEach getArray (configFile >> "CfgVehicles" >> getText (configFile >> "CfgWeapons" >> uniform _unit >> "ItemInfo" >> "uniformClass") >> "hiddenSelections");

_set

The global function:

/*
    Argument: Global
    Effect: Global

    Description:
        Sets unit insignia (e.g., shoulder insignia on soldiers)

    Parameter(s):
        0: OBJECT - unit
        1: STRING - CfgUnitInsignia class. Use an empty string to remove current insignia.

    Returns:
        BOOL - true if insignia was set
*/

params ["_unit", "_class", ["_force", true]];

if (_class isEqualTo "REFRESH") then {
    _class = _unit getVariable ["MF_fnc_setUnitInsignia_class", ""];
};

// For remotes
[_unit, _class, _force] remoteExecCall ["MF_fnc_SetUnitInsignia", -clientOwner];
// For JIPs
_unit setVariable ["MF_fnc_setUnitInsignia_class", _class, true];
// We run it locally manually to get return value.
//  using REFRESH here after setVariable to ensure _force is respected.
[_unit, "REFRESH", _force] call MF_fnc_SetUnitInsignia;

To ensure proper loading for JIPs and also for player changing uniform, I run the following post-init:

// Updates client insignias from broadcast data
{
    private _insignia = _x getVariable ["MF_fnc_setUnitInsignia_class", ""];
    if (not (_insignia isEqualTo "")) then {
        [_x, _insignia, true] call MF_fnc_setUnitInsignia;
    };
} forEach allUnits;

// For simplicity only handle local player changing loadouts. E.g. not AI's that has later been changed by scripting.
if (hasInterface) then {
    [] spawn {
        waitUntil {sleep 0.1; local player};
        MF_fnc_setUnitInsignia_lastUniform = uniformContainer player;
        player addEventHandler ["InventoryClosed", {
            params ["_unit", "_targetContainer"];
            private _curUniform = uniformContainer _unit;
            if (_curUniform != MF_fnc_setUnitInsignia_lastUniform) then {
                MF_fnc_setUnitInsignia_lastUniform = _curUniform;
                if (not (isNull _curUniform)) then {
                    [_unit, "REFRESH", true] call MF_fnc_setUnitInsigniaGlobal;
                };
            };
        }];
    };
};

The corresponding CfgFunction entry is:

class CfgFunctions {
    class MF_Insignia {
        tag = "MF";
        class Insignia {
            file = "functions";
            class setUnitInsignia {};
            class UnitInsignia_PostInit {
                postInit = 1;
            };
            class setUnitInsigniaGlobal {};
        };
    };
};

 

  • Like 1

Share this post


Link to post
Share on other sites

@pierremgi There is no need for while loop in this case. Why use waitUntil in while loop when you can make the waitUntil loop itself by returning false at the end. There is an EH available as well as stated in my post above.

Share this post


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

@pierremgi There is no need for while loop in this case. Why use waitUntil in while loop when you can make the waitUntil loop itself by returning false at the end. There is an EH available as well as stated in my post above.

Yes, but I answered at your general consideration about "never" using that: You should never use waitUntil inside a while loop. This is actually the first time I've seen it.

 

Share this post


Link to post
Share on other sites

Are you referring to the waitUntil inside the while loop? It isn't good practice, imo. Especially since there are other ways. The way @tRiKy_ch was using the waitUntil inside the while loop was pointless and not worth it.

20 hours ago, pierremgi said:

is better than a running loop with several if then. This kind of endless loop is already scheduled anyway.

Not always true. I did mention using a sleep in there. A singular if statement would of sufficed, if needed but as I said. None of it was was needed. EHs are available to both of the questions. Also... I don't reply in a general consideration to threads unless needed. My reply was directly to his reply.

Share this post


Link to post
Share on other sites

I found some kind of "maybe" solution to the spawn problem and pictures, but the problem is that everyone get the same pictures.

I do not know if this page is anything useful:

.

Share this post


Link to post
Share on other sites

Maybe their rank is the same? Use the setRank command to change this.

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

Alternative would be:

player setVariable ["unitInsignia", "path/filename.paa"]; // set on each player

{
	[_x, (player getVariable "unitInsignia")] call BIS_fnc_setUnitInsignia;
} forEach allUnits;

You can also make a nested array with something like:

_units =
[
	[unit1, "insigniaIcons/icon1.paa"],
	[unit2, "insigniaIcons/icon2.paa"],
	[unit3, "insigniaIcons/icon3.paa"]
];

{
	_unit = _x select 0;
	_insignia = _x select 1;
	[_unit, _insignia] call BIS_fnc_setUnitInsignia;
} forEach _units;

 

  • Like 1

Share this post


Link to post
Share on other sites

@Casio91Fin it depends on your scenario, you have a defined rank for every player (i.e: clan) or ranks are defined mission by mission? tell us more about your needs

in my case (clan) i used to read them from squad.xml

setUnitRank could be very useful but consider its limited to 7 ranks

 

20 hours ago, HazJ said:

@pierremgi ...when you can make the waitUntil loop itself by returning false at the end

ok, right, now i see it ;)

 

btw it has to not be a so bad practice as you can see it on the wiki (example 4)

  • Like 1

Share this post


Link to post
Share on other sites

I don't see the point of the waitUntil discussion. You want to replace it by a condition and a sleep to make sure the script only runs once per frame.

Well that's exactly what waitUntil does. Just more compact and easier to read.

Share this post


Link to post
Share on other sites

@tRiKy_ch

Skenario type: TVT

1. (Ranks) I know it is very limited but also useful, but not in this case. (maybe in the future)

2. squad.xml is pretty good and works, but if the players do not have squad.xml. That's why Insignia should be good. https://community.bistudio.com/wiki/File:A3_insignia_infantry.jpg

 

 

 

Share this post


Link to post
Share on other sites

@HazJ

player name is (unit_x) I understood this but where i put this 

On 22.8.2018 at 9:38 AM, HazJ said:

{ [_x, (player getVariable "unitInsignia")] call BIS_fnc_setUnitInsignia; } forEach allUnits;

and

On 22.8.2018 at 9:38 AM, HazJ said:

_units = [ [unit1, "insigniaIcons/icon1.paa"], [unit2, "insigniaIcons/icon2.paa"], [unit3, "insigniaIcons/icon3.paa"] ]; { _unit = _x select 0; _insignia = _x select 1; [_unit, _insignia] call BIS_fnc_setUnitInsignia; } forEach _units;

 

Share this post


Link to post
Share on other sites

unit1, unit2, etc is the var name of the unit. You can set this in the Editor.

Share this post


Link to post
Share on other sites
On 8/23/2018 at 5:14 PM, Casio91Fin said:

all scripts?

What? Where are you stuck? Re-read my post and let me know if you still need help.

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

×