Jump to content

Recommended Posts

Hey there,

 

I'm trying to get an object to provide a whitelisted player with the option to purchase ammunition once in close proximity. So far, I've written the following into the object's init:

 

if (getPlayerUID player in _UIDList) then { this addAction ["Buy STANAG mag $100","purchasestanag.sqf"]};

 

The mentioned _UIDList simply reads as follows under init.sqf:

 

_UIDList=["76561198090900291"];

 

Is there something crucial I'm forgetting to include? I'm very fresh to coding, so do excuse my ignorance.

 

Any pointers are much appreciated.

 

Share this post


Link to post
Share on other sites

Your variable "_UIDList" is local, so it won't work. Your addAction will see it as undefined. Fortunately, making it global is easy - just remove the leading underscore. 

Tangentially, it's good practice to get specific with your variables, particularly globals. You might want to get into the habit of prepending yours with your tag. You'll often see example code using this concept, for example: TAG_UIDList. The idea is to replace "TAG" with your modder tag. You might choose SNK or similar, which gives you SNK_UIDList.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Hhhmmm, not sure what you have so far works in the way you describe you want it to work... I believe you should use the condition of the addAction command. Additionally, what Harzach says is correct, your addAction code does not have access to your local variable. Here's an example of what I would do.

// Since you already have th UID you could hardcode it in the init field like you already do
missionNamespace setVariable["whitePlayer", "76561198090900291"]; // Set the value in a variable in the namespace to have access to it

// Create and attach the addAction to the object
this addAction["Buy STANAG mag $100", // Title of the action
			   "purchasestanag.sqf", // Script to be executed when the action is performed
               [], // Arguments passed to the script
               2, // Priority (how high up in the list will show)
               true, // Show window (text in the middle of the scree)
               true, // Hide on use (hide but NOT detach the action after use)
               "", // Shortcut (not sure how it works, have never used it :P)
               { // Condition to show (HERE WE ARE...!!!) If the code returns true the action will show, otherwise it will not
				private _uID = getPlayerUID player; // Get the player's UID
				private _whiteID = missionNamespace getVariable["whitePlayer", false]; // Get the whitelisted UID
				
				// Check if the IDs match
				_uID isEqualTo _whiteID; // This result will return. If they match true will be returned and action will show
               }, // End of condition code
               5, // Radius (how close you have to go for the action to show up
               false]; // Show if incapacitated

This way, you attach the action to the object and forget about it. The condition will handle the rest. The condition check compares each player's UID that goes close to the object and if this matched the one you set as the whitelisted it will show to that player, otherwise it will not.

 

I believe it is a quite "elegant" way to achieve what you want. Not sure this is very efficient though because the condition is evaluated in each frame in an unscheduled environment. I guess that its CPU load depends on how expensive are the getPlayerUID and getVariable commands. Another way would be to do what Harzach proposes, making the whitelisted ID a global variable (not sure how much this would speed things up though).

 

Please feel free to comment or ask for more clarifications or help if you need it.

  • Like 2

Share this post


Link to post
Share on other sites

^^^

Definitely familiarize yourself with addAction's extended syntax.

 

You might move the condition check to the executed code instead, if cpu overhead is at a premium. A failed check could result in a hint ("You do not have the required permit", etc).

  • Like 1
  • Thanks 1

Share this post


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

// Condition to show (HERE WE ARE...!!!) If the code returns true the action will show, otherwise it will not

VERY bad idea. That condition will run every single frame, and its result will never change as the whitelist is hardcoded and the players UID will never change.

Just doesn't make any sense to do such a thing.

 

13 hours ago, BigSnek said:

if (getPlayerUID player in _UIDList) then { this addAction ["Buy STANAG mag $100","purchasestanag.sqf"]};

 

Why "this" ? is "this" defined? Where did you put this code? Did you define _UIDList before it? where do you define _UIDList, what else is in that code snippet that you've omitted here?

More details please.

  • Like 1
  • Thanks 1

Share this post


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

VERY bad idea. That condition will run every single frame, and its result will never change as the whitelist is hardcoded and the players UID will never change.

Just doesn't make any sense to do such a thing.

Aaaahhh, you are right, this will only get the player where the object is local. My bad, I am really sorry! A corrected version of that would be

/*
 * This whole script goes into the object's init field
 */

// Since you already have the UID you could hardcode it in the init field like you already do
missionNamespace setVariable["whitePlayer", "76561198090900291"]; // Set the value in a variable in the namespace to have access to it

// Create and attach the addAction to the object
this addAction["Buy STANAG mag $100", // Title of the action
               "purchasestanag.sqf", // Script to be executed when the action is performed
               [], // Arguments passed to the script
               2, // Priority (how high up in the list will show)
               true, // Show window (text in the middle of the scree)
               true, // Hide on use (hide but NOT detach the action after use)
               "", // Shortcut (not sure how it works, have never used it :P)
               { // Condition to show (HERE WE ARE...!!!) If the code returns true the action will show, otherwise it will not
				private _uID = getPlayerUID _this; // Get the player's UID
				private _whiteID = missionNamespace getVariable["whitePlayer", false]; // Get the whitelisted UID
				
				// Check if the IDs match
				_uID isEqualTo _whiteID; // This result will return. If they match true will be returned and action will show
               }, // End of condition code
               5, // Radius (how close you have to go for the action to show up
               false]; // Show if incapacitated

The only change here is that instead of player you have to use _this inside the condition script. According to the docs this holds the "caller" (or the person who is to see or not the action). Thus, you can check this player's UID against the whitelisted ID.

 

Thank you Dedmen for the correction!

 

Once more..., this will most probably result in suboptimal efficiency, due to the "onEachFrame" execution (like very well Dedmen also stated). As Harzach states, this check could go into the executed code to save (most probably a lot of) CPU usage.

 

2 hours ago, Dedmen said:

Why "this" ? is "this" defined? Where did you put this code? Did you define _UIDList before it? where do you define _UIDList, what else is in that code snippet that you've omitted here?

BigSnek states that they use this snippet in the object's init field, which means that this should refer to the object that needs to have the action attached.

  • Like 1

Share this post


Link to post
Share on other sites
On 4/28/2020 at 12:14 PM, ZaellixA said:

Aaaahhh, you are right, this will only get the player where the object is local. My bad, I am really sorry! A corrected version of that would be


/*
 * This whole script goes into the object's init field
 */

// Since you already have the UID you could hardcode it in the init field like you already do
missionNamespace setVariable["whitePlayer", "76561198090900291"]; // Set the value in a variable in the namespace to have access to it

// Create and attach the addAction to the object
this addAction["Buy STANAG mag $100", // Title of the action
               "purchasestanag.sqf", // Script to be executed when the action is performed
               [], // Arguments passed to the script
               2, // Priority (how high up in the list will show)
               true, // Show window (text in the middle of the scree)
               true, // Hide on use (hide but NOT detach the action after use)
               "", // Shortcut (not sure how it works, have never used it :P)
               { // Condition to show (HERE WE ARE...!!!) If the code returns true the action will show, otherwise it will not
				private _uID = getPlayerUID _this; // Get the player's UID
				private _whiteID = missionNamespace getVariable["whitePlayer", false]; // Get the whitelisted UID
				
				// Check if the IDs match
				_uID isEqualTo _whiteID; // This result will return. If they match true will be returned and action will show
               }, // End of condition code
               5, // Radius (how close you have to go for the action to show up
               false]; // Show if incapacitated

The only change here is that instead of player you have to use _this inside the condition script. According to the docs this holds the "caller" (or the person who is to see or not the action). Thus, you can check this player's UID against the whitelisted ID.

 

Thank you Dedmen for the correction!

 

Once more..., this will most probably result in suboptimal efficiency, due to the "onEachFrame" execution (like very well Dedmen also stated). As Harzach states, this check could go into the executed code to save (most probably a lot of) CPU usage.

 

BigSnek states that they use this snippet in the object's init field, which means that this should refer to the object that needs to have the action attached.

 

Thank you all for the feedback! Certainly learned an important lesson about local and global variables today.

 

I finally found time to test out your script ZaellixA, which looks like exactly what I need, however I keep getting hit with the following error message despite my debugging attempts:

 

'...ePlayer", "76561198090900291"];

this |#|addAction["Buy STANAG mag $100","purchas...'
Error Type code, expected String

Any thoughts?

  • Like 1

Share this post


Link to post
Share on other sites

Condition for addAction is a "string", not {code}.

And for a string inside the string (i.e., "whitePlayer"), you would use 'semiquotes' (i.e., 'whitePlayer').

  • Like 1

Share this post


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

Condition for addAction is a "string", not {code}.

And for a string inside the string (i.e., "whitePlayer"), you would use 'semiquotes' (i.e., 'whitePlayer').

Ppppfffff..., I am really sorry about that... I always forget that and it's one of the most common errors I get when I code in ArmA (it's easy to realise what your error is though after the 50th time :D).

 

Thanks opusfmspol for the correction!

 

Please let us know if it is indeed what you are looking for... when you make it work that is :D.

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

×