Table of Contents:
This tutorial will take you through some of the known problems
in mIRC, and how to solve them. Most experienced scripters are
probably already aware of these, but this tutorial aims at the
average newbie who isn't enlightened in these matters.
I really hope you will learn something by reading this, and thus becoming
a better scripter, or more important, developing your logical skills.
If you have any questions regarding this tutorial or anything else related to scripting,
check the contact information at the bottom of the page.
Enjoy!
What is debuging?
How do I debug my code?
Why should I debug?
People new to programming are very ignorant to the importance of debuging,
but what exactly is debuging? Let's look up the word 'debug' in a dictionary:
To search for and eliminate malfunctioning elements or errors. Locate and correct errors in a computer program code; "debug this program"So, basically it means "finding the error". Fair enough. But how?
alias readfile { var %file = $1 var %line = $2 var %read = $read($1,$2) echo %read } /readfile myfile.doc Nothing happens when we execute the command above.
Why? We do not know the cause of this unintended behaviour. Yet. Lets debug it:
alias readfile { var %file = $1 var %line = $2 var %read = $read($1,$2) echo Value of % $+ file? %file echo Does %file exists? $isfile(%file) echo Does the line exist? $iif(%line <= $lines(%file),yes,no) echo Did you even provide me with a line number? $iif($2 == $null,no,yes) echo %read }
We execute the command once again and get the following output:
Value of %file?myfile.doc Does myfile.doc exists?$false Does the line exist?no Did you even provide me with a line number?no
Bingo! Lets go through the results. Checking the value of your variables is an essential part
of debuging, you need to know where they are set, where they are altered, or if they are set at all. In this
example the variable
That wasn't too hard to understand, right? But to make the code even more verbose, you should unsilence all your silenced commands to access some more information and possible errors. Consider this:
alias readfile { .fopen handle mir.ini var %read = $fread(handle) .fclose handle echo %read } /readfile
Same problem as the previous code, nothing happens when we execute it (this one requires no parameters). Lets debug shall we?
alias readfile { fopen handle mir.ini var -s %read = $fread(handle) fclose handle echo %read }
Now the command produces the following output:
* fopen unable to open 'handle' (C:\Program\mIRC\mir.ini) - * Set %read to - * fclose closed 'handle' (C:\Program\mIRC\mir.ini)
Ding-ding-ding! Problem spotted.
That's it! Debuging isn't hard at all, once you know the actual meaning of the word. So the next time you decide to ask someone for help, make sure you have debuged your code BEFORE you ask, since this may piss some people off. Well this concludes this chapter.
TopMaking the proper error checkings prevents a code from being used in the wrong way, and tells the program what terms is in play. Let you control the program, and do not let it run freely without any indication on where to stop. See at it like a teenager. If you do not set limits and boundraries, he or she will eventually end up being a cracker. We do not want a cracker program. So what can we do?
Examine the code below.
alias readfile { echo $read(mirc.ini,$1) } /readfile 5
Everything looks fine, and it will work as long as we supply it with an appropriate parameter.
But what if the parameter isn't of the desired type? In this example we are the one who's choosing
the parameter, and we know it has to be a number higher than
alias readfile {if $1 isnum 1- { echo $read(mirc.ini,$1)} }
Now it requires a number higher than
on *:SOCKOPEN:mysocket:{ sockwrite -nt $sockname Hello World echo We want this to echo, but it never will. } /sockopen mysocket localhost 666 Produces: * /sockwrite: 'mysocket' not connected (line XX, scriptfile.ext)
This is generating an error which CANNOT be muted with the dot prefix. The error is also
halting further processing, which we may not want. Luckily for us, socket events in mIRC has
on *:SOCKOPEN:mysocket:{ if $sockerr { echo An error occured! } else { sockwrite -nt $sockname Hello World } echo Now this part will echo. } /sockopen mysocket localhost 666 Produces: An error occured! Now this part will echo.
Even though the socket is never opened, we allow the script to continue processing even if there's an error. This is not the only reason to check for errors, you wont have to see your status window filling up with unmutable error messages, which can be very annoying if they are recurring. I hope you realize the point of errorchecking, it is an important part of making your program do what you want, and nothing else. In some occasions it prevents the pain of debuging the code. Anyway, enough of this.
TopThe
alias marriage { if $2 == Lisa && $1 == John || $1 == Mike { echo $1 will marry $2 } else { echo $1 will NOT marry $2 } }
The point of this script is to decide to whom Lisa will marry (yes, mIRC can also solve love problems).
/marriage John Lisa /marriage Mike Lisa /marriage Mike John /marriage Mike Mike Produces: John will marry Lisa Mike will marry Lisa Mike will marry John Mike will marry Mike
Two ordinary weddings, one gay wedding, and one single person wedding (poor schizophreniac Mike). To elaborate the processing of this condition, we can illustrate it like this:
Condition: if $2 == Lisa && $1 == John || $1 == Mike Intention: The condition should evaluate totrue if a)$2 isLisa , and$1 isJohn . b)$2 isLisa , and$1 isMike . Reality: This condition will evaluate totrue if a)$2 isLisa and$1 isJohn b)$1 isMike .
Mike will marry anyone, and this is obviously not what we want. But what do we change? We use () parenthises to tell mIRC how to parse the condition.
alias marriage { if $2 == Lisa &&( $1 == John || $1 == Mike) { echo $1 will marry $2 } else { echo $1 will NOT marry $2 } }
And when we try the same inputs again..
/marriage John Lisa /marriage Mike Lisa /marriage Mike John /marriage Mike Mike Produces: John will marry Lisa Mike will marry Lisa Mike will NOT marry John Mike will NOT marry Mike
Mike is both straight and sane! Remember, you do not have to use
This is a neverending discussion whether or not to use brackets/braces when scripting for mIRC. This is of course, each individuals opinion and preference, and it is really up to you if you want to use them or not. I will go through the combinations (including abscence) of brackets and braces.
if (($me == John) && ($nick == Mike)) { echo whatever } on *:TEXT:hello:#:{ if ($nick isop $chan) { msg $chan Hi $nick } }
This is standard for most people, it will parse every piece correctly but at the expense of readability. Of course, if you are used to this type of structure it wont be fugly to you. This is also the method of choice for beginners in mIRC scripting.
if ($me == John) && ($nick == Mike) echo whatever on *:TEXT:hello:#:if ($nick isop $chan) msg $chan Hi $nick
This method is also fine and will be parsed correctly, if you use
if $me == John && $nick == Mike echo whatever on *:TEXT:hello:#:if $nick isop $chan msg $chan Hi $nick
This
if $me == John && $nick == Mike { echo whatever } on *:TEXT:hello:#:if $nick isop $chan { msg $chan Hi $nick }
This is my personal preference, it will always be parsed correctly since we are using
if $me == John && $nick == Mike { echo whatever } on *:TEXT:hello:#:{ if $nick isop $chan { msg $chan Hi $nick } }
The reason why I dislike
The most common error/bug in mIRC scripting. Could sometimes be tricky to spot but let me explain it to you. When mIRC processes a scriptfile, it checks for events and will only trigger the FIRST of the events in question. To illustrate this behaviour, have a look at this:
on *:START:echo This will echo. on *:START:echo This will NOT echo (above event was triggered).
Fair enough, they are indeed identical. But what if a matchtext field was involved?
on *:TEXT:*:#:echo This will echo. on *:TEXT:!boo:#:echo This will NOT echo (above event was triggered).
Now
a) Put the events in seperate scriptfiles and make sure that event is the only one of its kind. b) Change the order of the events, put the!boo event above the* one. c) Integrate them into one single event usingif branches to seperate the tasks.
on *:TEXT:!boo:#:echo This will echo. on *:TEXT:*:#:echo This will also echo. or... on *:TEXT:*:#:{ if $1- == !boo { echo First task. } else { echo Second task. } }
Note that if the events have seperate target fields
on *:TEXT:*:?:echo This will echo. on *:TEXT:*:#:echo This will also echo.
Of course, the most appropriate measures of avoiding this problem is to use different scriptfiles for each script/snippet, and to integrate the tasks in one single event (which will improve performance as well).
TopTimers can cause some problems when using
alias time.in.titlebar { .timer $+ time 10 1 titlebar $time } /time.in.titlebar
This will set the time to the same value over and over again. Why? Because
//time.in.titlebar | echo -a $timer(time).com Produces: titlebar 17:41:19
Luckily timers re-evaluate the
alias time.in.titlebar { .timer $+ time 10 1 titlebar$!time } alias time.in.titlebar { .timer $+ time 10 1 titlebar$ $+ time } alias time.in.titlebar { .timer $+ time 10 1 titlebar$eval($time,0) }
Any of these will work, and
alias timer.test { .timer 1 1 echo -t First line.| echo -t Second line. } /timer.test Produces: 17:58:24 Second line. 17:58:25 First line.
This will not work as intended, watch.
Commands: .timer 1 1 echo First line. | echo Second line. Intention: Set a timer with two commands: a) echo First line. b) echo Second line. Reality: Sets a timer with one command, and performs the next command a) .timer 1 1 echo First line. b) echo Second line. You cannot use{} braces to prevent this either, but there are solutions. a) Prevent| command seperator from being evaluated.$chr(124) and$(|) are two examples. b) Put the commands in an alias and make the timer call the alias instead.
Example:
alias timer.test { .timer 1 1 echo -t First line.$chr(124) echo -t Second line. } /timer.test Produces: 18:00:29 First line. 18:00:29 Second line.
Be aware of this, if something looks like it has been evaluated twice, check your timers. Note that this
re-evaluating behaviour also applies to
I can't count the number of times I've seen a user who has more than one input event (which sends data to the server).
This can be quite tricky if you create or get a script with such input event, while you already have on in another
scriptfile. If both events executes
on *:INPUT:#:{ if /* !iswm $1 { msg $chan ( $1- ) haltdef } } at the same time in another scriptfile.. on *:INPUT:#:{ if /* !iswm $1 { msg $chan [ $1- ] haltdef } }
Now you will
The purpose of a matchtext is to filter out unwanted lines, but this has some hidden issues which some aren't really aware of.
on *:TEXT:!my* :#:{ msg $chan My $2 is big. }
This is a poor matchtext for this kind of script. Watch.
!mymomisafilthyhoe Produces: My is big.
First of all, it only checks for a line starting with
on *:TEXT:!my * :#:{ msg $chan My $2 is big. }
But what if we do not want that second parameter required? We want to be able to write
on $*:TEXT:/^!my($| )/i :#:{ msg $chan My $iif($2 != $null,$2,car) is big. }
Ok, so what does this do? Instead of a wildcard match we are using a regexp which will match
Inefficient code: on *:TEXT:* :#:{ if $1 == !on { msg $chan Script is on. } elseif $1 == !off { msg $chan Script is off. } } Better code: on $*:TEXT:/^!(on|off)$/i :#:{ if $regml(1) == on { msg $chan Script is on. } else { msg $chan Script is off. } }
This also eliminates the problem of double events in most cases. Moving on..
TopThe extra
on ^*:TEXT:*:#:{ haltdef echo $chan $1-3 $bold($4) } alias bold { return $chr(2) $+$$ 1 $+ $chr(2) }
What's wrong with this code you ask? Basically, if
This is a bug rare known to beginners (and many experienced scripters as well). As far as I know
the bug only appears in the
on *:JOIN:#:{ echo Address of $nick : $address($nick,5) }
Sometimes
When making scripts that sends data to the server and allowing other users to trigger it,
you will need to protect yourself from the infamous
on *:TEXT:!trigger:#:{ msg $chan You have triggered me! }
Bad code. Lets fix it.
on *:TEXT:!trigger:#:{ .timerflood. $+ $nick 1 1 msg $chan You have triggered me! }
This will limit the triggering to once per second per nick. Another example:
on *:TEXT:!trigger:#:{ if %count <= 3 { msg $chan You have triggered me! inc -u3 %count } }
This will limit triggerings from everyone. The variable increases by one every triggering, and is unset 3 seconds after it's increased (unless another triggering increases it again). As long as the variable is below 3 it will perform the task given, otherwise it will just ignore the trigger until the variable has been unset.
If you do not want a custom flood protection, take a look at: /help /flood
TopEver had the problem with an
//echo $count(myggan,g)
Should echo
/echo [color] [-cdeghiNtsaqlbfnmr] [color name] [#channel|[=]nick]
Notice the
/echo 2
This will try to echo a
When echoing a string with color ctrl codes, make it a habit to PAD your color index number
with a leading
//var %string = foobar | echo -a $chr(3) $+4 $+ %string
Works quite fine. But what if
//var %string =0 foobar | echo -a $chr(3) $+ 4 $+ %string
No longer working. Why? Because that
//var %string = 0foobar | echo -a $chr(3) $+0 4 $+ %string
This applies to the background color index as well (
alias fixcolor { var %index = 1, %result while $eval($ $+ %index,2) != $null { %result = $addtok(%result,$base($ifmatch,10,10,2),44) inc %index } return %result } //echo -a $fixcolor(2) //echo -a $fixcolor(5,7) Produces: 02 05,07
This is the deadliest of sins. The help file contains the information you need in 95-100% of the cases.
And just because you do not understand what is said in the helpfile, doesn't mean it's not wellwritten,
it only means you didn't put enough effort in reading and understanding the text. The
However, if you (like me) find me helpfile somewhat tiresome to find stuff in, or if you feel something missing, take a look at these tools:
/rtfm - instant /help by myggan Updated mIRC Helpfile by Teazle mIRC Chm Help 6.16 Anchored by AdrenalinTop
Everyone needs help sometimes, and that's fine. Alot of IRC networks and Web forums have volunteering helpers, which will offer you help 100% for free, without anything to gain. If you marsch into a channel or into a forum with a cocky attitude, you will have one or more of these scenarios ahead of you:
a) People will get pissed off. b) People will laugh at you. c) People will ignore your need of aid. d) People will think you have a small penis.If you have a question, do not hesitate to ask. You should not ask for permission to ask a question, which is quite paradoxal if you think about it. Classical questions like these will only annoy people:
a) Can anyone help me? b) I need help! c) My script does not work, what is wrong? d) This is a help channel, help me!Remember, demanding help from a non-profit organization is retarded. Here are three key elements in getting helped quickly and easy:
a) Being straightforward, and provide the helpers with sufficient information (debug/error messages) b) Being humble, respect the helpers aiding you without any personal gain. c) Speak english if the channel/forum is international.
Also, follow these steps BEFORE asking questions:
1) a) If you are searching for a particular script, search google and the popular mirc scripting sites. b) If you have a piece of code, test it by yourself and examine the results. c) If you have a question on how to do something, just ask. 2) View debug/error messages and try to correct your code. 3) Read the manual for command syntaxes, use of switches, other notes, etc.. 4) a) Collect debug information and error messages and paste them along with the code in a pastebin. b) Paste the URL in the channel/forum along with a basic briefing on your problem. c) Wait for someone to answer, and try to solve it on your own while waiting. Pastebins: www.pastebin.com www.nomorepasting.com www.google.com/search?q=pastebin Scripting Sites: www.google.com/search?q=mirc+scripting
This tutorial was written by myggan (11/12-2005)
If you have any questions, feel free to contact me:
IRC: irc.quakenet.org -> #Scripting irc.dal.net -> #Scripting MSN: [email protected] (mail as well) WEB: http://www.mircscripts.org/users/myggan Thanks for reading! :)