Jump to content
Sign in to follow this  
Nebulazer

Need help with my GUI for displaying level and money

Recommended Posts

I am working on a GUI for my mission that will display how much money you have and what level you are but I am running into some issues and i cant find anything on how to make the GUI display variables, I have read KK's GUI tutorials and Icemans and watched videos and read the BI wiki on cutRsc and GUI but none of them really explains how to simply put 2 variables at the bottom of your players screen. I have the UI possitioned already but i cant make the two UI that i have work simultaneously together and I am not sure what needs to be done for the text to be replaced with variables since this is in the description.ext and the syntax is a little different from sqf. Here is what I have, hopefully someone can assist me with making it do what i need it to then other people who have this same problem can reference this post for help.

In the description.ext

class RscTitles
{
	class DollarTitle
	{
		idd = 1;
		duration = 999999;
		class controls
		{
				class DollarControl
				{
						idc = 101;
						type = 0;
						style = 2;
						x =  safeZoneX + safeZoneW - 0.2 * 3 / 4;
						y = safeZoneY + safeZoneH - 0.1;
						w = 0.2;
						h = 0.2 * 3 / 4;
						font = "EtelkaNarrowMediumPro";
						sizeEX = 0.03;
						colorBackground[] = {0,0,0,0};
						colorText[] = {0,0,1,1};
						text = "$$$$";
					};
			};
	};
	class LevelTitle
	{
		idd = 2;
		duration = 999999;
		class controls
		{
				class LevelControl
				{
						idc = 102;
						type = 0;
						style = 2;
						x =  safeZoneX + safeZoneW - 0.4 * 3 / 4;
						y = safeZoneY + safeZoneH - 0.1;
						w = 0.2;
						h = 0.2 * 3 / 4;
						font = "EtelkaNarrowMediumPro";
						sizeEX = 0.03;
						colorBackground[] = {0,0,0,0};
						colorText[] = {0,0,1,1};
						text = "LVL";
					};
			};
	};
};

in the init.sqf

cutRsc ["DollarTitle","PLAIN"];
cutRsc ["LevelTitle","PLAIN"];

Share this post


Link to post
Share on other sites

To elaborate on KK's response:

("DollarTitle_layer" call BIS_fnc_rscLayer) cutRsc ["DollarTitle","PLAIN"];
("LevelTitle_layer" call BIS_fnc_rscLayer) cutRsc ["LevelTitle","PLAIN"];

If you don't put them on different layers explicitly, they'll end up in the same. And whenever you run a new cutRSC on the same layer, the existing display gets overwritten/replaced. Which is actually great, if you want to remove specific UI elements via script (just cutRsc /cutText a "null" display).

To be able to change the text dynamically, you need to assign them to variables onLoad. Which is described in KK's awesome tutorials as well, but maybe you missed that. This approach has the added benefit that you can access UI elements without having to use disableSerialization. It's practically the "cleanest" way to handle dynamic UI, in my opinion.

class RscTitles 
{ 
       class DollarTitle 
       { 
           idd = 1; 
           duration = 999999; 
           onLoad = "uiNameSpace setVariable ['myUI_DollarTitle', (_this select 0) displayCtrl 101];";
           class controls 
           { 
                   class DollarControl 
                   { 
                           idc = 101; 
                           type = 0; 
                           style = 2; 
                           x =  safeZoneX + safeZoneW - 0.2 * 3 / 4; 
                           y = safeZoneY + safeZoneH - 0.1; 
                           w = 0.2; 
                           h = 0.2 * 3 / 4; 
                           font = "EtelkaNarrowMediumPro"; 
                           sizeEX = 0.03; 
                           colorBackground[] = {0,0,0,0}; 
                           colorText[] = {0,0,1,1}; 
                           text = "$$$$"; 
                       }; 
               }; 
       }; 
       class LevelTitle 
       { 
           idd = 2; 
           duration = 999999;
           onLoad = "uiNameSpace setVariable ['myUI_LevelTitle', (_this select 0) displayCtrl 102];";
           class controls 
           { 
                   class LevelControl 
                   { 
                           idc = 102; 
                           type = 0; 
                           style = 2; 
                           x =  safeZoneX + safeZoneW - 0.4 * 3 / 4; 
                           y = safeZoneY + safeZoneH - 0.1; 
                           w = 0.2; 
                           h = 0.2 * 3 / 4; 
                           font = "EtelkaNarrowMediumPro"; 
                           sizeEX = 0.03; 
                           colorBackground[] = {0,0,0,0}; 
                           colorText[] = {0,0,1,1}; 
                           text = "LVL"; 
                       }; 
               }; 
       }; 
};  

You might ask: Why not use missionnamespace, considering that UInamespace persists between missions? Simple: You'll get an error/warning popup if you store UI controls in missionnamespace :) . Just make sure to use unique names and to only store true UI elements in uinamespace.

Also: There's no need for custom IDDs or IDCs. As you will access them using getVariable and not the finddisplay /displayctrl combo, you can give both of them an IDD of -1. IDC has to be unique per display, so in your case both can have an IDC of "1". This way you also don't have to worry to accidentally interfere with vanilla-defined IDDs.

If you want to change the content text dynamically, you now can simply access the controls using this in your sqf:

uiNameSpace getVariable "myUI_DollarTitle" ctrlSetText("Lorem ipsum");
uiNameSpace getVariable "myUI_LevelTitle" ctrlSetText("Lorem ipsum");

Which also makes for some easy-to-read code as an added benefit.

Share this post


Link to post
Share on other sites

(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText "Lorem ipsum";
(uiNameSpace getVariable "myUI_LevelTitle") ctrlSetText "Lorem ipsum";

Fixed that for ya

Share this post


Link to post
Share on other sites

While that might be logically cleaner and even easier-to-read, it actually works just fine without any parenthesis, both the part before ctrlsetText and the one after. So if you REALLY want to save some bits of mission file size:

uiNameSpace getVariable "myUI_DollarTitle" ctrlSetText "Lorem ipsum";
uiNameSpace getVariable "myUI_LevelTitle" ctrlSetText "Lorem ipsum";

But that's being fairly nitpicky, I guess ;) .

Share this post


Link to post
Share on other sites
While that might be logically cleaner and even easier-to-read, it actually works just fine without any parenthesis, both the part before ctrlsetText and the one after. So if you REALLY want to save some bits of mission file size:

uiNameSpace getVariable "myUI_DollarTitle" ctrlSetText "Lorem ipsum";
uiNameSpace getVariable "myUI_LevelTitle" ctrlSetText "Lorem ipsum";

But that's being fairly nitpicky, I guess ;) .

Indeed, this would work without parenthesis around getvariable, but there are plenty of cases when it wouldn't, so I guess it is just safer to use them.

Share this post


Link to post
Share on other sites

Wow, thanks for the great responses from both of you, that definitely fixed the problem of the lvl UI replacing the the money UI and that explains a lot with the onLoad line. So it works if i leave the "Lorem ipsum" in there or any other text but whenever i try to make it a variable the same way you would a hint, i get nothing back. I have tried these to no avail. Cash is my money variable and level is my level variable.

uiNameSpace getVariable "myUI_DollarTitle" ctrlSetText("Money: %1.",cash);
uiNameSpace getVariable "myUI_LevelTitle" ctrlSetText("Level: %1",level);

uiNameSpace getVariable "myUI_DollarTitle" ctrlSetText["Money: %1.",cash];
uiNameSpace getVariable "myUI_LevelTitle" ctrlSetText["Level: %1",level];

uiNameSpace getVariable "myUI_DollarTitle" ctrlSetText "Money: %1.",cash;
uiNameSpace getVariable "myUI_LevelTitle" ctrlSetText "Level: %1",level;

The last is the closest to working i suppose. It does return Level: %1 and Money: %1 at the bottom right of my screen, but it does not display the variable. the other 2 throw back nothing at all. I have tried some others too but these are the ones i figured should work since they look like they make sense.

Screenshot of it kind of working

http://steamcommunity.com/sharedfiles/filedetails/?id=426817356

Edited by Nebulazer
added link to image

Share this post


Link to post
Share on other sites

uiNameSpace getVariable "myUI_DollarTitle" ctrlSetText format ["Money: %1.",cash];

Share this post


Link to post
Share on other sites

thank you, that worked for displaying it correctly at the bottom right, but now i have a new problem with that. I cant seem to get my money system to work the way it was working before for some reason. I had it working where you could kill an enemy and it would tell you in the hint "+$100" but now it wont even give me the hint for some reason. I moved the global variable for cash to another script but that should not matter, right? I tried putting back in that script and it will work but it will not tick the numbers on the bottom right as they seem to be stuck at '1'. http://cloud-4.steamusercontent.com/ugc/45376357718345624/812530357E3E6A417C89CFE6E28E9751C135C960/

Here are my scripts currently.

moneyLevels.sqf

cash=0;
level=0;
("DollarTitle_layer" call BIS_fnc_rscLayer) cutRsc ["DollarTitle","PLAIN"];
("LevelTitle_layer" call BIS_fnc_rscLayer) cutRsc ["LevelTitle","PLAIN"];
(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: 1%",cash];
(uiNameSpace getVariable "myUI_LevelTitle") ctrlSetText format ["Level: 1%",level];

cashOnKills.sqf

if (isServer)then{
_unit=(_this select 0);

_unit addEventHandler ["killed", {
_unit=		(_this select 0); 
_killer=	(_this select 1); 


if (isPlayer _killer)then{ 

cash=cash+100;
hint "+$100";
_unit removeAllEventHandlers "killed"; 
		};
	}];
};

navidHex.sqf

//Navid Hex
//Remove weapons
_cost=100;

if (cash >= _cost) 
then {
 cash=cash-_cost;
 hint "$100 Taken";
player removeWeapon (primaryWeapon player);
{player removeMagazine _x} forEach magazines player;
//Add new weapons
player addMagazine '150Rnd_93x64_Mag';
player addWeapon 'MMG_01_hex_F';
player addMagazines ['150Rnd_93x64_Mag', 3];

	}else{

	hint "Not enough money";

	};

The description.ext is the one that you provided me with above.

EDIT: I have the UI working with the money script now but the UI for the money in the bottom right still does not follow the variable for some reason, it just stays at 1.

Fixed cashOnKill.sqf

//cash=0;
if (isServer)then{
_unit=(_this select 0);

_unit addEventHandler ["killed", {
_unit=		(_this select 0); 
_killer=	(_this select 1); 


if (isPlayer _killer)then{ 

	cash=cash+100;
	hint "$+100";

_unit removeAllEventHandlers "killed"; 
		};
	}];
};

Edited by Nebulazer
Sort of fixed

Share this post


Link to post
Share on other sites

If you are playing on a dedicated server, only the server will have the "killed" eventhandler registered, due to the "if isserver then". Read KK's note here about isServer.

This means only the server's "cash" variable will be increased by 100. If you are playing this mission on a local LAN MP server, it "works" because your client is the server at the same time, but in MP this will not work.

You probably could keep all this entirely client-side for your use-case, and let each client handle its money on its own. Instead of checking "isplayer _killer" you would then change it to "player == _killer" to make sure the client only gets cash if he is the killer.

The UI money value is not updated because your script never updates it. Whenever you want the value to be updated, you will have to do so manually by executing

(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: 1%",cash];

again. ctrlsetText is a one-time action, it doesn't auto-refresh just because you are using a variable in the format command. ArmA never auto-updates anything "just like that", you always have to do every step yourself. That's the whole reason why eventhandlers exist.

EDIT: Regarding the cash variable: As it's a global variable, you only have to make sure that it is initialized ( cash = 0;) before you use something like "cash = cash +100" for the first time. Usually you initialize such global variables at the very start of your init.sqf to make sure they will exist before any other script might need them.

Share this post


Link to post
Share on other sites

Thanks, so this should work for all players and headless client then right? It still works for me except it still does not show the correct amount of money in the GUI, i have not tested it with another player joining my game, all my clanmates have been playing GTA.

if (!isDedicated)then{
_unit=(_this select 0);

_unit addEventHandler ["killed", {
_unit=        (_this select 0); 
_killer=    (_this select 1); 


if (isPlayer _killer)then{ 

       cash=cash+100;
       hint "$+100";

(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: 1%",cash];

_unit removeAllEventHandlers "killed"; 
           };
       }];
   };  

I am going to be putting this on a dedicated server very soon (maybe today or tomorrow) that i will have access to through a remote desktop program, so I want to make sure this is all set up to be able to work with that as well.

still, no matter where or when i run

(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: 1%",cash];

it always returns a value of 1, but the cash=0 so why does it show 1?

Also, is there a way to execute the cashOnKill.sqf on the ai without having to put

null =[this]execVM "cashOnKill.sqf";

on all of them?

EDIT: I have been trying a bunch of things but i still cant get it to change from a 1 all though the money script itself is still working and i can use the shop just not show the display on the UI correctly. Do i need to use onRscLoad? I am not sure if i need to use an eventhandler in the script or not and how it should exactly be formatted. I have been reading a ton of stuff and trying it with a ton of stuff from tutorials but nothing seems to work. i am testing it buy running it from the debug with execVM then using

		cash=cash+10000000;
	hint "$+1000000";
onRscLoad = {
(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: 1%",cash];
};
("DollarTitle_layer" call BIS_fnc_rscLayer) cutRsc ["DollarTitle","PLAIN"];

I dont know much about how exactly everything should be formatted though.

Edited by Nebulazer

Share this post


Link to post
Share on other sites

Your string format is wrong.

(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: %1",cash];

Sometimes it's the little things.:)

Share this post


Link to post
Share on other sites

WOW! I can't believe that was it the whole time, i was having dreams about how to fix this, haha. Thank you so much to both of you for your help on this, and KK thank you for the awesome tutorials that you put out there so everyone can learn about how to do these things. Heres some screenshots of it working http://cloud-4.steamusercontent.com/ugc/45376357725037082/6B0D6EACAD1D592B17F998C112CBCFC92231A5E7/ and buying a gun http://cloud-4.steamusercontent.com/ugc/45376357725037576/5FAEC02DC9F0E7BA8C76F83D6D36C7F802F042F2/

Also I want to share what my shop and cashOnKill scripts looks like now that it works

This is run through submenus in the actionmenu from a box currently, might try to find a different object to put it on, maybe an AI.

//SPMG sand
_cost=4500;

if (cash >= _cost) 
then {
 cash=cash-_cost;
 hint "$4,500 Taken for SPMG Sand";
 (uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: %1",cash];
//Remove weapons
player removeWeapon (primaryWeapon player);
{player removeMagazine _x} forEach magazines player;
//Add new weapons
player addMagazine '130Rnd_338_Mag';
player addWeapon 'MMG_02_sand_F';
player addMagazines ['130Rnd_338_Mag', 3];

	}else{

	hint "Not enough money";

	};

this is run from execVM in the init

//Get Cash when you kill
if (!isDedicated)then{
_unit=(_this select 0);

_unit addEventHandler ["killed", {
_unit=        (_this select 0); 
_killer=    (_this select 1); 


if (player == _killer)then{ 

       cash=cash+100;
       hint "$+100";

(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: %1",cash];

_unit removeAllEventHandlers "killed"; 
           };
       }];
   };  

Use this in debug for testing the shop if you dont have AI or players to kill


	cash=cash+9000;
	hint "$+9,000";

(uiNameSpace getVariable "myUI_DollarTitle") ctrlSetText format ["Money: %1",cash];

Edited by Nebulazer

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
Sign in to follow this  

×