mScriptBox Tutorial
Custom Identifier

Written by Hammer
Published with permission.

Table Of Contents

  1. Introduction
  2. What is a custom identifier?
  3. New Functions: Write your own $functions, just like mIRC's
  4. Labelers: Ways to change popups or messages
  5. Replacers
  6. Readers: Using custom identifiers to make reading easier
    1. $read
    2. $readini
  7. Resolvers
  8. The $isid Identifier
  9. Conclusion

1. Introduction  Back to Top

Since custom identifiers are a special kind of alias, you need to know about aliases. This page assumes you know what an alias is and what parameters are; it just shows you how to use an alias in new and exciting ways. Remember, an alias can be added to an alias file or to a remote file. We'll use the remote file for consistency and ease of keeping track of them. Just precede the alias declaration with the word alias in a remote file.

In an Alias file:


slap { me slaps $$1 with a large, smelly trout } 
In a Remote file:

alias slap { me slaps $$1 with a large, smelly trout } 

You should already know what normal identifiers are and basically how to use them. For example, you should know how to use identifiers such as $ctime, $mircdir, $fulladdress, $nick(channel,number) or even $gettok(string,number,tokenseparator). These are the identifiers that come standard with mIRC. You should understand the use of $read and $readini - we'll be needing both of them!

If you know about all of these, you probably already know how to use variables, so I'll just assume that you do.


2. What is a custom identifier?  Back to Top

Simple: they are an alias that returns (or sometimes doesn't return) a value. They fall into several catagories, but they basically just return a value to wherever they were called from and insert it as if that value where put in that spot in the script or command.


3. New Functions: Write your own $functions, just like mIRC's   Back to Top

A very simple one might be to simply add two numbers and return the answer.

alias CI.add return $calc($1 + $2) 
You could call such an identifier from your script, perhaps an alias like this:

alias add {
  IF (($1 isnum) && ($2 isnum)) {
    echo $colour(info) -a *** ADD: $1 + $2 = $CI.Add($1,$2)
  }
}
Now you could just type:

/add 257 354 
And it would show in the active window:

*** ADD: 257 + 354 = 611

4. Labelers: Ways to change popups or messages   Back to Top

When you want to make your popup labels dynamic (make them change based on something), you can use a nifty little feature that the return command allows. By having a custom identifier as a label for your popups, you can make the label give you detailed information about the option you are about to select. You can also hide options that don't apply at the moment based on the status of your script or your status in the channel or the status of the nick or channel you want to run the popup on. In fact, you can hide whole sections of popups or make them "magically" appear at runtime.

For instance, if you only want your away configuration popups to show up when you're not marked away, simply have a custom identifier for your label that checks to see if you're marked away or not. (Granted, this is a simple example that might be better implemented using $iif(), but that identifier is much slower and cannot do what a custom identifier label can do.)

Here's one that gives you a top level Away section heading. It will check to see if you are marked away; if you are, it will only allow you to mark yourself back. If you're not marked away, you won't even see this option on the list. The next one checks to see if you are marked away as well; if you are not marked away, it will return a label for the rest of the away script options.


; Groups to hold the logging and paging script 
#CI.Logging off 
#CI.Logging end 
; 
#CI.Paging on 
#CI.Paging end 
; 
; Dynamic popup labels 
alias CI.Back {
  IF ($away) {
    RETURN Mark as Back 
  }
}
alias CI.Away {
  IF ($away == $false) {
    RETURN Away 
  }
}
alias CI.Logging { 
  IF ($group(#CI.Logging) == on) {
    return [+] Logging 
  }
  ELSE { return $chr(91) $chr(160) $+ $chr(93) Logging }
} 
alias CI.Paging { 
  IF ($group(#CI.Paging) == on) {
    return [+] Paging 
  }
  ELSE { return $chr(91) $chr(160) $+ $chr(93) Paging  }
} 

; Here are the popups, some of whose labels change! 
menu channel { 
  ; these first two will appear to occupy the same place in your channel popups, 
  ; one of them having a sub menu and the other just executing code! 
  $CI.Back:away 
  $CI.Away 
  .Mark as Away:away $$?="Why away?" 
  .- 
  .$CI.Logging:{ 
    IF ($group(#CI.Logging) == on) {
      .disable #CI.Logging
    }
    ELSE { .enable #CI.Logging }
    echo $colour(mode) -a *** Away: Logging is now $group(#CI.Logging) 
  } 
  .$CI.Paging:{ 
    IF ($group(#CI.Paging) == on) {
      .disable #CI.Paging
    } 
    ELSE { .enable #CI.Paging }
    echo $colour(mode) -a *** Away: Paging is now $group(#CI.Paging) 
  } 
} 

An interesting feature of popups is that if there's nothing under a menu to show, then nothing does show! This is handy if you want a dividing line to show, but only if you have something underneath it in your popups to show.
For instance, if you had set up your mIRC to Cancel away on keypress, then you won't ever need to mark yourself as back, so you could just replace the $CI.Back:away line with a - (hyphen). If you are not currently away, you'll see your away system with a divider above it; if not, you won't see anything. Tricky, but neat.


5. Replacers  Back to Top

Many people would like to replace every instance of "lol" with "Laughs Out Loud" anywhere on the line. One way of doing this is by creating replacement identifiers that you can use anywhere as a shorter way of typing out the whole thing, including the special formatting you want with it.

Below are three identifiers, each takes up one line, but on some screen resolutions they may appear to take more.


alias LOL {
  RETURN $+($chr(2),$chr(3),12L,$chr(15),aughs $chr(2),$chr(3),12O,$chr(15),ut $chr(2),$chr(3),12L,$chr(15),oud)
}
alias WB {
  RETURN $+($chr(2),$chr(3),12W,$chr(15),elcome,$chr(2) $chr(3),12B,$chr(15),ack)
}
alias ROTFL {
  RETURN $+($chr(2),$chr(3),12R,$chr(15),olling $chr(2),$chr(3),12O,$chr(15),n $chr(2),$chr(3),12T,$chr(15),
         he $chr(2),$chr(3),12F,$chr(15),loor $chr(2),$chr(3),12L,$chr(15),aughing)
  ; Note the above 2 lines have to be on a single line
}
You can even use this when you type by starting the line with //say or //me.

//me $LOL at Pasmal

* Hammer Laughs Out Loud at Pasmal

More to the point, however, it would make an on INPUT $reptok() much easier to read:


on *:INPUT:#:{ 
  IF (/* !iswm $1-) { 
    SET %CI.OutputString $1- 
    IF ($findtok(%CI.OutputString,lol,0,32)) { 
      SET %CI.OutputString $reptok(%CI.OutputString,lol,$LOL,1,32) 
    }
    IF ($findtok(%CI.OutputString,wb,0,32)) { 
      SET %CI.OutputString $reptok(%CI.OutputString,wb,$WB,1,32) 
    }
    IF ($findtok(%CI.OutputString,rotfl,0,32)) { 
      SET %CI.OutputString $reptok(%CI.OutputString,rotfl,$ROTFL,1,32) 
    }
    say %CI.OutputString 
    UNSET %CI.OutputString 
    HALT 
  } 
}


6. Readers: Using custom identifiers to make reading easier   Back to Top

$read and $readini are identifiers which tend to give scripters fits until they really understand them, and even then, they'll make mistakes. Here's one way to use a custom identifier to make using $read easier, followed by a way to make $readini easier for script configuration control.


6a. $read  Back to Top

Your script has a file just full of funny kick messages. You want to clean up your script a little, so you've made yourself a custom identifier to return that message for you. Optionally, you can specify a line number you want and it will return that line for you (assuming you know what's on that line).

In order to do this, we need an if statement to find out if there is a line number; if there is, then return the requested line from the kickmsgs.txt file, otherwise pick a random one and return that.

We will always use the same file for this identifier - that means we won't have to pass in a filename everytime! And finally, we want to check the first parameter to see if there is a dash (ascii 45) in it, indicating a specific range from which to pick. If the first parameter is not a number (a line number you can read from in the kickmsg file) then give out the generic kick message.

Assuming that the kickmsg.txt file is in the $mircdir:

alias CI.kickmsg { 
  IF ($1 !isnum)
  {
    RETURN Have a wonderful day...but not here! 
  }
  ELSEIF ($1 isnum) { 
    IF ($gettok($1,0,45)) {
      RETURN { $read -l $+ $rand($gettok($1,1,45),$gettok($1,2,45)) kickmsg.txt }
    }
    ELSE { RETURN $read -l $+ $1 kickmsg.txt }
  } 
  ELSE { RETURN $read(kickmsg.txt) }
}

All we need to do to include a random kick message now is use the $CI.KickMsg identifier we've just created wherever we kick.
We can use $CI.KickMsg for a random one, $CI.KickMsg(15) for the 15th line of our file, or $CI.KickMsg(50-65) to have it pick one from the lines 50 through 65; this idea is very useful if you have your file set up with appropriate and known ranges of kick message styles (50-65 might be different flood kick messages).


alias kb { 
  IF ($me isop $chan) { 
    ban $chan $$1 3 
    kick $chan $$1 $CI.kickmsg($2) 
  } 
  ELSE { echo $colour(mode) -a *** Kick/Ban: You are not a channel operator }
}
Now we want to see how to use these in a channel as a channel operator:

To kick/ban Pasmal with the standard message: /kb Pasmal d
To kick/ban Pasmal with a random message: /kb Pasmal
To kick/ban Pasmal with the message from line 15: /kb Pasmal 15
To kick/ban Pasmal with a random message from the range of lines 50 to 65: /kb Pasmal 50-65


6b. $readini  Back to Top

We are keeping all of our flood kick configuration information in a single file with sections for number of lines per number of seconds for each channel in which we op. We have the same kind of information for repeats stored in its own file. These files are called FloodConf.ini and RepeatConf.ini. One way to approach this is to have a separate identifier for each file and ask for the information you want.

alias CI.FloodSettings { RETURN $readini(floodconf.ini,$chan,$1) }
alias CI.RepeatSettings { RETURN $readini(repeatconf.ini,$chan,$1) }

You could include showing the settings for that channel when you op up in that channel, including the on/off status plus the number of lines in however many seconds for that channel.

; Groups to hold the flood protect and repeat protect script


#CI.FloodProtect on 
#CI.FloodProtect end 
; 
#CI.RepeatProtect on 
#CI.RepeatProtect end 

on me:*:OP:#:{ 
  echo $colour(info) -a *** $iif($group(#CI.FloodProtect) == on,[+],[ ]) 
    Flood Protection for $chan: $CI.FloodSettings(lines) lines in $CI.FloodSettings(seconds) seconds 
  ; The above 2 lines have to be on a single line	
  echo $colour(info) -a *** $iif($group(#CI.RepeatProtect) == on,[+],[ ]) 
    Repeat Protection for $chan: $CI.RepeatSettings(lines) lines in $CI.RepeatSettings(seconds) seconds 
  ; The above 2 lines have to be on a single line	
}
Which will show up like this:

*** ChanServ sets mode: +o Hammer
*** [+] Flood Protection for #HelpDesk: 10 lines in 5 seconds
*** [ ] Repeat Protection for #HelpDesk: 5 lines in 3 seconds


7. Resolvers  Back to Top

Here's an idea that's not too far away from a new numeric function, but it deals with time instead. But what if you wanted to add the exact time zone you were in, including the correct Standard/Daylight setting? Well, one way (this is geared for US timezones - the rest of the time zones are left to you as an exercise!) would be to use a custom identifier to return it for you. Like this:

alias CI.TZ.USA { 
  IF ($timezone == 14400) { SET -u0 %TZ (Atlantic }
  ELSEIF ($timezone == 18000) { SET -u0 %TZ (Eastern }
  ELSEIF ($timezone == 21600) { SET -u0 %TZ (Central }
  ELSEIF ($timezone == 25200) { SET -u0 %TZ (Mountain }
  ELSEIF ($timezone == 28800) { SET -u0 %TZ (Pacific }
  ELSEIF ($timezone == 32400) { SET -u0 %TZ (Alaskan }
  ELSEIF ($timezone == 36000) { SET -u0 %TZ (Hawaii-Aleutian }
  ELSEIF ($timezone == 39600) { SET -u0 %TZ (Samoa }
  IF ($daylight) { SET -u0 %TZ %TZ Daylight Time) }
  ELSE { SET -u0%TZ %TZ $+ Standard Time) }
  RETURN %TZ 
} 

alias SayTime  {
  say It's $asctime(hh:nn:ss tt) $CI.TZ.USA here right now 
}
By typing /SayTime in a window, you'd get the following in the active window:

<Hammer> It's 11:01:23 pm (Eastern Daylight Time) here right now


8. The $isid Identifier - Written by dohcan  Back to Top

Ever wondered if you can create aliases and identifiers that share the same name, like the /nick command used for changing your own nick and the remote $nick identifier that returns the nickname of the person who triggered the the action?

Before mIRC v5.6, this really wasn't practical, but one of the new additions of of 5.6 was the identifier $isid, which applies to custom aliases. With the identifier, you can tell if the alias was called using /aliasname or $aliasname. If it was used as a command, $isid returns false. If it was used as an identifier, $isid returns true.

I would say this is more of a vanity feature. You could always get by and simply name your aliases and identifiers different names, and never have any conflicts. With $isid, however, you could write some code that is a bit cleaner. For one of the addons I created, I was regularly reading and writing to an .ini file. I had created the aliases:

alias c.set {
  IF (($len($1)) && ($len($2)) && ($len($3))) {
    writeini settings.ini $1 $2 $3-
  }
  ELSE { echo -a * c.set: invalid syntax }
}
alias c.get {
  IF (($len($1)) && ($len($2))) {
    RETURN $readini settings.ini $1 $2
  }
  ELSE { echo -a * $!c.get: invalid parameters }
}
Then I would use them in the form of:
/c.set <section> <key> <value>
$c.get(section, key)
Using $isid, this could be rewritten as one alias called c.set:
alias c.set {
  IF ($isid) {
    IF (($len($1)) && ($len($2))) {
      RETURN $readini settings.ini $1 $2
    }
    ELSE { echo -a * $!c.set: invalid parameters }
  }
  ELSE {
    IF (($len($1)) && ($len($2)) && ($len($3))) {
      writeini settings.ini $1 $2 $3-
    }
    ELSE { echo -a * c.set: invalid syntax }
  }
}
And now I would use:
$c.set(section, key)
/c.set <section> <key> <value>

If we had several instances where we could use this, we could simply devote an alias for each section that is needed, and not have to bother remembering all of the different alias names.

On a side note, if you are using this technique for something that is very cpu-intensive, it would probably be best to not use $isid, but for most cases, I think the performance hit would be negligible


8. Conclusion  Back to Top

You've now seen some of the very cool things you can do with custom identifiers. There are many, many more ideas to be discovered than could ever possibly be covered in an entire web site; the only limitation you have is your own imagination. Have fun.