View unanswered posts | View active topics It is currently 24 Apr 2018 14:44

Forum rules


- Use common sense and be respectful towards each other at all times, even when disagreeing.
- Do not reveal sensitive game information. Guild secrets, player seconds are examples of things not allowed.



Reply to topic  [ 11 posts ]  Go to page 1, 2  Next
Args Explained 
Author Message
Wanderer
User avatar

Joined: 06 Apr 2014 07:40
Posts: 71
You might have seen several really high functioning javascript code examples using args or an index of args to get extra information that was passed along with an alias. You might not have seen however anywhere that states what exactly it's doing or why they're doing it. In this post, I'll explain what args are, how they are used, and why they're awesome. Lets take a look:

Explanation:
Args are the arguments that are passed when one gives a command (so basically everything you ever enter into the console, that's fair game for args). This is done by taking a command, like 'kill stinky pete', cutting it up into pieces in the background, and having it stored for the user to use in their javascript code in their alias as usable strings.

The important part about args is that you can select all or some of the text that was passed along with the alias depending on the index of args that you are looking it. For our example of 'kill stinky pete', args would have five indexes: 0, 1, 2, $*, and *. If you were to programmatically retrieve them, it would look like this: kill stinky pete, stinky, pete, stinky pete, stinky pete. The ones we care about are going to be the non-zero numbers and *. The non-zero numbers inform us that at least one other word was passed along with our alias. The asterisk will allow us to retrieve all information that was passed other than the alias.

In a nice graph format:
Index | Output
0 | kill stinky pete
1 | stinky
2 | pete
$* | stinky pete
* | stinky pete

In use:
So, lets say that you want to automate killing crap. The command for doing so is "kill <identifier for what to kill>". So it would be a good idea to create an alias "kill", and then use some fancy javascript to remember what you last attacked. That way, when your "You killed" trigger pops, you can have it try to kill the same thing again in the hopes that there's another enemy standing around. To do that, we're going to need to use what was supplied with the "kill" command and store it to a variable. That'd look something like this:

alias: kill
Code:
if (args[1] !== undefined){
  gwc.userdata.last_target = args['*'];
  gwc.connection.send( 'kill ' + args['*'] );
}
else{
  gwc.output.append('Kill what?');
  gwc.output.color('red');
}


The reason that we're using '*' instead of the second index like we checked is because the '*' index is always going to be present. If one was to only type "kill", then the '*' index will be an empty string, or ''. It would always cause our if statement to pop, and that's not what we want. Instead, we are checking whether there was at least one other word after "kill" that was separated by a space. If that's the case, we need to grab ALL of the words that were after the "kill" command. That's why we can't use the second index, or [1], for when we go to use the data. If we did, then when stinky pete is dead and we want to kill his clone that happens to be near by, we would then be trying to only "kill stinky" which would inevitably be met with the most irritating of all console errors of "You find no such living creature". If you have a trigger that responds to that by moving on, then you may completely overlook all the other Pete's on that tile.

Our trigger would then look something like this:
trigger: You killed
Code:
gwc.connection.send( 'kill ' + gwc.userdata.last_target );



Advanced args use: (Using non-capturing groups in regular expressions)
Once you get the hang of taking chunks of text out of a sentence using regular expressions, you may feel like it is time to simplify your trigger list by putting multiple triggers together that all perform the same types of actions. This can be done normally using (?:<statement one>|<statement two>). When one wishes to receive a portion of the statements within the non-capturing group, then the indexing for args becomes different. Instead of having each numerical index in args being a portion of the received text, it instead returns what each portion of the non-capturing group collected when the trigger fired. This means that, if you have four different statements, you will have three that are undefined and a forth one that is defined (and contains the text that you want).

To give an example, if you were trying to put all of your statements together that were for a quest in which there were several statements that all used different language to describe the same thing, you may be tempted to put them together into a non-capturing group that had capturing groups inside of it.

Example of regular expression:
(?:The (.*) throws a rock!|The (.*) bites you|The (.*) goes berserk)
We know that, because there are three different statements within our non-capturing group, there will be three different non-zero integer indexes for args: 1, 2, and 3. Each of these will correlate with the individual statements. So, if you wanted the first statement, you would use args[1] and so forth. What if you wanted to get whichever one is available though?

Then you'd use something like this in order to get the one defined value:
Code:
for (var i = 1; i < 5; i++){
  if ( args[ i ] !== undefined ){
    var value = args[ i ];
    break;
  }
}
//Here is where you'd use the value variable



Why that's awesome:
Aliases are amazing. They have a great amount of power, but aliases that can have extra information passed with them are even more awesome. Don't take my word for it, look at script examples like the one that allows you to save statistical information about forgings and retrieve specific stats by an alias call. Literally, the sky is the limit.

_________________
Args Explained - Adv. Trigger Manip - Adding Audio


03 May 2015 10:53
Profile WWW
Wizard
User avatar

Joined: 17 Apr 2012 12:09
Posts: 753
vlek wrote:
Example of regular expression:
(?:The (.*) throws a rock!|The (.*) bites you|The (.*) goes berserk)
We know that, because there are three different statements within our non-capturing group, there will be three different non-zero integer indexes for args: 1, 2, and 3. Each of these will correlate with the individual statements. So, if you wanted the first statement, you would use args[1] and so forth. What if you wanted to get whichever one is available though?

Then you'd use something like this in order to get the one defined value:
Code:
for (var i = 1; i < 5; i++){
  if ( args[ i ] !== undefined ){
    var value = args[ i ];
    break;
  }
}
//Here is where you'd use the value variable



Sorry to nitpick, but that's very inefficient...

First of all, your regex doesn't conform with DRY (the most important principle). Second of all, you declare your value variable inside a loop and then immediately break out of it and try to do something with the variable outside of the loop (not good since you're trying to access the variable out of scope now).

Code:
^=The (.*) (thorws a rock|bites you|goes berserk)

var value = null;
var i = 1;

while (i < 5) {
    if (args[i]) {
        value = args[i];
        break;
    }

    i += 1;
}

// do stuff with variable 'value'

_________________
Time is precious. Waste it wisely.


10 May 2015 05:25
Profile
Wanderer
User avatar

Joined: 06 Apr 2014 07:40
Posts: 71
Hello Zhar, thanks for the input.

You're right, I didn't give a very good example because it does seem like what I was doing was inefficient, but I'm talking about cases in which the syntax of the line can be vastly different, causing one to use an or case statement like the one that I was using, and how that effects args. If one were to use the regex statement that you provided, they wouldn't get the weird args indexing I wanted to highlight.

Since the trigger would only fire in the case of at least one of those statements being in the output, it is impossible that one would be trying to interact with the value variable and it being out of scope.

Lastly, as far as the choice of loop goes, you're right. I'd change it in the main post if I still could edit it.

_________________
Args Explained - Adv. Trigger Manip - Adding Audio


11 May 2015 00:26
Profile WWW
Wizard
User avatar

Joined: 17 Apr 2012 12:09
Posts: 753
vlek wrote:
Hello Zhar, thanks for the input.

You're right, I didn't give a very good example because it does seem like what I was doing was inefficient, but I'm talking about cases in which the syntax of the line can be vastly different, causing one to use an or case statement like the one that I was using, and how that effects args. If one were to use the regex statement that you provided, they wouldn't get the weird args indexing I wanted to highlight.

Since the trigger would only fire in the case of at least one of those statements being in the output, it is impossible that one would be trying to interact with the value variable and it being out of scope.

Lastly, as far as the choice of loop goes, you're right. I'd change it in the main post if I still could edit it.


Well, it doesn't really matter if you use for or while loop in this case (I think that while loop is easier to grasp for people unfamiliar with coding, that's why I used it). What was mostly wrong in your original code was that you declared 'var value =' inside of the loop. If you tried to access it later then it might not have been set at all. Maybe not in this particular case, but it's usually better to always try and guard against such things in your code. Good habits go a long way :)

_________________
Time is precious. Waste it wisely.


11 May 2015 01:44
Profile
Site Admin
User avatar

Joined: 04 Mar 2010 01:14
Posts: 275
Zhar wrote:
Well, it doesn't really matter if you use for or while loop in this case (I think that while loop is easier to grasp for people unfamiliar with coding, that's why I used it). What was mostly wrong in your original code was that you declared 'var value =' inside of the loop. If you tried to access it later then it might not have been set at all. Maybe not in this particular case, but it's usually better to always try and guard against such things in your code. Good habits go a long way :)


Due to one of the oddities of javascript that's actually not true.
'var' declarations are always hoisted to the top of the current function scope.

https://developer.mozilla.org/en-US/doc ... r_hoisting


11 May 2015 10:07
Profile
Wizard
User avatar

Joined: 17 Apr 2012 12:09
Posts: 753
cotillion wrote:
Zhar wrote:
Well, it doesn't really matter if you use for or while loop in this case (I think that while loop is easier to grasp for people unfamiliar with coding, that's why I used it). What was mostly wrong in your original code was that you declared 'var value =' inside of the loop. If you tried to access it later then it might not have been set at all. Maybe not in this particular case, but it's usually better to always try and guard against such things in your code. Good habits go a long way :)


Due to one of the oddities of javascript that's actually not true.
'var' declarations are always hoisted to the top of the current function scope.

https://developer.mozilla.org/en-US/doc ... r_hoisting


One of the reasons I dislike JS. My IDE is always warning about possible variables without set values so I kind of got into the habit of declaring everything explicitly within the scope I want to use them.

_________________
Time is precious. Waste it wisely.


11 May 2015 10:48
Profile
Myth
User avatar

Joined: 09 Mar 2010 20:33
Posts: 1331
Location: UK
Been searching and searching cus I read this in the past but then got confused and though last target was something that was in gmcp data. Doh!

Glad I found it again, great example thank you!

_________________
http://genesisquests.pbworks.com/
Join up and help each other with Quests :)


28 May 2017 17:07
Profile
Veteran

Joined: 21 Mar 2016 09:17
Posts: 206
What the heck is all in that "gwc" thingy?

_________________
Alea iacta est. Serius regredi est.


29 May 2017 04:53
Profile
Great Adventurer

Joined: 24 Jan 2016 21:27
Posts: 198
Kwevin wrote:
What the heck is all in that "gwc" thingy?


In my experience, coding consists of copying stuff you have no idea how/why work (but they do) and then adding/replacing stuff to make your case work. So I wouldn't worry about that!


29 May 2017 16:19
Profile
Rising Hero
User avatar

Joined: 29 Feb 2016 19:51
Posts: 318
Location: Everywhere
Kwevin wrote:
What the heck is all in that "gwc" thingy?
I don't know what "gwc" stands for specifically, but it's likely a main global variable that relates to the document.
For instance, when coding a canvas element, these are the first two lines in your script:
Code:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
"ctx" is then used whenever you want to modify the canvas.
Such as:
Code:
  ctx.font = height*0.75 + "px Helvetica Neue";
  ctx.textBaseline="middle";
  ctx.fillStyle="green";
  ctx.fillText("Hello World");
This would print "Hello World" in green in the middle of the canvas.
But it wouldn't work without the "ctx"

"gwc" likely serves a similar purpose.

_________________
Chillin
[-_- ]
Click here to become a pupil of my Brute! It's really cool, I swear.


29 May 2017 18:58
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 11 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.