Jump to content
Sign in to follow this  
KC Grimes

Trouble intertwining string/format/objects

Recommended Posts

Howdy! So, I'll put the basics out there of what I'm trying to accomplish. I want to successfully call upon a unit, without having named it in the editor (in order to reduce turnaround time for mission makers). I'm going to ask this as a series of questions as I get replies, as it kind of builds on itself, especially as I get help figuring out what is wrong.

First off, given the following: (ignore the commented out line for now)

{
call compile format["_dist = %1 distance player",_x];
//_dist = _x distance player;
player sideChat _dist;
} forEach allUnits;

In this case, allUnits only includes the player, whose unit is named in the editor as tester, so we are checking the distance between player and player, which is supposed to be 0. However, I get the error that _dist is undefined. If I use the line that is commented out, it works as expected. However, with my application, I need to use format. But here is the twist. When I remove the underscore to make _dist to dist, a global variable, it works as intended. How can I accomplish this with a local variable?

Next question, as it uses the same bit of code. How do I make this work, with local or global variables, without naming the unit in the editor? The reason this is an issue is being non-named units are automatically named "B 1-1-4 Alpha" and the like, which includes spaces, and thus throws off any application of it in script. How can I get around this, specifically when I want to be able to handle all MP clients from an MP client?

Basically I am asking what conversion can I do or how can I control B 1-1-4 Alpha as an object, instead of a bunch of characters that break a script?

Thanks for the help, as always!

Edit: After playing with it more, I believe I've found that _x is originally an object, but becomes a string when used in format, thus causing the issues with spaces and such. Any ideas on how to prevent this, without defining allUnits as a variable at init? :P

Edited by Grimes [3rd ID]

Share this post


Link to post
Share on other sites

Why not put the sidechat part into the format?

{
call compile format["_dist = %1 distance player; 
				player sideChat _dist",_x];
} forEach allUnits;

The original version of my ied script did that with several commands chained in a format from time to time, since each ied object was named ied_%1. However, I was able to reference each of those variables again later, so I am not sure why it isn't working for you. When I referenced them again, they were inside of another format, so that might be something to look into.

For example

call compile format ['ied_%1 = _iedType createVehicle _iedPos;
	ied_%1 setDir (random 360);
	ied_%1 enableSimulation false;', iedcounter];

/// Then I used it later on
call compile format ['[[ied_%1, t_%1],"Disarm", true, true] spawn BIS_fnc_MP;', iedcounter];

I did end up moving away from this type of programming though. If you have errors in your statement, they won't get reported in the .rpt file and that can be frustrating to debug. However, for some stuff, it is absolutely necessary.

Share this post


Link to post
Share on other sites

Thanks for the idea, hadn't thought of it.

{
call compile format["_dist = %1 distance player; 
player sideChat str _dist",_x];
} forEach allUnits;

Interestingly, however, when running the script with me and 3 AI in the map, I only received a single message, 0, instead of 4 messages (from the other units).

Share this post


Link to post
Share on other sites

How soon after mission load are you running the loop? I have had trouble with sidechat showing up on my ied script if I use it early in the mission... Try using a hint and seeing if you hear the 4 beeps, or store the values in an array and check it with the debug console.

Share this post


Link to post
Share on other sites

In my script I'm running it a few execs after a waituntil player == player, so that shouldn't be trouble. For the snippet of code, I ran it from the debug console, so all is loaded well in advance. It is erroring out like I explained in my OP, because it is getting confused by the spaces in the not-so-much-a-variable variable name (B 1-2:3 Alpha). I'm going to send you a PM.

Edit: Scratch that, I'll just put it here. Hoping to release soon anyway. This is from a portion of my revive script. I have debugged it to hell and back, and just can't figure out what to do. I've reverted it to a clean look, so you can see what I am trying to do. I'm not one to ask for people to do stuff for me, but I would really appreciate some help here, as I am just completely and utterly beat by this one.

//Controls 3D unit markers

private ["_unit"];

switch (G_Unit_Marker_Display) do {
case 0: {
	//Body
};

case 1: {
	//Body
};

case 2: {
	{
		if (G_Unit_Marker_ShowDistance) then {
			addMissionEventHandler ["Draw3D", {
				private ["_color","_height","_alpha","_distp"];
				_distp = _x distance player;
				if ((_distp <= G_Unit_Marker_Distance) and ((player getVariable "G_Side") == (_x getVariable "G_Side")) and (_x isKindOf "CAManBase")) then {
					_alpha = (-0.02*(_distp))+(0.025*(G_Unit_Marker_Distance));
					if (_x getVariable "G_Unconscious") then {
						_color = call compile format["[1,0,0,%1]",_alpha];
					}
					else
					{
						_color = call compile format["[0,0.85,0,%1]",_alpha];
					};
					_height = 0.0053*(_distp)+2;
					drawIcon3D ["", _color,[(visiblePosition _x) select 0, (visiblePosition _x) select 1, _height],0, 0, 0, "format['%1 (%2m)',name _x,ceil(_distp)]", 0, 0.035];
				};
			}];
		}
		else
		{
			addMissionEventHandler ["Draw3D", {
				private ["_color","_height","_alpha","_distp"];
				_distp = _x distance player;
				if ((_distp <= G_Unit_Marker_Distance) and ((player getVariable "G_Side") == (_x getVariable "G_Side")) and (_x isKindOf "CAManBase")) then {
					_alpha = (-0.02*(_distp))+(0.025*(G_Unit_Marker_Distance));
					if (_x getVariable "G_Unconscious") then {
						_color = call compile format["[1,0,0,%1]",_alpha];
					}
					else
					{
						_color = call compile format["[0,0.85,0,%1]",_alpha];
					};
					_height = 0.0053*(_distp)+2;
					drawIcon3D ["", _color,[(visiblePosition _x) select 0, (visiblePosition _x) select 1, _height],0, 0, 0, "name _x", 0, 0.035];
				};
			}];
		};
	} forEach allUnits;
};
};

Variable info:

G_Side will return unit's side

G_Unconscious will return true or false

G_Under_Marker_Distance is a positive number, lets say 75

What happens when this is executed is, simply, nothing. Nothing happens, nothing is reported. As I've said, I've debugged through it completely and just can't figure out a way to fix it, and its completely due to the B 1-1:3 Alpha variables and their spaces.

If anyone needs further explanation of what I am trying to accomplish, feel free to ask, I'm happy to elaborate. I just can't do this one on my own apparently.

Thanks again!

Edit 2: Not to confuse anyone, but here was another attempt I had made, and saved before trying another method. Perhaps it is easier to read as well. This is the ideal structure I want to get working, as it has a cleaner look and is technically "smaller". Same problem, however.

private ["_text"];

G_Unit_Marker_Exec = {
_unit = _this select 0;
if (G_Unit_Marker_ShowDistance) then {
	_text = "format['%1 (%2m)',name _unit,ceil(_unit distance player)]";
}
else
{
	_text = "name _unit";
};
call compile format["
	addMissionEventHandler ['Draw3D', {
		private ['_color','_height','_alpha','_distp'];
		_distp = %3 distance player;
		if ((_distp <= G_Unit_Marker_Distance) and ((player getVariable 'G_Side') == (%3 getVariable 'G_Side')) and (%3 isKindOf 'CAManBase')) then {
			_alpha = (-0.02*(_distp))+(0.025*(G_Unit_Marker_Distance));
			if (%3 getVariable 'G_Unconscious') then {
				_color = call compile format['[1,0,0,%2]',_alpha];
			}
			else
			{
				_color = call compile format['[0,0.85,0,%2]',_alpha];
			};
			_height = 0.0053*(_distp)+2;
			drawIcon3D ['', _color,[(visiblePosition %3) select 0, (visiblePosition %3) select 1, _height],0, 0, 0, %1, 0, 0.035];
		};
	}];
", _text, "%1", _unit];
};

switch (G_Unit_Marker_Display) do {
case 0: {
	{
		[_x] call G_Unit_Marker_Exec;
	} forEach allUnits;
};

case 1: {
	[cursorTarget] call G_Unit_Marker_Exec;
};

case 2: {
	{
		[_x] call G_Unit_Marker_Exec;
	} forEach allUnits;
};
};

If anyone is interested, I am willing to send the mission file for use, to avoid having to "setup the test chamber".

Edited by Grimes [3rd ID]

Share this post


Link to post
Share on other sites

Without going into the new code, is there any reason you can't pass the distance into format?

 
{
_dist = "";  //variable needs to be created before the next line so it exists afterwards
call compile format["_dist = %1",_x distance player];  //you really don't even need call compile format anymore...
player sidechat str _dist;
} forEach allUnits;

I will look into trying to actually use a player object now.

******************************************

First error I see is this

_color = call compile format['[1,0,0,%2]',_alpha]; //%2 refers to the second input, which you don't have

Edited by brians200

Share this post


Link to post
Share on other sites

Haven't tried formatting distance, only because it isn't returned in the first place with the issue I'm having.

About the error with _color, it's a little bit of a tricky move. The %2 there refers to the #2 spot in the larger format, which says "1%", referring to _alpha back at the _color line. Its because there is a format inside a format. Not sure why that error is popping, haven't had that issue before. Be sure that you have copy/pasted all of the format lines as well :P Thanks for looking into it, I really appreciate the help.

Share this post


Link to post
Share on other sites

I have gotten the text to show up for a split second, before receiving an error. So making some progress. Will let you know what I figure out.

EDIT: The way I am doing it isn't going to work either, at least not more than 1 frame.

The fun part about this issue is that you can't use objects passed in to call compile format. So that approach isn't going to work in the second bit of code you have. Looking at the first one now.

The other fun part is that you can't directly pass inputs into the "command" of addMissionEventHandler without call compile format. However, you can't pass objects in that way.

The final fun part is that local variables declared before the addMissionEventHandler call don't exist inside the "command" part.

Edited by brians200

Share this post


Link to post
Share on other sites

I appreciate the effort. Yeah, it treats it a bit differently than other EHs, unfortunately. Especially when considering local variables. My alternative is the use of either netIDs (haven't tested this fully, so not 100% yet...) or just defining all players with a custom global variable (easy to setup, just dirty dirty dirty, and will be fun to get working with JIP).

I've got finals this week, but once my head is cleared I'll take another stab at these ideas.

Share this post


Link to post
Share on other sites

Does this look about right?

http://i.imgur.com/AMSI8uv.jpg

http://i.imgur.com/akXqFd0.jpg

You can clean it up and check for edge cases, but it seems to be working. I obviously don't have the wounding part and what not, so I can't test that.

You are going to want to move the _text = ... code inside of the addMissionEventHandler (so the distance value gets updated), but you don't need to make it as complex as you were trying to do earlier.

private ["_text"];

G_Unit_Marker_Exec = {
   _unit = _this select 0;
_i = _this select 1;

(player getVariable 'otherUnits') set [_i, _unit];


/****ADDED TO TEST ****/
player setVariable ["G_Side", side player];
_unit setVariable ['G_Unconscious', false];
_unit setVariable ["G_Side", side _unit];
/****END ADDED TO TEST****/


   if (G_Unit_Marker_ShowDistance) then {
       _text = format['%1 (%2m)',name _unit,ceil(_unit distance player)];
   }
   else
   {
       _text = name _unit;
   };

addMissionEventHandler['Draw3D', format['
				private ["_color", "_height", "_alpha","_distp"];
				_unit = (player getVariable "otherUnits") select %1;
				_distp = _unit distance player;
				if ((_distp <= G_Unit_Marker_Distance) and ((player getVariable "G_Side") == (_unit getVariable "G_Side")) and (_unit isKindOf "CAManBase")) then {
					_alpha = (-0.02*(_distp))+(0.025*(G_Unit_Marker_Distance));
					if(_unit getVariable "G_Unconscious") then {
						_color = [1,0,0,_alpha];
					} else {
						_color = [0,0.85,0,_alpha];
					};
					_height = 0.0053*(_distp)+2;
					drawIcon3D ["", _color, [(visiblePosition _unit) select 0, (visiblePosition _unit) select 1, _height], 0, 0, 0, "%2", 0, 0.035];
				};
			',_i, _text]];
};

/****ADDED TO TEST ****/
G_Unit_Marker_Display = 2;
G_Unit_Marker_ShowDistance = true;
G_Unit_Marker_Distance = 75;
/****END ADDED TO TEST****/

player setVariable ['otherUnits', []];

switch (G_Unit_Marker_Display) do {
   case 0: {
      /************HANDLE THIS CASE**************/
   };

   case 1: {
       /************HANDLE THIS CASE**************/
   };

   case 2: {
	_i = 0;
       {
           [_x,_i] call G_Unit_Marker_Exec;
		_i = _i + 1;
       } forEach allUnits;
   };
};  

Good luck on your finals!

Edited by brians200

Share this post


Link to post
Share on other sites
Does this look about right?

http://i.imgur.com/AMSI8uv.jpg

http://i.imgur.com/akXqFd0.jpg

You can clean it up and check for edge cases, but it seems to be working. I obviously don't have the wounding part and what not, so I can't test that.

You are going to want to move the _text = ... code inside of the addMissionEventHandler (so the distance value gets updated), but you don't need to make it as complex as you were trying to do earlier.

Good luck on your finals!

I've promised myself I won't touch this until I get a few things done, but it looks good, and your pictures are in the ballpark (I just need to mess with the values, it was the format that was the real brain masher). I'll update this thread either way in a few days with my results, or any changes. Thank you, thank you, thank you for taking the time to go through this. I'll be sure to WinMerge it and take a look at what you did so I can learn from this. Unfortunately right now I just have "life" to take care of before this hobby. But again, thank you so much!

Share this post


Link to post
Share on other sites

Taking a brain break from studying and am implementing the fixed bit you gave me. I see that you did what I had said my alternative was, by involving global variables, but in a different way by using set variable. I'll play with this a bit and see how it goes, and work JIP into it. Thank you again for doing this!

Now, my biggest question, and my honest WTF to what you gave me is, why is all of this working with how you handled quotations and apostrophes? Basically all you did to get this working was trade all of my "" with '', and vice versa. Why did that work? I thought apostrophes were strictly to be used within quotes, instead of having to use double and triple quotations at variables/strings? I'm glad you did it, don't get me wrong, it works, but I do not understand why.

Edit: Now that I played with it a bit more, I see that the positioning of apostrophes and quotes can be swapped, as long as you are consistent about it. However, I see the advantage of having the apostrophes on the outer most scope is that the syntax highlighter doesn't consider it all a string and maintains the proper highlighting. Very interesting. Thank you for showing me this, without intending to! :P As well, thank you again for getting this going. I'll do the minor tweaking, no worries, but you got it up and running. I appreciate the help.

Edited by Grimes [3rd ID]

Share this post


Link to post
Share on other sites

Yes, the order of the apostrophe and quotation marks can be mixed. I have always done it the way I wrote it, so it was easier for me to comprehend the overall code that way. If you want to get it to be more confusing, you can even use """words""" inside of a " block. :D

Ultimately, I was trying to reduce the complexity of your original code so we could break it down into what isn't working. So you will see I ended up formatting a bit less than you did, which ultimately helped.

One thing you might check is how setVariable works after death. I haven't used it enough to know fully.

Share this post


Link to post
Share on other sites

Right now the issue is that upon death, the tags stay on the body and don't follow the "player". But I've already thought of a fix for that. But we'll see how it goes. Back to studying :P

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  

×