Table Of Contents

  1. Introduction
  2. What is if-then-else?
  3. The Syntax
  4. Operators
  5. $iif
  6. Another Example
  7. Common /if Mistakes (Article by blue-elf)
  8. Optimizing your /if's (Article by blue-elf & pai)
  9. Conclusion

Introduction  Back to Top

Welcome to this little article where we'll look at one of the key-elements in mIRC scripting, and for that matter, in any programming language; the if-then-else statement.

Required knowledge for this article is identifiers and aliases.


What is if-then-else?  Back to Top

If-then-else, or just if-statements is short terms for IF this is true, THEN do this, ELSE do something else. It's a tool that allows us to create code that is dynamically changing depending on several factors such as user input, mIRC version etc, instead of doing one thing and only this one thing. Knowing if-then-else is crucial if you want to become a good coder.


3. The Syntax  Back to Top

IF (v1 OPERATOR v2) THEN { execute this code } ELSE { execute this code }

We've also got a variation of this;

IF (v1 OPERATOR v2) THEN { execute this code }
ELSEIF (v1 OPERATOR v2) THEN { execute this code }
ELSE { execute this code }


4. Operators  Back to Top

An operator is a function or symbol that determines how v1 is compared to v2. Most common is ==, which means is equal to, < meaning is smaller than, > meaning is larger than.
Other commonly used operators are


=== (Case SenSiTive is equal to),
!= (is not equal to),
>= (larger or equal to),
<= (smaller or equal to),
isin (v1 is in v2),
iswm (v1 is a wildcard string in v2),
ison (v1 is on channel v2),
isop (v1 is an op on channel v2),
ischan (v1 is a channel which you are on).

There are others, consult the mIRC helpfile (/help if-then-else) for more info on the subject. You can also do multiple IF statements in one line by using && or || to combine them, && meaning AND (if (statement1) AND (statement2)), || meaning OR (if (statement1) OR (statement2)). Finally, you can negate an operator with placing a ! in front of the operator, thus !isop would mean (v1 is NOT an op on channel v2).

An example

alias hug {
  IF ($1 == $me) { describe $active gives himself a nice hug }
  ELSE { describe $active gives $$1 a nice hug }
}

This code basically says; IF word1 is your own nick, THEN do a /me gives himself a nice hug), ELSE do a /me gives word1 a nice hug. /describe is a command that does a /me to the target, in this case the target is $active, the active window.



5. $iif  Back to Top

This identifier is good for testing what an if statement would return, the syntax is:

$iif(statement is true,do this,else do this)

Try for instance

//echo -a $iif($chan(0) > 0,You're on one or more channels,You're not on any channels) $chan(0)

It will return the number of channels you're on, the if statement thus says; if you're on one or more channels, then echo "You're on one or more channels", else echo "You're not on any channels".

Aside from testing purposes, $iif is good for creating dynamic popups because just as with regular IF statements, you can omit the ELSE part, meaning you can do something like this..:

$iif($me isop $chan,Change topic): { 
  topic $chan $$?="Enter the new topic in # $+ " 
}

This popup would only be available when you're op'd in a channel, allowing you to change the topic of the channel. $iif is also good for producing messages where most of the words are similar, changing only a word or two depending on the user's input or other conditions such as channel modes or awaystatus...


6. Another example  Back to Top

alias bdeg { 
  IF ($2 == c) { RETURN $round($calc(($1 * 1.818) +32),1) }
  ELSEIF ($2 == f) { RETURN $round($calc(($1 - 32) * 0.55),1) }
  ELSE { RETURN Invalid input }
}

This is a custom identifier that converts Celsius degrees to Fahrenheit, and vice versa. Usage is $bdeg(N,C/F), N is the number of degrees to convert, C means that this number is degrees Celsius and should be converted to Fahrenheit, whereas F.... well, you know :)

Looking at line one, the if statement ($2 == c) says that IF word2 is c, THEN return the number in word1 first multiplied with 1.818, then added to 32, then rounded to 1 decimal. This will be the degrees in Fahrenheit. Line two says ELSE IF word2 is f, THEN return the number in word one subtracted with 32, then multiplied with 0.55, then rounded to 1 decimal. With these two lines, we've got ourselves functions that can convert the temperature, the third line says IF NONE of the above is true, THEN return Invalid input, as an error message.

Test this yourself,

//echo -a $bdeg(32,F) should return 0.0,
//echo -a $bdeg(0,C) should return 32.0, and
//echo -a $bdeg(88,F) should return 30.8.


7. Common /if Mistakes (Article by blue-elf)  Back to Top

This article summarizes some common (and not so common) mistakes scripters often make, mostly related to the use of /if.

1. Using >= And <=

Always remember that these operators must be consistent.
This is wrong:
IF ($1 => $2) 
IF ($1 =< $2)
The correct usage is:
IF ($1 >= $2) 
IF ($1 <= $2)

Notice how the equal sign is always last. Also note that, although <> is used for 'not equal' in some languages, in mIRC you must use != to mean 'not equal'.

2. Using isin

Many scripters abuse the isin operator. This leads to a lot of mistakes. For example:

IF ($right($1,4) isin .mp2.mp3)

what the scripter wants is to detect if $1 ends with a .mp2 or .mp3, but it might cause error if the end of $1 is 2.mp, for example. A better way of doing it:

IF ((*.mp? iswm $1) && ($right($1,1) isnum 2-3))
or
IF (($right($1,4) == .mp2) || ($right($1,4) == .mp3))

This is a longer way of doing it but more precise. This can be applied in many places, and although often not significant, it may make a difference in many cases.

3. isin and $istok

Sometimes, isin is used to check if an item is within a list. However, $istok (or $findtok) is often the right way of doing this. For example:

shelp { 
  IF ($1 isin j p plist addpack doffer) { GOTO $1 }
  commands 
}

The above would probably give an error if the user typed /shelp a, something the scripter wasn't looking for. The correct way of doing it would be:

shelp { 
  IF ($istok(j p plist addpack doffer,$1,32)) {
    goto $1 
  }
  commands 
}

The $istok identifier will specifically find only exact words. Note that the '32' is the ascii code for space, which is what separates the 'tokens', or words, here.

4. RETURN and HALT

Although not directly related to /if, this is one of the bigger mistakes many scripters make. Not knowing when to /halt and when to /return can cause many problems.

The return command can also be used to stop processing commands aside from returning values. The difference between the two is as follows:

/halt - stops script processing entirely, and halts any default mIRC behaviors
/return - stops that part of the script only
For example: scripters create aliases that can be called in other parts of the script, for example:
alias do { 
  msg $1 $2- 
  HALT 
} 
on +100:TEXT:*:#:{ 
  do $nick $1- 
  echo $nick sent $1- to you 
}

In the above, the /echo in the on text event will not trigger because it uses a /halt in the alias- which stops the entire script. Whereas, if /return was used, it will continue to echo. thus, in the following:

alias do { 
  msg $1 $2- 
  RETURN 
} 
on +100:TEXT:*:#:{ 
  do $nick $1- 
  echo $nick sent $1- to you 
}

In this, the echo will trigger because /return was used and not a /halt. A common place where /halt is improperly used is, in fact, with /if statements, often as an /else. For example:

alias do { 
  IF ($1 > %blah) { %blah = $1 } 
  ELSE { HALT } 
}

This alias may have the purpose of tracking the highest count of something. However, if the /if fails, the alias halts any script or alias that might have called it, which is probably not what was intended. Instead, a 'RETURN' should have been used, or in this case, simply leave the /else section out.



8. Optimizing your /if's (Article by blue-elf & pai)  Back to Top

This mini-article attempts to demonstrate some tricks and shortcuts that can be used in your /if statements, for speed and compactness.

True And False In /if Statements

/if (value) returns a "true" or "not null" result as long as value is a non-zero value. For example:

%i = 0 
:loop 
INC %i 
IF ($nick(#,%i)) { 
 echo $ifmatch 
 GOTO loop 
}
or
%i = $nick(#,0) 
:loop 
echo $nick(#,%i) 
DEC %i 
IF (%i) { GOTO loop }

With this method, many things can be shortened and optimized. To be specific, /if ($false), /if ($null), and /if (0) will be treated as false, (will not trigger) and anything else will be treated as true. (will trigger)

Another example:

back { 
  away 
  IF ($chan(0) >= 1) { ame is back! }
}

The above could be simplified using the following:

back { 
  away 
  IF ($chan(0)) { ame is back! }
}

Same thing as below:

input { 
  IF ($2 != $null) { echo second argument is $2 }
  ELSE { echo no second argument is given }
}
Simplified as:
input { 
  IF ($2) { echo second argument is $2 }
  ELSE { echo no second argument is given }
}

Note that negative values will not act like 0 values. thus, for example:

%i = -1 
IF (%i) { echo this line will trigger }
As compared with:
%i = 0 
IF (%i) { echo this line will not trigger }
Operator Shortcuts

Some simple simplifications by using different operators-

IF ($left($1,1) == /)

can be simplified with the code below:

IF (/* iswm $1)

In some cases:

IF ($1 isin abcdefghijklmopqrstuvwxyz)

simplified:

IF ($1 isletter)

Instead of:

IF ($me ison %chan)
use:
IF (%chan ischan)
Using Braces

When you write an if statement, you must normally enclose the group of commands in braces:

IF ($nick == $me) { 
  part $chan 
  HALT 
}

However, if you ONLY have one command, the braces are optional, and in fact slow things down ever so slightly:

IF ($nick == $me) { part $chan }
is the same as:
IF ($nick == $me) { part $chan }

although arguably not as nice looking. This one is really a matter of personal preference.

If And Goto

One of the biggest mistakes beginning scripters make is assuming that you MUST have an 'else' statement, or that you have to 'goto' to get to your commands. Commonly seen in scripts-

IF ($me isop $chan) { 
  do stuff 
} 
ELSE { 
  HALT 
}

In most cases, the 'else' section can be completely removed. Or another example, using goto:

IF($me isop $chan) { GOTO first } 
ELSE { GOTO second }
:first 
do stuff 
HALT 
:second 
do stuff

Instead of using gotos like this, just stick the code in the ifs:

IF ($me isop $chan) { 
  do stuff 
} 
ELSE { 
 do stuff 
} 

A final example of an if that doesn't need a goto:

IF ($me !isop $chan) { GOTO end }

This assumes that ':end' is a label at the end of the routine. Instead, just use 'return'- it will end the current alias or remote, without halting any default behaviors or other scripts. (same end effect.)


9. Conclusion  Back to Top

We've in this little article gone through one of the most important features of any coding, the IF-THEN-ELSE statement, and seen how it allows us to create code that reacts conditionally on the environment and the user's input. Note that in the case of single line if statements or execute sections, the ( )'s around the IF statement and the { } around the execute code is not needed, but it's still however generally recommended, as it's supposed to speed up the parsing of such statements and also produces easier-to-read code.

Also note that each code snippet needs the same number of opening { and closing } brackets, missing opening or closing brackets may result in code that's not executed in the correct order, is executed at the wrong time or just wrongfully executed in general. You can often spot this in your remotes if the beginning of an alias, remote or popup definition is indented (not quite to the left of the editor window). To check for bracket mismatches, you may also press the { } button, this will usually take you to the area where a bracket mismatch error occurs.



On Events - mIRC

Triggers or more commonly On Events are blocks of code that gets executed when a certain event occurs. This is how most channel bots, scripts, and games work. All events, with the exceptions of custom ones, get automatically called. (We will talk about custom events later on)

Syntax

Generally, most events will follow this format. Some will have additional parameters.

on <level>:<event>:<commands>
 
; or
 
on <level>:<event>: {
   ;Statement block
}

We should probably mention that the colon (":") is an important part of the event line. It effectively divides the different sections of the event into parts. As a result, certain parameters that accept input like text cannot include that character in them. We will touch on that a little later in this tutorial.

At this point I feel the need to talk more about how events work with respect to multiple script files. When some kind of an action take place, like a user entering a channel or a user quitting, mIRC will scan each file for a matching event. When a matching event is found, the code gets executed, and mIRC moves on searching of a matching event in the next file. As a result, you cannot have two identical events in the same file, only the first one will get executed. It means the order of definition of your event does matter, compared to aliases:

;this event triggers whenever someone says anything (the *) on the channel #help
on *:text:*:#help:{
 
}
;this one triggers when someone says !help on the channel #help
on *:text:!help:#help:{
 
}
With that order, when someone says !help, since the first event triggers for any text, it will triggers for !help, meaning the second event will never trigger, so this configuration doesn't make sense. However the other way around does:
on *:text:!help:#help:{
 
}
on *:text:*:#help:{
 
}
Now when someone says !help, it will trigger the first event, as we expect, while the other event will still trigger for any other text.


Note: These events are empty for the sake of the example

Levels

All events have an access level parameter. The access level parameter indicates which user access level can trigger this specific event. It is important to understand that mIRC's access levels are NOT related to access levels that are controls by IRC services like Anope's Services (ChanServ/NickServ).

Built-In Events

Built-In events are events that get executed whenever certain action took place in mIRC. For example, when a user joins a channel, you can write a script that will utilize the on join event which will voice the user.

When an event gets executed, a number of additional identifiers become accessible, we call them local identifiers. Some of the most common identifiers are (whenever applicable):

  • $nick - The nickname of the user that triggered the event
  • $chan - The channel name of where the event took place
  • $target - The name of where the event took place. (This can be a window, a query, or a channel name)
  • $wildsite - The address of the user who triggered an event (in *!*@host format)

Note: This is not an exhaustive list

On Join

The on join event triggers when a user joins one of the channels you are on.

Format:

on <level>:join:<target>:<commands>

Example:

on *:join:#:{
  notice $nick Welcome to $chan $+  !
}

In the example above, we made the on join activate for any channel (by specifying no name) by any user (denoted by the wildcard * character). When a user joins, this script will notice him and say "Welcome to #channel!"

On Kick

The on kick event triggers once a user has been kicked from a channel you are on.

Format:

on <level>:kick:<target>:<commands>

Example:

on *:kick:#:{
 
  msg $chan $nick $+ , Why did you kick $knick $+  ?
 
}

In the example above, we have used the very basic setup like the on join example. $knick is an identifier that returns the name of the kicked user.

On Text, Action, and Notice

All three events trigger when a user says something, as an action, as a notice, or in a channel.

Format:

on <level>:text:<matchtext>:<target>:<commands>
on <level>:notice:<matchtext>:<target>:<commands>
on <level>:action:<matchtext>:<target>:<commands>
  • <matchtext> - The match text is the text pattern that mIRC will use to compare with every user message. Once the text has been matched (and the channel if provided), the event will trigger.

Wildcard text pattern

The matchtext can contain wild characters:

  • * - matches any text
  •  ? - matches any single letter
  • & - matches any single word

For Example:

  •  !test - the matchtext will only match if the ONLY word is "!test"
  •  !test* - the matchtext will match if the text starts with "!test"
  • *!test - the matchtext will match if the text ends with "!test"
  • *!test* - the matchtext will match any text that has "!test" in it (anywhere)

The basic text pattern

The most basic on text event is the normal wildcard pattern:

on *:text:!help:#:{
 notice $nick For Help just state your question and pastebin any relevant code.
}

Sometimes we want to get the user's input. We can use the & to match a single word (in this case it will be a name, although it doesn't matter)

on *:text:!color &:?:{
  var %color = $gettok(white black red blue brown yellow orange green, $rand(1, 8), 32)
  msg $chan $2's random color is: %color $+ .
}

RegEx text pattern

The matchtext parameter can also be a Regular Expression Pattern by prefixing the user level with a dollar sign ($)

Example:

on $*:text:/^!test$/i:#:{
  msg $chan Test Worked!
}

Dynamic text pattern

Text matched patterns can also be dynamic, for example your name at the time of the execution ($me), a variable or time. In order for mIRC to know to evaluate the expression, it must be enclosed by the $() identifier.

Example:

on *:action:$(*slaps $me $+ *):#:{
  describe $chan Slaps $nick with dried-up sandwich!
}

If the entire match text pattern contains a SINGLE variable, the $() is not required.

Example:

;Assume %text is set to !cool
on $*:text:%text:#:{
  msg $chan I am the coolest! 
}

It is also possible to use regular expressions with dynamic match text.

on $*:action:$(/^slaps $me $+  /Si):#:{
  describe Slaps $nick with dried-up sandwich!
}
Target

The target parameter of the event defines the locations of where the event can be triggered from. For example, the on text event can be triggered by a channel message or by a query.

  •  ? - defines query location
  • # - defines channel location
  • * - defines both query and channel locations
  •  %var - A variable containing a channel or a list of channels is also acceptable

Example:

;let %chan equal #mSL,#help,#supprt
on *:text:!hi:%chan:{
  notice $nick Hello!
}

Custom Events

Custom events or signals are events that get called by a certain script instead of mIRC itself. These events are usually used in a framework script that lets the user that implements the script add his own code using the signal events without modifying the original script's code.

Syntax:

on *:signal:<eventName>:<command>