eventMacro: Difference between revisions

From OpenKore Wiki
Jump to navigation Jump to search
No edit summary
m (Conversion script moved page EventMacro to eventMacro: Converting page titles to lowercase)
 
(60 intermediate revisions by 7 users not shown)
Line 1: Line 1:
== Description ==
== Description ==
* This plugin is a complete rework of the macro plugin, it has been written to be event-based and way less CPU intensive than it's predecessor.
* With this plugin you can create complex blocks of conditions called automacros and blocks of consecutive actions called macros.
* With this plugin you can create complex blocks of conditions called automacros and blocks of consecutive actions called macros.
* Macros can be called by one or more automacros when their conditions become true or be called by hand using a console command.
* Macros can be called by one or more automacros when their conditions become true or be called by hand using a console command.
* Automacros have simple to use conditions like base level, zeny, job class and many others.
* Automacros have simple to use conditions like base level, zeny, job class and many others.
* Macros can be as simple as 'say something in chat' or 'save in kafra' and as complex as 'do a complete quest'.
* Macros can be as simple as 'say something in chat' or 'save in kafra' and as complex as 'do a complete quest'.
* This page was last updated with the current version at the moment being 324.


== Installation ==
== Installation ==
* Download the eventMacro plugin. You can download it from the following link:
<span style="color:red">* eventMacro plugin is now included and enabled by default in openkore.</span style>
** [https://github.com/Henrybk/eventMacro '''Github''' Head version from the developer page]
 
* Go to your OpenKore main folder (''the folder which contains the file openkore.pl'') and create a subfolder called '''plugins''', if there isn't already one. Create a subfolder '''eventMacro''' in it.
* Inside the eventMacro plugin's zipfile (normally eventMacro-master.zip), you will find the file '''eventMacro.pl''', the folder '''eventMacro''' and other files and folders. Extract them to your plugins/eventMacro folder, so '''eventMacro.pl''' ends up in plugins/eventMacro/eventMacro.pl.
* In your OpenKore control folder, create a blank file named '''eventMacros.txt'''. In this file you will put your macros/automacros.  
* In your OpenKore control folder, create a blank file named '''eventMacros.txt'''. In this file you will put your macros/automacros.  
After installation, your OpenKore file tree should look like this (''ignoring OpenKore's own files''):
openkore
|-- openkore.pl
|-- control
|  |-- eventMacros.txt
|-- fields
|-- logs
|-- plugins
|  |-- eventMacro
|  |  |-- eventMacro
|  |  |  |-- Automacro.pm
|  |  |  |-- Condition.pm
|  |  |  |-- Core.pm
|  |  |  |-- Data.pm
|  |  |  |-- FileParser.pm
|  |  |  |-- Lists.pm
|  |  |  |-- Macro.pm
|  |  |  |-- Runner.pm
|  |  |  |-- Utilities.pm
|  |  |  |-- Validator.pm
|  |  |  |-- Validator
|  |  |  |  |-- ListMemberCheck.pm
|  |  |  |  |-- NumericComparison.pm
|  |  |  |  |-- RegexCheck.pm
|  |  |  |-- Conditiontypes
|  |  |  |  |-- ListConditionEvent.pm
|  |  |  |  |-- ListConditionState.pm
|  |  |  |  |-- MultipleValidatorEvent.pm
|  |  |  |  |-- MultipleValidatorState.pm
|  |  |  |  |-- NumericConditionEvent.pm
|  |  |  |  |-- RegexConditionEvent.pm
|  |  |  |  |-- RegexConditionState.pm
|  |  |  |  |-- SimpleEvent.pm
|  |  |  |-- Condition
|  |  |  |  |-- AttackEnd.pm
|  |  |  |  |-- AttackStart.pm
|  |  |  |  |-- AttackStartRegex.pm
|  |  |  |  |-- BaseLevel.pm
|  |  |  |  |-- CartCurrentSize.pm
|  |  |  |  |-- CartCurrentWeight.pm
|  |  |  |  |-- CartMaxSize.pm
|  |  |  |  |-- More conditions...
|  |  |-- test
|  |  |  |-- unit_tests.pl
|  |  |  |-- RunnerStatementTest.pm
|  |  |  |-- RunnerParseCommandTest.pm
|  |  |  |-- LoadConditionsTest.pm
|  |  |  |-- GlobalVarRegexTest.pm
|  |  |  |-- FindVarTest.pm
|  |  |  |-- DynamicAutoVarsTest.pm
|  |  |  |-- CoreVarFunctionsTest.pm
|  |  |  |-- Validator
|  |  |  |  |-- ListMemberCheckTest.pm
|  |  |  |  |-- NumericComparisonTest.pm
|  |  |  |  |-- RegexCheckTest.pm
|  |  |  |-- textfiles
|  |  |  |  |-- DynamicAutoVarsTest.txt
|  |  |  |  |-- DynamicAutoVarsTest2.txt
|  |  |  |  |-- DynamicAutoVarsTest3.txt
|  |  |  |  |-- empty.txt
|  |  |  |  |-- LoadConditionsTest.txt
|  |  |-- eventMacro.pl
|-- src
|-- tables


== Console Commands ==
== Console Commands ==
=== Syntax ===
=== Syntax ===
  eventMacro [MACRO|auto|list|status|check|stop|pause|unpause|var_get|var_set|enable|disable] [extra]
  eventMacro [MACRO|auto|list|status|check|stop|pause|unpause|var_get|var_set|enable|disable|include] [extra]


; eventMacro MACRO
; eventMacro MACRO
: Run macro MACRO
:* Runs macro MACRO.


Runs macro <macroname>.
{|class="indextable" style="text-align:center;"
 
{| class="wikitable" border="1" cellspacing="0"
|-style=background-color:#F9F9F9;
! Option
! Option
! Value
! Value
! Description
! Description
|-
|-
|align=center| -repeat
|align=center| -repeat | -r
|align=center| n
|align=center| n
|align=center| repeat the macro '''n''' times  
|align=center| repeat the macro '''n''' times  
Line 111: Line 40:
|-  
|-  
|align=center| -orphan
|align=center| -orphan
|align=center| method
|align=center| terminate <br/> reregister <br/> reregister_safe <br/> terminate_last_call
|align=center| use method for handling orphaned macros
|align=center| use method for handling orphaned macros
|}
|}




Parameters for the macro can be specified after a double dash (--). These parameters are saved to the variables $.param1 to $.paramN. Example:  
Parameters for the macro can be specified after a double dash (--). These parameters are saved to the array @.param. Example:  


  macro foo {
  macro foo {
   log Parameter 1 is $.param1
   log Parameter 1 is $.param[0]
   log Parameter 2 is $.param2
   log Parameter 2 is $.param[1]
  }
  }


Line 126: Line 55:
When called as '''''eventMacro foo -- foo bar''''' it would print out  
When called as '''''eventMacro foo -- foo bar''''' it would print out  


  [eventmacro log] Parameter 1 is foo
  [eventmacro message] Parameter 1 is foo
  [eventmacro log] Parameter 2 is bar
  [eventmacro message] Parameter 2 is bar


; eventMacro auto AUTOMACRO
; eventMacro auto AUTOMACRO
Line 138: Line 67:
: Shows current status of automacro, macro or both
: Shows current status of automacro, macro or both


; eventMacro check [force_stop|force_start|resume]
; eventMacro check (force_stop|force_start|resume)
: Sets the state of automacros checking
: Sets the state of automacros checking


Line 150: Line 79:
: Unpauses current running macro
: Unpauses current running macro


; eventMacro var_get
; eventMacro var_get [var]
: Shows the value of one or all variables
: Shows the value of one or all variables


; eventMacro var_set
; eventMacro var_set var_name value
: Set the value of a variable
: Set the value of a variable


Line 162: Line 91:
: Disable one or all automacros
: Disable one or all automacros


; eventMacro include (on|off|list) [filename or pattern]
: Enables or disables !include in eventMacros file


== Configuration files ==
== Configuration files ==
Line 169: Line 100:


; control/timeouts.txt
; control/timeouts.txt
: Add '''''eventMacro_delay''''' and set it to the number of seconds you want the plugin to pause between commands.  
: Add '''''eventMacro_delay''''' and set it to the number of seconds you want the plugin to pause between commands. Default value: 1.


; control/config.txt
; control/config.txt
{| class="wikitable" border="1" cellspacing="0"
{|class="indextable" style="text-align:center;"
|-style=background-color:#F9F9F9;
!Option
!Option
!Value
!Value
Line 221: Line 151:


; log <''text''>
; log <''text''>
: Prints a text in the console. Can contain macro $variables and @stuff.
; warning <''text''>
; error <''text''>
: Prints a text in the console. Can contain macro $variables and &stuff.


  macro foo {
  macro foo {
   log This line logs a text to console.
   log This line logs a text to console.
   log All your base are belong to us!
   warning All your base are belong to us!
  }
  }


Line 242: Line 174:




; call <''macroname''> [<''n''>]  
; call <''macroname''> [<''parameters''>]  
: Calls macro <''macroname''> [<''n''> times]. When <''macroname''> is finished the current macro continues.  
: Calls macro <''macroname''> [set <''parameters''>]. When <''macroname''> is finished the current macro continues.  
: <''macroname''> can be a variable (ex: call $killmacro)




Line 256: Line 189:
; stop
; stop
: Immediately terminates the running macro.
: Immediately terminates the running macro.
; include (<''on''> | <''off''> | <''list''>) [<''filename''> | <''pattern''>]
: Enables or disables !include in eventMacros file
include [on|off|list] [filename or pattern]




Line 280: Line 219:
: '''Array'''
: '''Array'''
:* Array variables hold a '''list''' of things.
:* Array variables hold a '''list''' of things.
:* Each member inside the array list has a index, which is it's position inside the list.
:* Each member inside the array list has a index, which is its position inside the list.
:* The first index of an array is always '''0''', and the '''last''' is always the '''size of the array minus 1'''.
:* The first index of an array is always '''0''', and the '''last''' is always the '''size of the array minus 1'''.
:* Arrays start with the symbol '''@'''.
:* Arrays start with the symbol '''@'''.
Line 286: Line 225:
: '''Hash'''
: '''Hash'''
:* Hash variables hold many '''pairs''' of things.
:* Hash variables hold many '''pairs''' of things.
:* Each hash pair in consisted of a '''key''' and a '''value'''.
:* Each hash pair consists of a '''key''' and a '''value'''.
:* Each key has only one value, but many keys can have the same value.
:* Each key has only one value, but many keys can have the same value.
:* Hashes start with the symbol '''%'''.
:* Hashes start with the symbol '''%'''.
Line 308: Line 247:
This would print in the console:
This would print in the console:


  [eventmacro log] Hello World!
  [eventmacro message] Hello World!


It is possible to increment and to decrement a variable using ''$variable++'' or ''$variable--''.
It is possible to increment and to decrement a variable using ''$variable++'' or ''$variable--''.
Line 322: Line 261:


The result is:
The result is:
  [eventmacro log] Counter is at 0
  [eventmacro message] Counter is at 0
  [eventmacro log] Now it's 1
  [eventmacro message] Now it's 1
  [eventmacro log] It's back to 0
  [eventmacro message] It's back to 0


You can also unset/vanish the existing variable using ''''undef'''' or ''''unset'''':
You can also unset/vanish the existing variable using ''''undef'''' or ''''unset'''':
  $x = 1
  macro Undef {
log \$x is $x
    $x = 1
$x = undef  # or you can use 'unset'
    log \$x is $x
log \$x now vanished: $x
    $x = undef  # or you can use 'unset'
   
    log \$x now vanished: $x
Variable assignment doesn't evaluate, it only does macro substitutions, so use @eval for calculations.
  }
 
The result is:
[eventmacro message] $x is 1
[eventmacro message] $x now vanished:
 
Variable assignment doesn't evaluate, it only does macro substitutions, so use &eval for calculations.


  macro math {
  macro math {
     $num = 2
     $num = 2
     $num2 = 3
     $num2 = 3
     $result = @eval($num+$num2)
     $result = &eval($num+$num2)
     log sum of $num and $num2 is $result
     log sum of $num and $num2 is $result
  }
  }


The result is:
The result is:
  [eventmacro log] sum of 2 and 3 is 5.
  [eventmacro message] sum of 2 and 3 is 5.
   
 
 
'''Scalars have the following keyword:'''
; &defined
defined syntax is as follows:
  &defined($<''variable''>})
: defined must have 1 parameter: <''variable''> whose existence should be checked. If <''variable''> exists, then the function will return <code>1</code>, else - <code>0</code>/.
: '''Note''': if the value of the <''variable''> =0, then it exists, i.e. the &defined function will return "1".
 
: example
macro defined {
  $var = 0;
  @array = (a, b)
  %hash = (a => 1, b => 2)
  log variable \$var exists: &defined($var)
  log element 1 in array \@array - exists: &defined($array[1])
  log key "с" in hash \%hash - not exists: &defined($hash{c})
}
 
: The result is:
[eventmacro message] variable $var exists: 1
[eventmacro message] element 1 in array @array - exists: 1
[eventmacro message] key "с" in hash %hash - not exists: 0
 
===== Arrays =====
===== Arrays =====


Set value of array variable, it must be declared with it's members inside parentheses, separated by comma:
Set value of array variable, it must be declared with its members inside parentheses, separated by comma:
  @variable = (member0, member1, member2)
  @variable = (member0, member1, member2)


Get a value of a certain index, use '''$''' at the start instead of '''@''', and put the index after the variable name, encapsulated by '''[''' and ''']''':
Get a value of a certain index, use '''$''' at the start instead of '''@''', and put the index after the variable name, enclosed by '''[''' and ''']''':
  $variable[index]
  $variable[index]


Line 362: Line 330:
This would print in the console:
This would print in the console:


  [eventmacro log] The size of @var is 2, the first member is drops and the second is poring
  [eventmacro message] The size of @var is 2, the first member is drops and the second is poring


* The definition of separate array members is the same as normal scalar.
* The definition of separate array members is the same as normal scalar.
Line 388: Line 356:
; Array Keywords
; Array Keywords
: There are 4 keywords which can be used on arrays:
: There are 4 keywords which can be used on arrays:
:* push: Adds a new element to the end fo the array, increasing it's size by 1.
:* push: Adds a new element to the end of the array, increasing its size by 1.
:* pop: Removes the last element from the end of the array, decreasing it's size by 1.
:* pop: Removes the last element from the end of the array, decreasing its size by 1.
:* shift: Removes the first element of the array and moves the whole array 1 index to the left, decreasing it's size by 1.
:* shift: Removes the first element of the array and moves the whole array 1 index to the left, decreasing its size by 1.
:* unshift: Adds a new element to the start of the array and moves the whole array 1 index to the right, increasing it's size by 1.
:* unshift: Adds a new element to the start of the array and moves the whole array 1 index to the right, increasing its size by 1.




Line 405: Line 373:
  &push(@names, juan)
  &push(@names, juan)


This is the array afterwars:
This is the array afterwards:
  (john, mary, juan)
  (john, mary, juan)


Line 413: Line 381:
     &push(@monsters, wolf)
     &push(@monsters, wolf)
     &push(@monsters, maya)
     &push(@monsters, maya)
     log The array \@monsters has size @monsters and it's members are $monsters[0], $monsters[1] and $monsters[2]
     log The array \@monsters has size @monsters and its members are $monsters[0], $monsters[1] and $monsters[2]
  }
  }


Prints this:
Prints this:
  [eventmacro log] The array @monsters has size 3 and it's members are poring, wolf and maya
  [eventmacro message] The array @monsters has size 3 and its members are poring, wolf and maya




Line 428: Line 396:
Here's an example of an array, and it after a pop:
Here's an example of an array, and it after a pop:
  @jobs = (teacher, doctor, seller)
  @jobs = (teacher, doctor, seller)
  log The array \@jobs has size @jobs and it's members are $jobs[0], $jobs[1] and $jobs[2]
  log The array \@jobs has size @jobs and its members are $jobs[0], $jobs[1] and $jobs[2]
  &pop(@jobs)
  &pop(@jobs)
  log The array \@jobs has size @jobs and it's members are $jobs[0], $jobs[1]
  log The array \@jobs has size @jobs and its members are $jobs[0], $jobs[1]
  &pop(@jobs)
  &pop(@jobs)
  log The array \@jobs has size @jobs and it's members are $jobs[0]
  log The array \@jobs has size @jobs and its members are $jobs[0]




This prints this:
This prints this:
  [eventmacro log] The array @jobs has size 3 and it's members are teacher, doctor and seller
  [eventmacro message] The array @jobs has size 3 and its members are teacher, doctor and seller
  [eventmacro log] The array @jobs has size 2 and it's members are teacher, doctor
  [eventmacro message] The array @jobs has size 2 and its members are teacher, doctor
  [eventmacro log] The array @jobs has size 1 and it's members are teacher
  [eventmacro message] The array @jobs has size 1 and its members are teacher




Line 448: Line 416:
Here's an example of an array, and it after a shift:
Here's an example of an array, and it after a shift:
  @jobs = (teacher, doctor, seller)
  @jobs = (teacher, doctor, seller)
  log The array \@jobs has size @jobs and it's members are $jobs[0], $jobs[1] and $jobs[2]
  log The array \@jobs has size @jobs and its members are $jobs[0], $jobs[1] and $jobs[2]
  &shift(@jobs)
  &shift(@jobs)
  log The array \@jobs has size @jobs and it's members are $jobs[0], $jobs[1]
  log The array \@jobs has size @jobs and its members are $jobs[0], $jobs[1]
  &shift(@jobs)
  &shift(@jobs)
  log The array \@jobs has size @jobs and it's members are $jobs[0]
  log The array \@jobs has size @jobs and its members are $jobs[0]




This prints this:
This prints this:
  [eventmacro log] The array @jobs has size 3 and it's members are teacher, doctor and seller
  [eventmacro message] The array @jobs has size 3 and its members are teacher, doctor and seller
  [eventmacro log] The array @jobs has size 2 and it's members are doctor, seller
  [eventmacro message] The array @jobs has size 2 and its members are doctor, seller
  [eventmacro log] The array @jobs has size 1 and it's members are seller
  [eventmacro message] The array @jobs has size 1 and its members are seller




After a shift the whole array is moved to the left, so after the first shift the member 'seller' which was in index 2 moved to index 1,
After a shift the whole array is moved to the left, so after the first shift the member 'seller' which was in index 2 moved to index 1, and after the second shift it moved to index 0.
and after the second shift it moved to index 0.




Line 469: Line 436:
  &unshift(@array, newmember)
  &unshift(@array, newmember)


push must have 2 parameters: the array you want to push, and the new member to be pushed.
unshift must have 2 parameters: the array you want to unshift, and the new member to be placed at the beginning of the array.


Here's an example of an array started from scratch using push:
Here's an example of an array started from scratch using unshift:
  &unshift(@foods, bread)
  &unshift(@foods, bread)
  &unshift(@foods, carrot)
  &unshift(@foods, carrot)
  &unshift(@foods, apple)
  &unshift(@foods, apple)


This is the array afterwars:
This is the array afterwards:
  (apple, carrot, bread)
  (apple, carrot, bread)


Line 484: Line 451:
  macro print_names {
  macro print_names {
     @array = (apple, banana)
     @array = (apple, banana)
     log The array \@array has size @array and it's first member is $array[0], and the second is $array[1]
     log The array \@array has size @array and its first member is $array[0], and the second is $array[1]
     &unshift(@array, pineapple)
     &unshift(@array, pineapple)
     log The array \@array has size @array and it's first member is $array[0], and the second is $array[1]
     log The array \@array has size @array and its first member is $array[0], and the second is $array[1]
     &unshift(@array, melon)
     &unshift(@array, melon)
     log The array \@array has size @array and it's first member is $array[0], and the second is $array[1]
     log The array \@array has size @array and its first member is $array[0], and the second is $array[1]
  }
  }


Prints this:
Prints this:
  [eventmacro log] The array @array has size 2 and it's first member is apple, and the second is banana
  [eventmacro message] The array @array has size 2 and its first member is apple, and the second is banana
  [eventmacro log] The array @array has size 3 and it's first member is pineapple, and the second is apple
  [eventmacro message] The array @array has size 3 and its first member is pineapple, and the second is apple
  [eventmacro log] The array @array has size 4 and it's first member is melon, and the second is pineapple
  [eventmacro message] The array @array has size 4 and its first member is melon, and the second is pineapple


===== Hashes =====
===== Hashes =====


Set value of hash variable, it must be declared with it's pairs inside parentheses, separated by comma, the key and the value must be separated by '''=>''':
To set the value of hash variable, it must be declared with its pairs inside parentheses, separated by comma, and the key and the value must be separated by '''=>''':
  %variable = (key1 => value1, key2 => value2, key3 => value3)
  %variable = (key1 => value1, key2 => value2, key3 => value3)


Get a value of a certain key, use '''$''' at the start instead of '''%''', and put the key after the variable name, encapsulated by '''{''' and '''}''':
To get a value of a certain key, use '''$''' at the start instead of '''%''', and put the key after the variable name, enclosed by '''{''' and '''}''':
  $variable{key1}
  $variable{key1}


* Keys can contain letters and numbers.
* Keys can contain letters and numbers.


Get a size of the variable:
Get the number of keys in the hash:
  %variable
  %variable


Line 515: Line 482:


This would print in the console:
This would print in the console:
  [eventmacro log] log John is 25 years old, and George is 32 years old
  [eventmacro message] log John is 25 years old, and George is 32 years old


* The definition of separate hash members is the same as normal scalar.
* The definition of separate hash members is the same as a normal scalar.


They can be set:
They can be set:
Line 539: Line 506:
  log \$myhash{value} now vanished: $myhash{value}
  log \$myhash{value} now vanished: $myhash{value}


; Hash Keywords
: There are 2 keywords which can be used on hashes:
:* '''&delete''': which completely deletes a key from a hash, as if it had never existed
:* '''&exists''': checks if a given key has a value
; &delete
delete syntax is as follows:
&delete ($<''hash''>{<''key''>})
: delete must have 1 parameter: hash key to remove.


There's one hash '''keyword''', '''delete''', it completely delete a key from a hash, as if it had never existed.


'''delete''' usage:
; &exists
  &delete($names{john})
exists syntax is as follows:
  &exists ($<''hash''>{<''key''>})
: delete must have 1 parameter: hash key to check. If the <''key''> has a value, then the function will return <code>1</code>, else - <code>0</code>/.


example:
: example
  macro print_names {
  macro hash {
    %fruitsprice = (apple => 1000, banana => 700)
    %fruitsprice = (apple => 1000, banana => 700)
    log The hash \%fruitsprice has size %fruitsprice.
    log Hash\%fruitsprice has %fruitsprice keys
    log The apple price is $fruitsprice{apple} and the banana price is $fruitsprice{banana}
    log apple price: $fruitsprice{apple} and bananas price: $fruitsprice{banana}
    &delete($fruitsprice{apple})
    &delete($fruitsprice{apple})
    log The hash \%fruitsprice has size %fruitsprice.
    log Hash \%fruitsprice has %fruitsprice key
    log The price of banana is: $fruitsprice{banana}
      if ( &exists($fruitsprice{apple}) ) {
    log The price of apple has vanished: $fruitsprice{apple}
        log apple price: $fruitsprice{banana}
      } else {
        log There are no apples in the Hash
      }
      if ( &exists($fruitsprice{banana}) ) {
        log bananas price: $fruitsprice{banana}
      } else {
        log There are no bananas in the Hash
      }
  }
  }


Prints this:
: Prints this:
  [eventmacro log] The hash \%fruitsprice has size 2.
  [eventmacro message] Hash%fruitsprice has 2 keys
  [eventmacro log] The apple price is 1000 and the banana price is 700
  [eventmacro message] apple price: 1000 and bananas price: 700
  [eventmacro log] The hash \%fruitsprice has size 1.
  [eventmacro message] Hash %fruitsprice has 1 key
  [eventmacro log] The price of banana is 700
  [eventmacro message] There are no apples in the Hash
  [eventmacro log] The price of apple has vanished:
  [eventmacro message] bananas price: 700
 
 


== Special Variables ==  
== Special Variables ==  
Line 572: Line 555:
!Definition
!Definition
!Example
!Example
|-
|$.map
|The map you're on
|prontera
|-
|$.pos
|Your current position
|123 234
|-
|-
|$.time
|$.time
Line 588: Line 563:
|Current date and time
|Current date and time
|Tue Dec 20 21:22:34 2016
|Tue Dec 20 21:22:34 2016
|-
|$.second
|Current second time (0 - 59)
|53
|-
|$.minute
|Current minute time (0 - 59)
|34
|-
|-
|$.hour
|$.hour
Line 593: Line 576:
|14
|14
|-
|-
|$.minute
|$.dayofmonth
|Current minute time (0 - 59)
|Current day of month
|34
|19
|-
|$.dayofweek
|Current day of week (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
|Wednesday
|-
|$.map
|The Map you're currently in
|prontera
|-
|$.incity
|[[References#boolean_flag|Boolean]], 1 whenever at a city, 0 otherwise
|1
|-
|$.inlockmap
|[[References#boolean_flag|Boolean]], 1 whenever at a lockMap, 0 otherwise
|1
|-
|$.job
|The current character job
|Swordman
|-
|$.pos
|Your current position
|123 234
|-
|-
|$.second
|$.name
|Current second time (0 - 59)
|The character name
|53
|Henrybk
|-
|-
|$.hp
|$.hp
Line 624: Line 631:
|Current zeny
|Current zeny
|8478341
|8478341
|-
|$.weight
|Current character weight
|1948
|-
|$.weightpercent
|Current character weight in percentage
|81.5
|-
|$.maxweight
|Current maximum character weight
|2400
|-
|-
|$.status
|$.status
Line 629: Line 648:
|Attention Concentrate,Endure,Two-Hand Quicken
|Attention Concentrate,Endure,Two-Hand Quicken
|-
|-
|$.paramN
|$.statushandle
|Current statuses handles in a comma-separated list
|SM_ENDURE,KN_TWOHANDQUICKEN
|-
|$.inventoryitems
|The current amount of items in inventory
|13
|-
|$.cartweight
|The current cart weight
|800
|-
|$.cartweightpercent
|The current cart weight in percentage
|10
|-
|$.cartmaxweight
|The current cart max weight
|8000
|-
|$.cartitems
|The current amount of items in cart
|21
|-
|$.cartmaxitems
|The current max amount of items in cart
|100
|-
|$.shopopen
|1 if shop is opened, 0 otherwise
|0
|-
|$.storageopen
|1 if storage is opened, 0 otherwise
|1
|-
|$.storageitems
|The current amount of items in storage
|432
|-
|$.storagemaxitems
|The current max amount of items in storage
|600
|-
|$.param[N]
|Command line parameters (see [[EventMacro#Syntax|Syntax]])
|Command line parameters (see [[EventMacro#Syntax|Syntax]])
|''N/A''
|''N/A''
|-
|-
|$.caller
|$.caller
|Nome da última automacro ativada
|Name of last automacro enabled
|''N/A''
|''N/A''
|-
|-
|$.weight
|Current weight of the character
|1948
|-
|$.maxweight
|Current maximum weight of the character
|2400
|}
|}


Line 650: Line 706:
These keywords (having common form of '''&<keyword>(<arguments>)''' each) interpolated to corresponding values just about anywhere inside ''macro blocks'' (except '''goto''', '''end''', label definitions, macro name in '''call''', '''set'''). Macro variables can be used in arguments, with the exception for <code>&nick()</code>.
These keywords (having common form of '''&<keyword>(<arguments>)''' each) interpolated to corresponding values just about anywhere inside ''macro blocks'' (except '''goto''', '''end''', label definitions, macro name in '''call''', '''set'''). Macro variables can be used in arguments, with the exception for <code>&nick()</code>.


; &npc (<''x''> <''y''> | /[http://www.regular-expressions.info/quickstart.html regexp]/i | "<''name''>")
; &questStatus (<''questID''>)
: Return NPC's index which location is <''x''> <''y''> or NPC's name match regexp or NPC's name is equal to <''name''> . Returns -1 if no NPC was found.  
: Returns the status of quest <''questID''> as a string (inactive, incomplete or complete).
 
; &questInactiveCount (<''questID1''>,<''questID2''>,<''questID3''>,etc)
: Returns the number of given quests which have status "inactive".
 
; &questIncompleteCount (<''questID1''>,<''questID2''>,<''questID3''>,etc)
: Returns the number of given quests which have status "incomplete".
 
; &questCompleteCount (<''questID1''>,<''questID2''>,<''questID3''>,etc)
: Returns the number of given quests which have status "complete".
 


; &inventory (<''item''>)
; &inventory (<''item|ID''>)
: Returns inventory item index of <''item''>. If <''item''> doesn't exist, it returns -1.
: Returns inventory item index of <''item|ID''>. You can specify the name of the item or its ID. If <''item''> doesn't exist, it returns -1.


; &Inventory (<''item''>)
; &Inventory (<''item|ID''>)
: Same as '''&inventory''' but returns all matching indexes as a comma-separated list or -1 if the item was not found.  
: Same as '''&inventory''' but returns all matching indexes as a comma-separated list or -1 if the item was not found.  


; &invamount (<''item''>)
; &invamount (<''item|ID''>)
: Returns the amount of the given <''item''> in inventory.
: Returns the amount of the given <''item|ID''> in inventory.


; &cart (<''item''>)
; &InventoryType (usable|equip|card|etc)
: Returns cart item index of <''item''>. If <''item''> doesn't exist, it returns -1.
: Returns a comma-separated list with all items of the specified type. If no items of that type are found, returns <code>-1</code>


; &Cart (<''item''>)
 
; &cart (<''item|ID''>)
: Returns cart item index of <''item|ID''>. If <''item|ID''> doesn't exist, it returns -1.
 
; &Cart (<''item|ID''>)
: Same as '''&cart''' but returns all matching indexes as a comma-separated list or -1 if the item was not found.
: Same as '''&cart''' but returns all matching indexes as a comma-separated list or -1 if the item was not found.


; &cartamount (<''item''>)
; &cartamount (<''item|ID''>)
: Returns the amount of the given <''item''> in cart.
: Returns the amount of the given <''item|ID''> in cart.
 


; &storage (<''item''>)
; &storage (<''item|ID''>)
: Returns storage item index of <''item''>. If <''item''> doesn't exist, it returns -1.
: Returns storage item index of <''item|ID''>. If <''item|ID''> doesn't exist, it returns -1.


; &Storage (<''item''>)
; &Storage (<''item|ID''>)
: Same as '''&storage''' but returns all matching indexes as a comma-separated list or -1 if the item was not found.
: Same as '''&storage''' but returns all matching indexes as a comma-separated list or -1 if the item was not found.


; &storamount (<''item''>)
; &storamount (<''item|ID''>)
: Returns the amount of the given <''item''> in storage.  
: Returns the amount of the given <''item|ID''> in storage.
 
 
; &venderitem (<''item|ID''>)
: Looks for an item in a player's shop and returns index or -1 if the item was not found.
 
; &venderprice (<''item|indexID''>)
: Looks for an item in a player's shop and returns its price.
 
; &venderamount (<''item|ID''>)
: Returns the amount of the given <''item''> in a player's shop.
 
 
; &store (<''item|ID''>)
: Looks for an item in a store and returns index or -1 if the item was not found.
 
; &shopamount (<''item|ID''>)
: Returns the amount of the given <''item''> in shop.
 
 
; &npc (<''x''> <''y''> | /[http://www.regular-expressions.info/quickstart.html regexp]/i | "<''name''>")
: Return NPC's index which location is <''x''> <''y''> or NPC's name match regexp or NPC's name is equal to <''name''> . Returns -1 if no NPC was found.  


; &player (<''name''>)
; &player (<''name''>)
Line 689: Line 781:
: Returns vender index of vender <''name''>. If vender <''name''> is not found, it returns -1.
: Returns vender index of vender <''name''>. If vender <''name''> is not found, it returns -1.


; &store (<''name''>)
: Looks for an item in a store and returns index or -1 if the item was not found.


; &shopamount (<''item''>)
; &config (<''variable''>)
: Returns the amount of the given <''item''> in shop.
: Returns the value of <''variable''> specified in config.txt.
 


; &random ("<''argument1''>", "<''argument2''>", ...)
; &random ("<''argument1''>", "<''argument2''>", ...)
Line 707: Line 798:
: Returns the <''n''>th word of <''argument''> or an empty string if the word index is out of range.
: Returns the <''n''>th word of <''argument''> or an empty string if the word index is out of range.


; &config (<''variable''>)
; &nick (<''word''>)
: Returns the value of <''variable''> specified in config.txt.
: Escapes all the regexp metacharacters and some of the perl special characters with '''\''' (a backslash). Especially for player's name.
 
 
; &split (<''separator''>, <''variable''>)
: Uses separator to create an array from another variable (ex: $list = a,b,c,d; @array = split(',', $list) )
 
; &keys (<''%hash''>)
: Creates an array from the keys of a hash (ex: %hash=(a=>"foo", b=>"bar"); @array = &keys (%hash) )


; &venderitem (<''name''>)
; &values (<''%hash''>)
: Looks for an item in a player's shop and returns index or -1 if the item was not found.
: Creates an array from the values of a hash


; &venderprice (<''indexID''>)
; &listlength (<''comma_separated_list''>)
: Looks for an item in a player's shop and returns its price.
: Returns the length of a <''comma_separated_list''> (ex: &listlength(a, b, c) )


; &nick (<''word''>)
; &strip (<''text''>)
: Escapes all the regexp metacharacters and some of the perl special characters with '''\''' (a backslash). Especially for player's name.
: Removes parentheses <code>( )</code> from <''text''> (ex: $text = (Hello))))) world); log strip: "&strip($text)" )


== Chaining commands ==
== Chaining commands ==
Line 789: Line 887:


You can use a simple statement;
You can use a simple statement;
  if (arg1 <[[eventMacro#Operators|Operators]]> arg2) (goto <label> | call <macro> [<n>] | stop | { )
  if (arg1 <[[eventMacro#Operators|Operators]]> arg2) (goto <label> | call <macro> [<parameters>] | stop | { )


A simple statement with '''OR''' condition;
A simple statement with '''OR''' condition;
  if (arg1 <[[eventMacro#Operators|Operators]]> arg2 || arg3 <[[eventMacro#Operators|Operators]]> arg4) (goto <label> | call <macro> <n> | stop | { )
  if (arg1 <[[eventMacro#Operators|Operators]]> arg2 || arg3 <[[eventMacro#Operators|Operators]]> arg4) (goto <label> | call <macro> <parameters> | stop | { )


A simple statement with '''AND''' condition;
A simple statement with '''AND''' condition;
  if (arg1 <[[eventMacro#Operators|Operators]]> arg2 && arg3 <[[eventMacro#Operators|Operators]]> arg4) (goto <label> | call <macro> <n> | stop | { )
  if (arg1 <[[eventMacro#Operators|Operators]]> arg2 && arg3 <[[eventMacro#Operators|Operators]]> arg4) (goto <label> | call <macro> <parameters> | stop | { )


Or with both;
Or with both;
  if ((arg1 <[[eventMacro#Operators|Operators]]> arg2 || arg3 <[[eventMacro#Operators|Operators]]> arg4) && arg5 <[[eventMacro#Operators|Operators]]> arg6) (goto <label> | call <macro> <n> | stop | { )
  if ((arg1 <[[eventMacro#Operators|Operators]]> arg2 || arg3 <[[eventMacro#Operators|Operators]]> arg4) && arg5 <[[eventMacro#Operators|Operators]]> arg6) (goto <label> | call <macro> <parameters> | stop | { )
  if ((arg1 <[[eventMacro#Operators|Operators]]> arg2 && arg3 <[[eventMacro#Operators|Operators]]> arg4) || arg5 <[[eventMacro#Operators|Operators]]> arg6) (goto <label> | call <macro> <n> | stop | { )
  if ((arg1 <[[eventMacro#Operators|Operators]]> arg2 && arg3 <[[eventMacro#Operators|Operators]]> arg4) || arg5 <[[eventMacro#Operators|Operators]]> arg6) (goto <label> | call <macro> <parameters> | stop | { )
  if ((arg1 <[[eventMacro#Operators|Operators]]> arg2 && arg3 <[[eventMacro#Operators|Operators]]> arg4) || (arg5 <[[eventMacro#Operators|Operators]]> arg6 && arg7 <[[eventMacro#Operators|Operators]]> arg8)) (goto <label> | call <macro> <n> | stop | { )
  if ((arg1 <[[eventMacro#Operators|Operators]]> arg2 && arg3 <[[eventMacro#Operators|Operators]]> arg4) || (arg5 <[[eventMacro#Operators|Operators]]> arg6 && arg7 <[[eventMacro#Operators|Operators]]> arg8)) (goto <label> | call <macro> <parameters> | stop | { )
  if ((arg1 <[[eventMacro#Operators|Operators]]> arg2 || arg3 <[[eventMacro#Operators|Operators]]> arg4) && (arg5 <condition> arg6 || arg7 <condition> arg8)) (goto <label> | call <macro> <n> | stop | { )
  if ((arg1 <[[eventMacro#Operators|Operators]]> arg2 || arg3 <[[eventMacro#Operators|Operators]]> arg4) && (arg5 <condition> arg6 || arg7 <condition> arg8)) (goto <label> | call <macro> <parameters> | stop | { )
:* Notice inside of each brackets containing the '''AND''' and '''OR''' symbols.
:* Notice inside of each brackets containing the '''AND''' and '''OR''' symbols.


Line 808: Line 906:
:* <''label''>, the name of an existing label, can only contain letters and numbers
:* <''label''>, the name of an existing label, can only contain letters and numbers
:* <''macro''>, the name of a existing macro, and
:* <''macro''>, the name of a existing macro, and
:* <''n''>, the number of times it will call the macro.
:* <''parameters''>, the macro call parameters (will be set to $.param[0], $param[1], etc),
:* < ''{'' >, the beginning of a block of commands that will be executed if the condition is true, to finish it, use ''}''.
:* < ''{'' >, the beginning of a block of commands that will be executed if the condition is true, to finish it, use ''}''.
'''''Note:'''''
:* If ''<n>'' is defined as '''0''' or even if it is '''undefined''', the called macro name will run at once and then stop, not continuing the previous macro caller at a run time.
:* If ''<n>'' is greater than '''0''', the called macro name will run at '''n''' time/s and then continuing the previous macro caller line at a run time.




'''''Note²:''''' If statements are unlimited, you can use as many statements as you want.
'''''Note²:''''' If statements are unlimited, you can use as many statements as you want.
  if (arg1 <[[eventMacro#Operators|Operators]]> arg2 || arg3 <[[eventMacro#Operators|Operators]]> arg4 || ... || arg'''''N''''' <[[eventMacro#Operators|Operators]]> arg'''''N+1''''') (goto <label> | call <macro> <n> | stop)
  if (arg1 <[[eventMacro#Operators|Operators]]> arg2 || arg3 <[[eventMacro#Operators|Operators]]> arg4 || ... || arg'''''N''''' <[[eventMacro#Operators|Operators]]> arg'''''N+1''''') (goto <label> | call <macro> <parameters> | stop)


Where;
Where;
Line 887: Line 980:


  switch (arg1) {
  switch (arg1) {
     case (<[[eventMacro#Operators|Operators]]> arg2) (goto <label> | call <macro> <n> | stop | {)
     case (<[[eventMacro#Operators|Operators]]> arg2) (goto <label> | call <macro> <parameters> | stop | {)
         (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
         (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
     case (<[[eventMacro#Operators|Operators]]> arg2) (goto <label> | call <macro> <n> | stop | {)
     case (<[[eventMacro#Operators|Operators]]> arg2) (goto <label> | call <macro> <parameters> | stop | {)
         (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
         (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
     ...
     ...
     else (goto <label> | call <macro> <n> | stop | {)
     else (goto <label> | call <macro> <parameters> | stop | {)
         (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
         (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
  }
  }


'''''Note:''''' The use of ''else'' is optional.
'''''Note:''''' The use of ''else'' is optional.<br>
'''''Note:''''' In case that no ''case'' ends being true, ''else'' will be activate if it exists.
'''''Note:''''' In case that no ''case'' ends being true, ''else'' will be activate if it exists.


Line 998: Line 1,091:
  }
  }
  macro one {
  macro one {
     log $num is 1
     log \$num is 1
  }
  }
  macro two {
  macro two {
     log $num is 2
     log \$num is 2
  }
  }
  macro three {
  macro three {
     log $num is 3
     log \$num is 3
  }
  }


Line 1,023: Line 1,116:


=== WHILE Loop ===
=== WHILE Loop ===
A ''while'' in macros means that certain commands will be ran while the defined conditions are met.
A ''while'' in macros means that certain commands will be ran while the defined conditions are met:
==== Syntax ====
 
  while (arg <condition> arg) as <loop>
  while (arg1 <[[eventMacro#Operators|Operators]]> arg2) {
     do bla bla
     do bla bla
     ...
     ...
  end <loop>
  }


Where;
Where;
:* ''arg'' can be a variable, a nested variable, a special keyword, &eval or letters and numbers. And
:* ''arg'' can be a variable, a nested variable, a special keyword, &eval, letters and numbers or even a [[eventMacro#Perl_Subroutines|Perl Subroutines]] function.
:* <loop> is the name of the loop. You can give any name you want.
Conditions can be found on [[eventMacro#Operators|Operators]].


==== Examples ====
'''Example:'''
  macro while {
  macro while {
     $i = 0
     $i = 0
     while ($i < 10) as loop
     while ($i < 10) {
     log \$i = $i
     log \$i = $i
     $i++
     $i++
     end loop
     }
  }
  }


The result is
The result is
  [eventmacro log] \$i = 0
  [eventmacro message] $i = 0
  [eventmacro log] \$i = 1
  [eventmacro message] $i = 1
  [eventmacro log] \$i = 2
  [eventmacro message] $i = 2
  [eventmacro log] \$i = 3
  [eventmacro message] $i = 3
  [eventmacro log] \$i = 4
  [eventmacro message] $i = 4
  [eventmacro log] \$i = 5
  [eventmacro message] $i = 5
  [eventmacro log] \$i = 6
  [eventmacro message] $i = 6
  [eventmacro log] \$i = 7
  [eventmacro message] $i = 7
  [eventmacro log] \$i = 8
  [eventmacro message] $i = 8
  [eventmacro log] \$i = 9
  [eventmacro message] $i = 9


== Automacros ==
{{Template:Eam_Automacros}}
{{Template:Eam_Parameters}}
{{Template:Call}}
{{Template:Delay}}
{{Template:Run-once}}
{{Template:CheckOnAI}}
{{Template:Disabled}}
{{Template:OverrideAI}}
{{Template:Exclusive}}
{{Template:Priority}}
{{Template:Macro_delay}}
{{Template:Orphan}}
{{Template:Repeat}}
{{Template:Timeout}}


At this point, you can define macros and call them, typing 'eventMacro <macro name>' in OpenKore's console input.
{{Template:Eam_Conditions}}
{{Template:Eam_Conditions_State}}


Automacro is an automatic trigger for calling your macros, just like blocks in config.txt are automatic triggers for certain AI actions.
{{Template:BaseLevel}}
{{Template:JobLevel}}
{{Template:CartCurrentWeight}}
{{Template:CartMaxWeight}}
{{Template:CartCurrentSize}}
{{Template:CartMaxSize}}
{{Template:CharCurrentWeight}}
{{Template:CharMaxWeight}}
{{Template:FreeStatPoints}}
{{Template:FreeSkillPoints}}
{{Template:CurrentHP}}
{{Template:MaxHP}}
{{Template:CurrentSP}}
{{Template:MaxSP}}
{{Template:InInventory}}
{{Template:InInventoryID}}
{{Template:InStorage}}
{{Template:InStorageID}}
{{Template:InCart}}
{{Template:InCartID}}
{{Template:InventoryCurrentSize}}
{{Template:SkillLevel}}
{{Template:Zeny}}
{{Template:StorageOpened}}
{{Template:ShopOpened}}
{{Template:InChatRoom}}
{{Template:ChatRoomNear}}
{{Template:InMap}}
{{Template:InLockMap}}
{{Template:InSaveMap}}
{{Template:IsInCoordinate}}
{{Template:IsInMapAndCoordinate}}
{{Template:InPvP}}
{{Template:InCity}}
{{Template:InMapRegex}}
{{Template:NpcNear}}
{{Template:NpcNearDist}}
{{Template:NpcNotNear}}
{{Template:PlayerNear}}
{{Template:PlayerNearDist}}
{{Template:PlayerNotNear}}
{{Template:MobNear}}
{{Template:MobNearDist}}
{{Template:MobNotNear}}
{{Template:JobID}}
{{Template:JobIDNot}}
{{Template:IsEquippedID}}
{{Template:IsNotEquippedID}}
{{Template:ConfigKey}}
{{Template:ConfigKeyNot}}
{{Template:ConfigKeyNotExist}}
{{Template:InProgressBar}}
{{Template:StatusActiveHandle}}
{{Template:StatusInactiveHandle}}
{{Template:QuestActive}}
{{Template:QuestInactive}}
{{Template:QuestOnTime}}
{{Template:QuestTimeOverdue}}
{{Template:QuestHuntCompleted}}
{{Template:QuestHuntOngoing}}
{{Template:NoPlayerNear}}
{{Template:NoPortalNear}}
{{Template:NoMobNear}}
{{Template:NoNpcNear}}
{{Template:PlayerNearCount}}
{{Template:NpcNearCount}}
{{Template:MobNearCount}}
{{Template:PortalNearCount}}


Automacro block consists of:
{{Template:Eam_Conditions_Event}}
* One or more '''Parameters''' ('''call''' being the only required one).
{{Template:PubMsg}}
* One or more '''Conditions'''.
{{Template:PubMsgDist}}
{{Template:PubMsgName}}
{{Template:PubMsgNameDist}}
{{Template:PrivMsg}}
{{Template:PrivMsgDist}}
{{Template:PrivMsgName}}
{{Template:PrivMsgNameDist}}
{{Template:PartyMsg}}
{{Template:PartyMsgDist}}
{{Template:PartyMsgName}}
{{Template:PartyMsgNameDist}}
{{Template:GuildMsg}}
{{Template:GuildMsgDist}}
{{Template:GuildMsgName}}
{{Template:GuildMsgNameDist}}
{{Template:NpcMsg}}
{{Template:NpcMsgDist}}
{{Template:NpcMsgName}}
{{Template:NpcMsgNameDist}}
{{Template:LocalMsg}}
{{Template:BusMsg}}
{{Template:MapLoaded}}
{{Template:OnCharLogIn}}
{{Template:ZenyChanged}}
{{Template:SimpleHookEvent}}


Automacro does not trigger if there is currently running macro in exclusive mode. Otherwise, automacro clears macro queue (which means that all currently running macros are stopped) before call.
=== Extras ===


The point of automacro is that you use them to check for certain conditions and call your macro when all conditions are fulfilled.
==== Math condition operators ====


=== Parameters ===
(<|<=|=|==|!=|!|>=|>|)\s*($number_qr%?|$general_wider_variable_qr)(?:\s*\.\.\s*($number_qr%?|$general_wider_variable_qr))


:* Each parameter can only be used once.
{|class="indextable" style="text-align:center;"
:* Parameters define the way the automacro or the called macro will work.
!Operator
:* Most parameters have a default value that will be used when it is not defined.
!Description
!Example
|-
|align=center| '''< <value>'''
|align=center| lower than <value>
|aling=center| '''< 50'''
|-
|align=center| '''> <value>'''
|align=center| higher than <value>
|aling=center| '''> 20'''
|-
|align=center| '''<= <value>'''
|align=center| lower or equal to <value>
|aling=center| '''<= 10'''
|-
|align=center| '''>= <value>'''
|align=center| higher or equal to <value>
|aling=center| '''>= 25'''
|-
|align=center| '''= <value> | == <value> | <value>'''
|align=center| equal to <value>
|aling=center| '''= 150 | == 150 | 150'''
|-
|align=center| '''!= <value> | ! <value>'''
|align=center| not equal to <value>
|aling=center| '''! 1000 | != 1000'''
|-
|align=center| '''<value1>..<value2>'''
|align=center| between <value1> and <value2>
|aling=center| '''20..80'''
|}


; call
:* Note: <value> can be a number or a variable.
:* '''call''' is the only required parameter in every automacro.
Examples:
:* '''call''' defines which macro the automacro will execute.
Math_condition >= 50 # Only true if higher or equal to 50
:* '''call''' can be a macro name or a macro block.
Math_condition < $variable # Only true if lower than $variable value


Example when using a macro name:
:* Note2: <value> can be a percentage (even if it is a variable).
  automacro <automacro name> {
Examples:
     <automacro conditions and parameters (and only them)>
  Math_condition <= 10% # Only true if lower or equal to 10%
     call myMacro
Math_condition != $variable # $variable value can be something like '50%', in which case it would only be true if different than 50%
 
 
==== Regex ====
 
: To learn about regex plese refer to this link: [http://www.regular-expressions.info/quickstart.html regexp tutorial]
: Note: Regex in conditions support all types of variables
 
== Perl Subroutines ==
eventMacro plugin support Perl subroutines in macros. You can now create any simple Perl function without limitations from the '''eval''' command.
 
Example No.1 - how to create a Perl Subroutine function in Macro
macro sub {
     $list = Orange, Milk, Soya, Peach
    if (existsInList("$list", "PeAch")) goto ok
    log Not Match!!!; stop
    :ok
    log Match!!!
    $x = &eval(existsInList("$list", "PeAch"))
     log \$x = $x  # $x here is 1
  }
  }
  macro myMacro {
  sub existsInList {
     <macro instructions (and only them, as this is regular macro)>
     my ($list, $val) = @_;
     # for example:
     return 0 if ($val eq "");
     do move prontera
    my @array = split / *, */, $list;
     do move payon
    $val = lc($val);
    foreach (@array) {
        s/^\s+//;
        s/\s+$//;
        s/\s+/ /g;
        next if $_ eq "";
        return 1 if lc eq $val;
     }
     return 0;
  }
  }


Example when using a macro block:
 
  automacro <automacro name> {
Example No.2 - how to create a re-writable file function using Perl Subroutine in Macro
     <automacro conditions and parameters (and only them)>
  automacro confHP1 {
    CurrentHP > 85%
    exclusive 1
    run-once 1
    call {
        $setting = Demon Pungus #becareful on your case, its case sensitive
        $attack = 1
        $teleport = 0
        $telesearch = 1
        call HP
    }
}
automacro confHP2 {
     CurrentHP < 75%
    exclusive 1
    run-once 1
     call {
     call {
         <macro instructions (and only them, as this is regular macro)>
         $setting = Demon Pungus #becareful on your case, its case sensitive
         # for example:
        $attack = 1
         do move prontera
         $teleport = 2
         do move payon
         $telesearch = 1
         call HP
     }
     }
  }
  }
macro HP {
    #Getting the value of the $setting monster name Ex: $setting $exist1 $exist2 $exist3
    $exist1 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{attack_auto}:"None")
    $exist2 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{teleport_auto}:"None")
    $exist3 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{teleport_search}:"None")
    log Old Values are $setting $exist1 $exist2 $exist3
    log Changing the values to $setting $attack $teleport $telesearch
    do eval Misc::mon_control("$::Macro::Data::varStack{setting}")->{attack_auto} = $attack; Misc::mon_control("$::Macro::Data::varStack{setting}")->{teleport_auto} = $teleport; Misc::mon_control("$::Macro::Data::varStack{setting}")->{teleport_search} = $telesearch
    log Writting mon_control.txt with new values
    rewrite()  # see the sub-routine function below
    log Reloading mon_control.txt
    do reload mon_control
    $exist1 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{attack_auto}:"None")
    $exist2 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{teleport_auto}:"None")
    $exist3 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{teleport_search}:"None")
    log New mon_control.txt Setting: $setting $exist1 $exist2 $exist3
    log Macro done
    #if $teleport = 0 ; means the Higher automacro HP is currently triggered
    #if $teleport = 2 ; means the Lower automacro HP is currently triggered
    if ($teleport < 2) goto releaseHighHp
    :releaseLowHp
        release confHP1
        stop
    :releaseHighHp
        release confHP2
        stop
}
sub rewrite {
    my $monster = Misc::mon_control("$::Macro::Data::varStack{setting}");
    my @lines = ();
    if (open(FILE, "<:utf8", Settings::getControlFilename("mon_control.txt"))) {
        while (<FILE>) {
            s/\x{FEFF}//g; chomp;
            if (/^#/ || /^\n/ || /^\r/) {
                push @lines,$_;
                next
            }
            /^(\d+|([a-zA-Z' ]+)*) -?\d/;
            if ("$::Macro::Data::varStack{setting}" eq $1 && defined $monster) {
                $_ = $1; s/\s+$//;
                push(@lines, ($_ . " $monster->{attack_auto} $monster->{teleport_auto} $monster->{teleport_search} $monster->{attack_lvl} $monster->{attack_jlvl} $monster->{attack_hp} $monster->{attack_sp} $monster->{weight}"));
            } else {
                push(@lines, $_);
            }
        }
        close FILE
    }
    open(FILE, ">:utf8", Settings::getControlFilename("mon_control.txt"));
    print FILE join "\n", @lines;
    close FILE;
}
== Comments ==
The macro files allow comments, i.e. lines that are ignored by the eventMacro plugin.
:* Lines starting with a # will be treated as a comment.
:* Everything after a space and followed by a # will also be ignored.
macro happy {
    #this is a comment line
    log I'm Happy # this is also a comment
}
Will print:
[eventmacro message] I'm Happy
== Examples with Explanations ==
I assume you already know how to use [[Console Commands]] and understand how they work. If not, before going further, read through all [[Console Commands]] and try out ones like ''a'', ''ai'', ''move'', ''cart get'', ''storage add'', ''talk'', ''deal'', ''take'', direction commands, ''sl'', ''sm'', ''relog'', ''pm'' and others.
Keep another page with this manual open for cross reference.
Okay, so there are 2 types of blocks
#'''automacros''' – these trigger automatically
#'''macros''' – these do not trigger automatically but need to be called manually or by an automacro




:* Two examples above do the same thing.
'''Automacros'''
:* Note that the macro block used in the call parameter has the same rules as a normal macro block.


Automacros automatically trigger when certain conditions are met, just like how blocks in config.txt trigger depending on the conditions set in them.


The first syntax is useful if you want more than one automacro to call one simple macro:
The point of automacros is that you use them to check for conditions. When the condition is fulfilled, you can either respond to it in the automacro or call a macro to do it. The format for automacro is...
  automacro First {
 
    <conditions>  
  automacro <name> {
    call print
        condition 1
}
        condition 2
automacro Second {
        …...
    <conditions>
        …...
    call print
        call {
}
                command 1
macro print {
                command 2
    log $.caller triggered
                …..
                …..
        }
        timeout <n seconds> #(if necessary)
  }
  }




; delay
For example, suppose you're playing manually but your slave priest is on Kore, and you want it to warn you if it's running out of sp, you can use an automacro like this....
:* '''delay''' is an optional parameter.
:* '''delay''' defines the time in seconds to wait before executing the macro in call parameter.
:* If not used in the automacro the default value will be used, which is: 0.
:* Must have a numeric value.


  automacro <automacro name> {
  automacro sp {
    <automacro conditions and parameters (and only them)>
    CurrentSP < 200
    delay 5
    timeout 10
    call myMacro
    call {
}
      do c sp low
macro myMacro {
    }
    <macro instructions (and only them, as this is regular macro)>
    log This is being logged 5 seconds after the automacro activated
  }
  }


; run-once
:* '''run-once''' is an optional parameter.
:* '''run-once''' defines if the automacro can activate only once, or multiple times.
:* If not used in the automacro the default value will be used, which is: 0.
:* When it's value is 1 the automacro will only activate once, when it's 0 it can activate multiple times.
:* To make an automacro with run-once value of 1 which already was already activated be able to run again you can use the command 'release' [[eventMacro#Macro Syntax|Macro Syntax]].


automacro myautomacro {
Taking it line by line,
    <automacro conditions and parameters (and only them)>
 
    run-once 1
#'''''automacro sp {''''' - you need to put automacro to tell kore that its an automacro. Then you put the name of the macro, in this case its “sp”. Then you need to put an opening bracket “{“ which tells Kore that the automacro's code begins there.
    call myMacro
#'''''CurrentSP < 200''''' – After the “{“, you put the conditions on successive lines. Here, there is only one condition and I think its clear that the condition is that sp should be below 200.
}
#'''''timeout 10''''' – This isn't a condition or a command, it works the same way it works in normal Kore blocks, so this automacro cannot trigger within 10 seconds of it already having been triggered. I ALWAYS put timeouts, so even if my conditions are faulty, the automacro doesn't spam and mess up whatever my bot is doing. Otherwise if your automacro is messed up then you could die or something, so its better to put an appropriate timeout.
automacro myaotherauto {
#'''''call {''''' – The word “call” tells Kore that now you're going to be putting commands, not conditions. The opening bracket “{“ tells Kore that the commands will start now. These commands are the ones that will get carried out when the conditions are met, here when sp goes below 200.
    <automacro conditions and parameters (and only them)>
#'''''do c sp low''''' – “do” tells Kore that this is a command, something to be done. After “do”, just leave a space and type in the console command you want to execute exactly the way you do in the Kore console.
    run-once 0
#'''''}''''' – This closing bracket “}” tells Kore that the commands have ended.
    call myMacro
#'''''}''''' – This closing bracket “}” tells Kore that your automacro code has ended.
}
macro myMacro {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will be called by myautomacro only once
    log but this macro can be called by myaotherauto many times
}


; CheckOnAI
So basically whenever, the bot's sp goes below 200, it says in public chat “sp low”. This also has the advantage of making your bot not look like a bot =p.
:* '''CheckOnAI''' is an optional parameter.
:* '''CheckOnAI''' defines in which AI states the automacro can activate.
:* The default value for this parameter can be set in the config key eventMacro_CheckOnAI [[eventMacro#Configuration files|Configuration files]].
:* If not used in the automacro the default value will be used, which is the config key eventMacro_CheckOnAI.
:* If eventMacro_CheckOnAI is not set in the config the default value will be used, which is: auto
:* It's values can be a combination of auto, manual and off, separated by comma.


automacro MyAuto {
    <automacro conditions and parameters (and only them)>
    CheckOnAI manual
    call myMacro
}
macro myMacro {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will only be called by MyAuto when AI is manual
}
automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    CheckOnAI manual, off
    call myMacro
}
macro myMacro2 {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will only be called by MyAuto2 when AI is manual or off
}


; disabled
Here's another macro which illustrates how you can use macros to handle weird situations which Kore is not equipped to deal with. When fighting against metalings, they often strip you and then your oh-so-smart bot punches! To get around this, put the weapon you use in default auto equip and use this macro.
:* '''disabled''' is an optional parameter.
:* '''disabled''' defines if the automacro is active of not.
:* If not used in the automacro the default value will be used, which is: 0.
:* When it's value is 1 the automacro won't activate ever, when it's 0 it can activate normally.


  automacro MyAuto {
  automacro strip {
    <automacro conditions and parameters (and only them)>
    StatusActiveHandle EFST_NOEQUIPWEAPON
    disabled 1
    timeout 10
    call myMacro
    call {
}
      do tele
macro myMacro {
      do relog 10
    <macro instructions (and only them, as this is regular macro)>
    }
    log This macro will never be called by MyAuto
}
automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    disabled 0
    call myMacro
}
macro myMacro2 {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will be called by MyAuto2 normally
  }
  }


; overrideAI
:* '''overrideAI''' is an optional parameter.
:* '''overrideAI''' defines if eventMacro will put itself in the AI queue.
:* If not used in the automacro the default value will be used, which is: 0.
:* When it's value is 0 the macro will be put into AI queue as 'eventMacro' and the next macro command will only be run if current AI is 'eventMacro'.
:* When it's value is 1 the macro will not be put into AI queue and the next macro command will always be run.
:* It's important to note that when it's value is 1 since it won't be put into AI queue normal AI functions will continue as normal, like mob hunting or autostorage.


automacro MyAuto {
Taking it line by line....
    <automacro conditions and parameters (and only them)>
 
    overrideAI 0
#'''''automacro strip {''''' - Tell Kore this is an automacro, and it's name is "strip". The '{' tells Kore the code of the automacro starts here.
    call myMacro
#'''''StatusActiveHandle EFST_NOEQUIPWEAPON''''' - The only condition in this macro. This checks your list of statuses for the status handle "EFST_NOEQUIPWEAPON". Thus, when you are stripped by a Metaling, you get the "EFST_NOEQUIPWEAPON" status and this condition will be fulfilled.
}
#'''''timeout 10''''' - Ensures automacro is not spammed, and 10 seconds is enough time to execute the automacro. So after 10 seconds, if for some reason you are still stripped, this automacro will trigger again. However, if you re-login and are stripped within 10 seconds, then macro will not trigger again untill the 10 seconds are up.
macro myMacro {
#'''''call {''''' - The word "call" and "{" tells Kore that the commands to be executed start after the '{'
    <macro instructions (and only them, as this is regular macro)>
#'''''do tele''''' - "do" tells Kore that what comes after is a console command to be carried out. Here, the command is "tele" so you teleport away from the Metaling, so that in case you lag or something, you aren't killed while executing the next instruction which is.....
    do move prontera
#'''''do relog 10''''' - Tells Kore to relogin in 10 seconds, because when you login again, your "strip weapon" status is cleared.
    log This will only be printed when the 'move prontera' has been completed, since 'move' takes the first place in AI queue.
#'''''}''''' - The closing bracket '}' tells Kore the commands have ended.
}
#'''''}''''' - The closing bracket '}' tells Kore the macro code has ended.
automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    overrideAI 1
    call myMacro
}
macro myMacro2 {
    <macro instructions (and only them, as this is regular macro)>
    do move prontera
    log This will be printed after a macro_delay has passed before the last command, because it won't check AI queue.
}


; exclusive
Summarising, on being stripped, you teleport away from the monster and then relogin, with a timeout of 10 seconds to ensure that the automacro is not spammed. Since the weapon you're using is filled in the default weapon option, after re-logging in, Kore will automatically re-equip that weapon.
:* '''exclusive''' is an optional parameter.
:* '''exclusive''' defines if the macro can be interrupted or not.
:* If not used in the automacro the default value will be used, which is: 0.
:* When it's value is 0 the macro can be interrupted by other automacros.
:* When it's value is 1 the macro can not be interrupted by other automacros.


automacro MyAuto {
    <automacro conditions and parameters (and only them)>
    exclusive 0
    call myMacro
}
macro myMacro {
    <macro instructions (and only them, as this is regular macro)>
    log This would probably cause a bug because the automacro would activate every AI cycle since the macro is interruptible.
}
automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    exclusive 1
    call myMacro
}
macro myMacro2 {
    <macro instructions (and only them, as this is regular macro)>
    log Since exclusive is 1 the macro is now uninterruptible and will work properly.
}


; priority
Let's try a more complicated macro. If you have a priest, you would want it to warp back to its lockmap or the nearest warp-able map near its lockmap. This macro does it. From the savemap, the bot takes the same route to the lockmap each time. So in the first map outside the town, just set it to move to a designated tile, and cast warp on a nearby tile, and then move to that tile. You will need delays to allow the spell to be cast and commands to be completed.
:* '''priority''' is an optional parameter.
:* '''priority''' defines the priority for activation the automacro has between all automacros, the lower the priority, the sooner ir will be checked.
:* If not used in the automacro the default value will be used, which is: 0.
:* Must have a numeric value.


  automacro MyAuto {
  automacro warp {
     <automacro conditions and parameters (and only them)>
     InMap gef_fild07
     priority 5
    InInventory "Blue Gemstone" > 0
     timeout 20
     call {
     call {
         log This automacro will be checked after MyAuto2 because it's priority is higher
         do ai manual
        pause 1
        do move 319 187
        do sl 27 316 188
        pause 2
        do warp 1
        pause 1
        do move 316 188
        do ai on
     }
     }
  }
  }
 
automacro MyAuto2 {
 
    <automacro conditions and parameters (and only them)>
Taking it line by line,
    priority 2
 
    call {
#'''''automacro warp {''''' - As explained, the automacro's name is warp, and “{“ indicates that the automacro begins.
        log This automacro will be checked before MyAuto because it's priority is lower
#'''''InMap get_fild07''''' - The first condition, the automacro will only trigger if the map is gef_fild07.
     }
#'''''InInventory “Blue Gemstone” > 0''''' - Second condition, ensures there is atleast one blue gemstone in the inventory so that warp portal can be cast. Obviously you need a getAuto in config.txt for the gemstones.
#'''''timeout 20''''' - Ensures that the bot does not spam the automacro. The timeout should be large enough to allow the completion of the automacro, so that the automacro does not trigger again while it is in execution.
#'''''call {''''' - Tells Kore that the commands start here.
#'''''do ai manual''''' - Frequently, I use this command in the more complicated and longer macros, so that Kore doesn't get diverted into doing something else while your macro is running, for example, attacking a monster or gathering up an item. In this case I'm using it so that the bot doesn't continue walking.
#'''''pause 1''''' - Inserts a delay of 1 second before the next command is carried out, VERY IMPORTANT. If you don't use delays then Kore can and will miss steps in the macro and the result is a mess.
#'''''do move 319 187''''' - The “move” console command is used to move your bot to a set location.
#'''''do sl 27 316 188''''' - The “sl” console command is used to make your priest cast warp portal on a convenient spot near your location, in this case (316,188).
#'''''pause 2''''' - Very Important. A delay of 2 seconds is put, allowing enough time to cast warp portal. If you priest has low dex, this delay should be increased.
#'''''do warp 1''''' - Console command “warp” is used to select memo location 1.
#'''''pause 1''''' - 1 second delay to allow the portal to form.
#'''''do move 316 188''''' - Move to the portal and Voila! You have been warped to the map.
#'''''do ai on''''' - You set ai to manual at the beginning of this macro, so now you need to turn it back on.
#'''''}''''' - Closing bracket indicates end of commands.
#'''''}''''' - Closing bracket indicates end of automacro code.
 
''Note the use of appropriate delays and timeouts in this automacro.''
 
 
The EventMacro plugin also has many useful built-in variables which give you your position for example. It's all listed in the eventMacro manual. I just want to show how to extract your position from these variables.
 
'''$.pos''' gives you your position. Now to get your ''x'' and ''y'' coordinates the code is,
 
  $px = &arg ("$.pos", 1)
  $py = &arg ("$.pos", 2)
 
Here, the ''x'' coordinate is the 1st value in '''$.pos''' so we have a ''''1''''. Similarly, the ''y'' coordinate is the second value in '''$.pos''' so we have a ''''2''''.
 
If you have a “'''MobNear'''” condition in your automacro, '''$.MobNearLastPos''' gives the position of that monster. To extract the ''x'' and ''y'' coordinates the code is,
 
  $mx = &arg ("$.MobNearLastPos", 1)
  $my = &arg ("$.MobNearLastPos", 2)
 
"'''run-once'''"
 
Frequently, the run-once condition is used instead of a timeout. It allows the automacro to run only once so that the automacro isn't spammed. To get the automacro to run again, a release command needs to be executed. However, due to a rogue situation that the macro hangs and the release macro isn't executed, your automacro is effectively stuck. To get around this, use a timeout instead of using run-once.
 
 
== How to write a macro ==
Now that you have some idea of what a macro is, try writing one
 
* Figure out under exactly what conditions you want your automacro to trigger
*Logically think out the steps your bot needs to perform in the automacro. Go step by step over this carefully.
*Ensure you have inserted appropriate pauses between the steps.
*Ensure you have a timeout or a run-once in your macro to prevent spamming of it.
*Now put the code in eventMacros.txt and start the bot or reload eventMacros.txt. If all is fine you won't get any error messages. But if there is a problem in the syntax, say you missed out a “}”, then you will get an error message and the macro won't work. Figure out what the error is, correct it, and reload eventMacros.txt again to check if you corrected it properly or not.
 
== Collected Macros ==
 
I would like to share some useful macros, hopefully not angering anyone here.
 
'''Identify with Magnifier'''
 
You got unidentified Items in your inventory and want to identify them using magnifiers? Use "eventMacro id" on console until all items are identified. You don't have to type anything else, the macro will identify the first item found, after that the second and so on.
 
macro id {
    $id = &inventory(Magnifier)
    do is $id
    pause 1
     do identify 0
  }
  }


; macro_delay
'''Automatically refine Rough Stones (Ori / Elu)'''
:* '''macro_delay''' is an optional parameter.
 
:* '''macro_delay''' defines the time in seconds to wait between macro commands.
This macro, once called, will automatically walk to the prontera forge and refine Rough Ori / Elu as long as there are more than 5 in your inventory. I did not find something like that yet, please post everything (better) I may have missed.
:* If not used in the automacro the default value will be used, which is: 1.
 
:* Must have a numeric value.
Just fire ''eventMacro ref'' to start. To stop manually, type ''eventMacro stop''.


  automacro MyAuto {
  macro ref {
     <automacro conditions and parameters (and only them)>
     do move prt_in 59 60
    macro_delay 2
     call ref-while
     call {
        log This will be printed at the macro execution
        log This will be printed 2 seconds after
    }
  }
  }
   
   
  automacro MyAuto2 {
  macro ref-while {
     <automacro conditions and parameters (and only them)>
     log start refining with
     macro_delay 5
    $ori = &invamount(Rough Oridecon)
     call {
    $elu =  &invamount(Rough Elunium)
         log This will be printed at the macro execution
    log I have $ori Rough Oridecons
         log This will be printed 5 seconds after
    log I have $elu Rough Eluniums
    while (&invamount(Rough Oridecon) > 4) {
        do talk 0
        pause 0.8
        do talk resp 0
        call ref-while
     }
     while (&inventory(Rough Elunium) > 4) {
         do talk 0
        pause 0.8
        do talk resp 1
         call ref-while
     }
     }
    stop
  }
  }
== FAQ ==
; I get disconnected from map server when running a macro!
: The commands are sent too fast. Increase macro_delay or add pause lines between your do commands
; I'm getting Malformed UTF-8 character (''fatal''), what is this?
: This error happens when your eventMacros.txt is not saved in UTF-8 encoding.
: To solve it, open your eventMacros.txt and if you're using Notepad, when you are going to save, change Encoding to '''UTF-8'''. '''(If that does not help - do not use Notepad.)'''
: If you're using Notepad++ or other text editor, go to '''Format > UTF-8 (without BOM)''' and save.
== Author ==
: EventMacro was written by '''Henrybk'''.
: EventMacro was based on macro plugin which was first written by '''arachno''' has various contributors like ezza, daigaku, keplerbr, eternalhavest and technologyguild.
: EventMacro was beta tested by '''emjustin'''.
: Some of the most important ideas and functions were developed by '''allanon'''.
[[Category:Plugins]]

Latest revision as of 22:35, 26 April 2021

Description

  • This plugin is a complete rework of the macro plugin, it has been written to be event-based and way less CPU intensive than it's predecessor.
  • With this plugin you can create complex blocks of conditions called automacros and blocks of consecutive actions called macros.
  • Macros can be called by one or more automacros when their conditions become true or be called by hand using a console command.
  • Automacros have simple to use conditions like base level, zeny, job class and many others.
  • Macros can be as simple as 'say something in chat' or 'save in kafra' and as complex as 'do a complete quest'.
  • This page was last updated with the current version at the moment being 324.

Installation

* eventMacro plugin is now included and enabled by default in openkore.

  • In your OpenKore control folder, create a blank file named eventMacros.txt. In this file you will put your macros/automacros.

Console Commands

Syntax

eventMacro [MACRO|auto|list|status|check|stop|pause|unpause|var_get|var_set|enable|disable|include] [extra]
eventMacro MACRO
  • Runs macro MACRO.
Option Value Description
-repeat | -r n repeat the macro n times
-overrideAI none override openkore's AI
-macro_delay delay override global macro_delay for this macro
-exclusive none do not allow automacros to cancel this macro
-orphan terminate
reregister
reregister_safe
terminate_last_call
use method for handling orphaned macros


Parameters for the macro can be specified after a double dash (--). These parameters are saved to the array @.param. Example:

macro foo {
 log Parameter 1 is $.param[0]
 log Parameter 2 is $.param[1]
}


When called as eventMacro foo -- foo bar it would print out

[eventmacro message] Parameter 1 is foo
[eventmacro message] Parameter 2 is bar
eventMacro auto AUTOMACRO
Get info on an automacro and it's conditions
eventMacro list
Lists available macros and automacros
eventMacro status [macro|automacro]
Shows current status of automacro, macro or both
eventMacro check (force_stop|force_start|resume)
Sets the state of automacros checking
eventMacro stop
Stops current running macro
eventMacro pause
Pauses current running macro
eventMacro unpause
Unpauses current running macro
eventMacro var_get [var]
Shows the value of one or all variables
eventMacro var_set var_name value
Set the value of a variable
eventMacro enable [automacro]
Enable one or all automacros
eventMacro disable [automacro]
Disable one or all automacros
eventMacro include (on|off|list) [filename or pattern]
Enables or disables !include in eventMacros file

Configuration files

control/eventMacros.txt
Put your macros and automacros in here. You can change the file's name depending on what you configured on config eventMacro_file.
control/timeouts.txt
Add eventMacro_delay and set it to the number of seconds you want the plugin to pause between commands. Default value: 1.
control/config.txt
Option Value Default Description
eventMacro_orphans terminate
reregister
reregister_safe
terminate_last_call
terminate How will openkore deal with macros that got cleanead out of AI queue
eventMacro_file file name eventMacros.txt file containing the macros and automacros
eventMacro_CheckOnAI combination of 'auto', 'manual' and 'off' auto In which AI states automacros will be checked

Macro Syntax

macro MacroName {
   do this..
   and that..
   yattayatta..
}
  • You can use any name you want for your macro. Be careful not to make two macros with the same name.
  • Macros is executed from top to bottom.
  • Only macro instructions can be used in macros. If you need to use console command, use do.

Macro Instructions

do <command>
Run <command>, as if it was entered in OpenKore terminal. Commands are from Console Commands.
macro foo {
   do move 123 234 prontera
   do sit
   do c hello world
}

The command ai clear is disabled by default in the plugin.
If has a macro the command do ai manual or do ai off , the macro will stop its execution.


log <text>
warning <text>
error <text>
Prints a text in the console. Can contain macro $variables and &stuff.
macro foo {
  log This line logs a text to console.
  warning All your base are belong to us!
}


pause [<n>]
Pauses the macro for n seconds.
macro foo {
   log It's 10:00:00
   pause 10
   log Now it's 10:00:10 
   log 10 seconds have passed after the first print.
}

pause not only pauses the macro running, pauses all our character's actions.


call <macroname> [<parameters>]
Calls macro <macroname> [set <parameters>]. When <macroname> is finished the current macro continues.
<macroname> can be a variable (ex: call $killmacro)


release (<name> | all)
Reenables a locked automacro ("run-once" keyword or locked by "lock") or reenables all automacros when using release all.


lock (<name> | all)
Locks an automacro and disables it's checks. To lock all automacros, use lock all.


stop
Immediately terminates the running macro.


include (<on> | <off> | <list>) [<filename> | <pattern>]
Enables or disables !include in eventMacros file

include [on|off|list] [filename or pattern]


set <option> <value>
Sets macro features:
  • orphan method
  • macro_delay timeout
  • overrideAI [0|1]
  • repeat times
  • exclusive [0|1]

Variables

  • You can work with variables. Variable declaration is not needed. All macro variables are global.
  • EventMacro variable system is based in perl and has support for scalars, arrays and hashes.
  • Variable names may only contain letters and numbers.
  • If you want to use any variable without replacing it for it's value you should escape it with \.

Types of variables and their definitions

Scalar
  • Scalar variables can hold a single piece of information, like a number or a string of characters.
  • Scalars start with the symbol $.
Array
  • Array variables hold a list of things.
  • Each member inside the array list has a index, which is its position inside the list.
  • The first index of an array is always 0, and the last is always the size of the array minus 1.
  • Arrays start with the symbol @.
Hash
  • Hash variables hold many pairs of things.
  • Each hash pair consists of a key and a value.
  • Each key has only one value, but many keys can have the same value.
  • Hashes start with the symbol %.

Declaration and usage

Scalars

Set value of scalar variable:

$variable = value

Get a value of variable (note that this is "Macro Syntax" section, so it doesn't apply to automacro conditions, config options etc):

$variable
macro Hello {
   $var = Hello
   $var1 = World!
   log $var $var1
}

This would print in the console:

[eventmacro message] Hello World!

It is possible to increment and to decrement a variable using $variable++ or $variable--.

macro Counter {
    $counter = 0
    log Counter is at $counter
    $counter++
    log Now it's $counter
    $counter--
    log It's back to $counter
}

The result is:

[eventmacro message] Counter is at 0
[eventmacro message] Now it's 1
[eventmacro message] It's back to 0

You can also unset/vanish the existing variable using 'undef' or 'unset':

macro Undef {
    $x = 1
    log \$x is $x
    $x = undef  # or you can use 'unset'
    log \$x now vanished: $x
}

The result is:

[eventmacro message] $x is 1
[eventmacro message] $x now vanished:

Variable assignment doesn't evaluate, it only does macro substitutions, so use &eval for calculations.

macro math {
    $num = 2
    $num2 = 3
    $result = &eval($num+$num2)
    log sum of $num and $num2 is $result
}

The result is:

[eventmacro message] sum of 2 and 3 is 5.


Scalars have the following keyword:

&defined

defined syntax is as follows:

&defined($<variable>})
defined must have 1 parameter: <variable> whose existence should be checked. If <variable> exists, then the function will return 1, else - 0/.
Note: if the value of the <variable> =0, then it exists, i.e. the &defined function will return "1".
example
macro defined {
  $var = 0;
  @array = (a, b)
  %hash = (a => 1, b => 2)
  log variable \$var exists: &defined($var)
  log element 1 in array \@array - exists: &defined($array[1])
  log key "с" in hash \%hash - not exists: &defined($hash{c})
}
The result is:
[eventmacro message] variable $var exists: 1
[eventmacro message] element 1 in array @array - exists: 1
[eventmacro message] key "с" in hash %hash - not exists: 0
Arrays

Set value of array variable, it must be declared with its members inside parentheses, separated by comma:

@variable = (member0, member1, member2)

Get a value of a certain index, use $ at the start instead of @, and put the index after the variable name, enclosed by [ and ]:

$variable[index]

Get a size of the variable:

@variable
macro Hello {
   @var = (drops, poring)
   log The size of \@var is @var, the first member is $var[0] and the second is $var[1]
}

This would print in the console:

[eventmacro message] The size of @var is 2, the first member is drops and the second is poring
  • The definition of separate array members is the same as normal scalar.

They can be set:

$myarray[0] = harry
$myarray[1] = potter

They can be incremented and decremented:

macro Counter {
    $counterArray[1] = 0
    log \$counterArray[1] is at $counterArray[1]
    $counterArray[1]++
    log Now it's $counterArray[1]
    $counterArray[1]--
    log It's back to $counterArray[1]
}

And they can be unset:

$var[5] = 1
log \$var[5] is $var[5]
$var[5] = undef  # or you can use 'unset'
log \$var[5] now vanished: $var[5]
Array Keywords
There are 4 keywords which can be used on arrays:
  • push: Adds a new element to the end of the array, increasing its size by 1.
  • pop: Removes the last element from the end of the array, decreasing its size by 1.
  • shift: Removes the first element of the array and moves the whole array 1 index to the left, decreasing its size by 1.
  • unshift: Adds a new element to the start of the array and moves the whole array 1 index to the right, increasing its size by 1.


push

push syntax is as follows:

&push(@array, newmember)

push must have 2 parameters: the array you want to push, and the new member to be pushed.

Here's an example of an array started from scratch using push:

&push(@names, john)
&push(@names, mary)
&push(@names, juan)

This is the array afterwards:

(john, mary, juan)

And this macro:

macro print_names {
    &push(@monsters, poring)
    &push(@monsters, wolf)
    &push(@monsters, maya)
    log The array \@monsters has size @monsters and its members are $monsters[0], $monsters[1] and $monsters[2]
}

Prints this:

[eventmacro message] The array @monsters has size 3 and its members are poring, wolf and maya


pop

pop syntax is as follows:

&pop(@array)

pop must have 1 parameter: the array you want to pop.

Here's an example of an array, and it after a pop:

@jobs = (teacher, doctor, seller)
log The array \@jobs has size @jobs and its members are $jobs[0], $jobs[1] and $jobs[2]
&pop(@jobs)
log The array \@jobs has size @jobs and its members are $jobs[0], $jobs[1]
&pop(@jobs)
log The array \@jobs has size @jobs and its members are $jobs[0]


This prints this:

[eventmacro message] The array @jobs has size 3 and its members are teacher, doctor and seller
[eventmacro message] The array @jobs has size 2 and its members are teacher, doctor
[eventmacro message] The array @jobs has size 1 and its members are teacher


shift

shift syntax is as follows:

&shift(@array)

shift must have 1 parameter: the array you want to shift. Here's an example of an array, and it after a shift:

@jobs = (teacher, doctor, seller)
log The array \@jobs has size @jobs and its members are $jobs[0], $jobs[1] and $jobs[2]
&shift(@jobs)
log The array \@jobs has size @jobs and its members are $jobs[0], $jobs[1]
&shift(@jobs)
log The array \@jobs has size @jobs and its members are $jobs[0]


This prints this:

[eventmacro message] The array @jobs has size 3 and its members are teacher, doctor and seller
[eventmacro message] The array @jobs has size 2 and its members are doctor, seller
[eventmacro message] The array @jobs has size 1 and its members are seller


After a shift the whole array is moved to the left, so after the first shift the member 'seller' which was in index 2 moved to index 1, and after the second shift it moved to index 0.


unshift

unshift syntax is as follows:

&unshift(@array, newmember)

unshift must have 2 parameters: the array you want to unshift, and the new member to be placed at the beginning of the array.

Here's an example of an array started from scratch using unshift:

&unshift(@foods, bread)
&unshift(@foods, carrot)
&unshift(@foods, apple)

This is the array afterwards:

(apple, carrot, bread)

Note that since unshift puts the new member in the start of the array the first member is now 'apple' which was added last.

And this macro:

macro print_names {
    @array = (apple, banana)
    log The array \@array has size @array and its first member is $array[0], and the second is $array[1]
    &unshift(@array, pineapple)
    log The array \@array has size @array and its first member is $array[0], and the second is $array[1]
    &unshift(@array, melon)
    log The array \@array has size @array and its first member is $array[0], and the second is $array[1]
}

Prints this:

[eventmacro message] The array @array has size 2 and its first member is apple, and the second is banana
[eventmacro message] The array @array has size 3 and its first member is pineapple, and the second is apple
[eventmacro message] The array @array has size 4 and its first member is melon, and the second is pineapple
Hashes

To set the value of hash variable, it must be declared with its pairs inside parentheses, separated by comma, and the key and the value must be separated by =>:

%variable = (key1 => value1, key2 => value2, key3 => value3)

To get a value of a certain key, use $ at the start instead of %, and put the key after the variable name, enclosed by { and }:

$variable{key1}
  • Keys can contain letters and numbers.

Get the number of keys in the hash:

%variable
macro Hello {
   %ages = (john => 25, george => 32)
   log John is $ages{john} years old, and George is $ages{george} years old
}

This would print in the console:

[eventmacro message] log John is 25 years old, and George is 32 years old
  • The definition of separate hash members is the same as a normal scalar.

They can be set:

$name{first} = harry
$name{last} = potter

They can be incremented and decremented:

macro Counter {
    $hash{monterskilled} = 0
    log \$hash{monterskilled} is at $hash{monterskilled}
    $hash{monterskilled}++
    log Now it's $hash{monterskilled}
    $hash{monterskilled}--
    log It's back to $hash{monterskilled}
}

And they can be unset:

$myhash{value} = 1
log \$myhash{value} is $myhash{value}
$myhash{value} = undef  # or you can use 'unset'
log \$myhash{value} now vanished: $myhash{value}
Hash Keywords
There are 2 keywords which can be used on hashes:
  • &delete: which completely deletes a key from a hash, as if it had never existed
  • &exists: checks if a given key has a value
&delete

delete syntax is as follows:

&delete ($<hash>{<key>})
delete must have 1 parameter: hash key to remove.


&exists

exists syntax is as follows:

&exists ($<hash>{<key>})
delete must have 1 parameter: hash key to check. If the <key> has a value, then the function will return 1, else - 0/.
example
macro hash {
   %fruitsprice = (apple => 1000, banana => 700)
   log Hash\%fruitsprice has %fruitsprice keys
   log apple price: $fruitsprice{apple} and bananas price: $fruitsprice{banana}
   &delete($fruitsprice{apple})
   log Hash \%fruitsprice has %fruitsprice key
     if ( &exists($fruitsprice{apple}) ) {
       log apple price: $fruitsprice{banana}
     } else {
       log There are no apples in the Hash
     }
     if ( &exists($fruitsprice{banana}) ) {
       log bananas price: $fruitsprice{banana}
     } else {
       log There are no bananas in the Hash
     }
}
Prints this:
[eventmacro message] Hash%fruitsprice has 2 keys
[eventmacro message] apple price: 1000 and bananas price: 700
[eventmacro message] Hash %fruitsprice has 1 key
[eventmacro message] There are no apples in the Hash
[eventmacro message] bananas price: 700

Special Variables

There are special read-only variables which begin with a dot. They are pre-defined with the eventMacro plugin.

Variable Definition Example
$.time Current time as unix timestamp 1482275422
$.datetime Current date and time Tue Dec 20 21:22:34 2016
$.second Current second time (0 - 59) 53
$.minute Current minute time (0 - 59) 34
$.hour Current hour time in 24h format 14
$.dayofmonth Current day of month 19
$.dayofweek Current day of week (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday) Wednesday
$.map The Map you're currently in prontera
$.incity Boolean, 1 whenever at a city, 0 otherwise 1
$.inlockmap Boolean, 1 whenever at a lockMap, 0 otherwise 1
$.job The current character job Swordman
$.pos Your current position 123 234
$.name The character name Henrybk
$.hp Current HP 2304
$.sp Current SP 345
$.lvl Current base level 175
$.joblvl Current job level 60
$.spirits Number of current spirit spheres or coin flip's coins 3
$.zeny Current zeny 8478341
$.weight Current character weight 1948
$.weightpercent Current character weight in percentage 81.5
$.maxweight Current maximum character weight 2400
$.status Current statuses in a comma-separated list Attention Concentrate,Endure,Two-Hand Quicken
$.statushandle Current statuses handles in a comma-separated list SM_ENDURE,KN_TWOHANDQUICKEN
$.inventoryitems The current amount of items in inventory 13
$.cartweight The current cart weight 800
$.cartweightpercent The current cart weight in percentage 10
$.cartmaxweight The current cart max weight 8000
$.cartitems The current amount of items in cart 21
$.cartmaxitems The current max amount of items in cart 100
$.shopopen 1 if shop is opened, 0 otherwise 0
$.storageopen 1 if storage is opened, 0 otherwise 1
$.storageitems The current amount of items in storage 432
$.storagemaxitems The current max amount of items in storage 600
$.param[N] Command line parameters (see Syntax) N/A
$.caller Name of last automacro enabled N/A

Special Keywords

These keywords (having common form of &<keyword>(<arguments>) each) interpolated to corresponding values just about anywhere inside macro blocks (except goto, end, label definitions, macro name in call, set). Macro variables can be used in arguments, with the exception for &nick().

&questStatus (<questID>)
Returns the status of quest <questID> as a string (inactive, incomplete or complete).
&questInactiveCount (<questID1>,<questID2>,<questID3>,etc)
Returns the number of given quests which have status "inactive".
&questIncompleteCount (<questID1>,<questID2>,<questID3>,etc)
Returns the number of given quests which have status "incomplete".
&questCompleteCount (<questID1>,<questID2>,<questID3>,etc)
Returns the number of given quests which have status "complete".


&inventory (<item|ID>)
Returns inventory item index of <item|ID>. You can specify the name of the item or its ID. If <item> doesn't exist, it returns -1.
&Inventory (<item|ID>)
Same as &inventory but returns all matching indexes as a comma-separated list or -1 if the item was not found.
&invamount (<item|ID>)
Returns the amount of the given <item|ID> in inventory.
&InventoryType (usable|equip|card|etc)
Returns a comma-separated list with all items of the specified type. If no items of that type are found, returns -1


&cart (<item|ID>)
Returns cart item index of <item|ID>. If <item|ID> doesn't exist, it returns -1.
&Cart (<item|ID>)
Same as &cart but returns all matching indexes as a comma-separated list or -1 if the item was not found.
&cartamount (<item|ID>)
Returns the amount of the given <item|ID> in cart.


&storage (<item|ID>)
Returns storage item index of <item|ID>. If <item|ID> doesn't exist, it returns -1.
&Storage (<item|ID>)
Same as &storage but returns all matching indexes as a comma-separated list or -1 if the item was not found.
&storamount (<item|ID>)
Returns the amount of the given <item|ID> in storage.


&venderitem (<item|ID>)
Looks for an item in a player's shop and returns index or -1 if the item was not found.
&venderprice (<item|indexID>)
Looks for an item in a player's shop and returns its price.
&venderamount (<item|ID>)
Returns the amount of the given <item> in a player's shop.


&store (<item|ID>)
Looks for an item in a store and returns index or -1 if the item was not found.
&shopamount (<item|ID>)
Returns the amount of the given <item> in shop.


&npc (<x> <y> | /regexp/i | "<name>")
Return NPC's index which location is <x> <y> or NPC's name match regexp or NPC's name is equal to <name> . Returns -1 if no NPC was found.
&player (<name>)
Returns player index of player <name>. If player <name> is not found, it returns -1.
&monster (<name|ID>)
Returns monster index of monster <name|ID>. If monster <name|ID> is not found, it returns -1.
&vender (<name>)
Returns vender index of vender <name>. If vender <name> is not found, it returns -1.


&config (<variable>)
Returns the value of <variable> specified in config.txt.


&random ("<argument1>", "<argument2>", ...)
Returns randomly one of the given arguments .
&rand (<n>, <m>)
Returns a random number between (and including) <n> and <m>.
&eval (<argument>)
Evaluates the given <argument>. Contents of &eval is Perl and does NOT have eventMacro plugin syntax, except for variables and @() substitution.
&arg ("<argument>", <n>)
Returns the <n>th word of <argument> or an empty string if the word index is out of range.
&nick (<word>)
Escapes all the regexp metacharacters and some of the perl special characters with \ (a backslash). Especially for player's name.


&split (<separator>, <variable>)
Uses separator to create an array from another variable (ex: $list = a,b,c,d; @array = split(',', $list) )
&keys (<%hash>)
Creates an array from the keys of a hash (ex: %hash=(a=>"foo", b=>"bar"); @array = &keys (%hash) )
&values (<%hash>)
Creates an array from the values of a hash
&listlength (<comma_separated_list>)
Returns the length of a <comma_separated_list> (ex: &listlength(a, b, c) )
&strip (<text>)
Removes parentheses ( ) from <text> (ex: $text = (Hello))))) world); log strip: "&strip($text)" )

Chaining commands

You can run multiple commands one after another without having to wait for openkore's AI or macro_delay or whatever. Just enclose these commands with [ and ].

0 macro foo {
1  do whatever
2  log yet another line
3  [
4     do something
5     do something else
6     log foo
7  ]
8  log done
9 }

Line 3 starts the chaining mode. This line has no delay. Lines 4, 5 and 6 are run as soon as the previous command has finished with no delay and they cannot be interrupted. Line 7 stops the chaining mode and line 8 will be run $macro_delay seconds after that.

Sub-lines

Instead of using one command/var assignments per line, you can separate them using a semi-colon ";".

macro foo {
    $i = 1; pause 5; log \$i = $i; $ii = 2; $iii = 3; $i++; $ii--; lock automacroName; release automacroName; set overrideAI 1
}

Commands separated by a semi-colon ";" the normal macro_delay between them.

Operators

Supported operators in eventMacro plugin are:

Operator Description
< less than
<= less or equal to
== or = equal to (link)
> greater than
>= greater or equal to
!= not equal to
~ <left part> is element of <right part (comma-separated list)>
=~ <left part> matches regular expression <right part>

Further Discussion: Forums

arg .. arg2 Between arg and arg2. Where arg can be a number, a % or a variable.

Flow control and labels

  • Just as prevalent in high-level languages ​​constructs like "if .. else", "while", "foreach", "for .. next", "do .. while" and other commands.
  • eventMacro plugin also has the operations "if", "else", "elsif", "switch", "case", "goto" and "while". There's also label declaration.

Syntax of command conditions

If

Right now, macro if conditions are very close to the perl if statements. It accepts unlimited number of statements in just one if condition line, regexp matching is allowed (unfortunately, no backreference using parenthesis) and the use of && for and meaning and || for or meaning.

You can use a simple statement;

if (arg1 <Operators> arg2) (goto <label> | call <macro> [<parameters>] | stop | { )

A simple statement with OR condition;

if (arg1 <Operators> arg2 || arg3 <Operators> arg4) (goto <label> | call <macro> <parameters> | stop | { )

A simple statement with AND condition;

if (arg1 <Operators> arg2 && arg3 <Operators> arg4) (goto <label> | call <macro> <parameters> | stop | { )

Or with both;

if ((arg1 <Operators> arg2 || arg3 <Operators> arg4) && arg5 <Operators> arg6) (goto <label> | call <macro> <parameters> | stop | { )
if ((arg1 <Operators> arg2 && arg3 <Operators> arg4) || arg5 <Operators> arg6) (goto <label> | call <macro> <parameters> | stop | { )
if ((arg1 <Operators> arg2 && arg3 <Operators> arg4) || (arg5 <Operators> arg6 && arg7 <Operators> arg8)) (goto <label> | call <macro> <parameters> | stop | { )
if ((arg1 <Operators> arg2 || arg3 <Operators> arg4) && (arg5 <condition> arg6 || arg7 <condition> arg8)) (goto <label> | call <macro> <parameters> | stop | { )
  • Notice inside of each brackets containing the AND and OR symbols.

Where;

  • arg can be a variable, a nested variable, a special keyword, &eval, letters and numbers or even a Perl Subroutines function.
  • <label>, the name of an existing label, can only contain letters and numbers
  • <macro>, the name of a existing macro, and
  • <parameters>, the macro call parameters (will be set to $.param[0], $param[1], etc),
  • < { >, the beginning of a block of commands that will be executed if the condition is true, to finish it, use }.


Note²: If statements are unlimited, you can use as many statements as you want.

if (arg1 <Operators> arg2 || arg3 <Operators> arg4 || ... || argN <Operators> argN+1) (goto <label> | call <macro> <parameters> | stop)

Where;

  • arg can be a variable, a nested variable, a special keyword, &eval or letters and numbers.
  • All the conditions is up to the Nth argument <Operators> N+1th argument.
  • While N is an integer number/s which is greater than zero.
Postfix control

Another way to use the if is to put it at the end of the command.

<command> if (arg1 <Operators> arg2)

The command before the if statement will only be executed if the condition is true. The way to create the condition is the same as previously explained.

In this example below, the two commands are equivalent:

call buy if ($.zeny > 1000)
if ($.zeny > 1000) call buy

Else

In case if is used with open braces ( { ), it's possible to use the command else along closed braces ( } ) in the end of the command block if, to start a new command block that will be executed if if is false.

if (arg1 <Operators> arg2) {
   command1
   command2
   ...
   commandN
} else {
   command1
   command2
   ...
   commandN
}

In this case, the first command block will be executed if the condition turns out being true. If it's false, the second command block (preceding by else) will be executed.

Note: Inside braces you're allowed to use tons of commands.
Note: It is not compulsory to wear else.

Elsif

It is like the else + if. The elsif is in the same place else with the difference being added conditions to its command block is executed if its conditions are true.

if (arg1 <Operators> arg2) {
   command1
   command2
   ...
   comandoN
} elsif (arg1 <Operators> arg2) {
   command1
   command2
   ...
   commandN
} else {
   command1
   command2
   ...
   commandN
}

In this case, the first block of commands will be executed if the condition is true. If it is false, the second block of commands (preceded by the elsif) will be executed if its condition is true. Should also be false, the command blocks else to be executed.

Note: As in the else, inside braces of elsif you're allowed to use tons of commands.
Note: It is not compulsory to wear the else or elsif.

Switch/case

It's similar to if followed by enumerous elsif. It's useful to leave the code cleaner when the paramater being analyzed is the same, this way you don't need to repeat it.

switch (arg1) {
    case (<Operators> arg2) (goto <label> | call <macro> <parameters> | stop | {)
        (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
    case (<Operators> arg2) (goto <label> | call <macro> <parameters> | stop | {)
        (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
    ...
    else (goto <label> | call <macro> <parameters> | stop | {)
        (If you use "{", the commands should be used here and in a separated line that should be closed with the block "}")
}

Note: The use of else is optional.
Note: In case that no case ends being true, else will be activate if it exists.

Examples

This macro will go a random walk

macro walk {
   $num = &rand(1, 4)
   if ($num == 1) {
       do c I will follow the path 1
       do north
   }
   if ($num == 2) {
       do c I will follow the path 2
       do south
   }
   if ($num == 3) {
       do c I will follow the path 3
       do east
   }
   if ($num == 4) {
       do c I will follow the path 4
       do west
   }
}

Simplified version of the above macro, using postfix control.

macro walk {
   $num = &rand(1, 4)
   do c I will follow the path $num
   do north if ($num == 1)
   do south if ($num == 2)
   do east  if ($num == 3)
   do west  if ($num == 4)
}

The following macro will tell if you've over 1.000z or 1.000z or less.

macro checkZeny {
   if ($.zeny > 1000) {
      do c I've over 1.000z! 
   } else {
      do c I've 1.000z or less...
   }
}

A little more complete than the above macro. Informa has more than 1.000z, has exactly 1.000z or has less than 1.000z with emoticons

macro checkZeny {
   if ($.zeny > 1000) {
      do c I've over 1.000z! 
      do e money
   } elsif ($.zeny == 1000) {
      do c I have exactly 1.000z.
      do e !
   } else {
      do c I've 1.000z or less...
      do e panic
   }
}

Similar to the above but with a different syntax

macro checkZeny {
    switch ($.zeny) {
        case (> 1000) {
            do c I've over 1.000z! 
            do e money
        }
        case (== 1000) {
            do c I have exactly 1.000z.
            do e !
        }
        else {
            do c I've 1.000z or less...
            do e panic
        }
    }
}

The below macro will print \$num is 1 if $num == 1, \$num is 2 if $num == 2, \$num is 3 if $num == 3.

macro checknum {
    $num = &rand(1, 3)
    if ($num == 1) goto one
    if ($num == 2) goto two
    if ($num == 3) goto three
    :one
    log \$num is 1
    stop
    :two
    log \$num is 2
    stop
    :three
    log \$num is 3
    stop
}

The above macro can be written using call instead of goto.

macro checknum {
    $num = &rand(1, 3)
    if ($num == 1) call one
    if ($num == 2) call two
    if ($num == 3) call three
}
macro one {
    log \$num is 1
}
macro two {
    log \$num is 2
}
macro three {
    log \$num is 3
}


A more complicated macro

macro if {
 $i = 1
 log \$i = $i
 if (((($i = 1 || $i < 5 || $i ~ 0 .. 5) && &eval(&eval($i - 1) - &eval($i - 0)) = -1) && ($i != 2 && $i > 0 && &eval($i - 1) = 0) && ($i != 2 && $i > 0 && &eval($i - 1) = 0)) && $i = 1) goto somewhere
 if (($i = 1 || $i < 5 || $i ~ 0 .. 5) && ($i != "" && $i > 0 && &eval($i - 1) = 0)) goto somewhere
 if (&eval (&eval($i-1) - 1) != "") goto somewhere
 if ((($i = 1) || ($i < 5 && $i ~ 0 .. 5)) && ($i != "" && $i > 0 && &eval($i - 1) > 0)) goto somewhere
 log ko
 stop
:somewhere
 log OK
}

WHILE Loop

A while in macros means that certain commands will be ran while the defined conditions are met:

while (arg1 <Operators> arg2) {
    do bla bla
    ...
}

Where;

  • arg can be a variable, a nested variable, a special keyword, &eval, letters and numbers or even a Perl Subroutines function.

Example:

macro while {
    $i = 0
    while ($i < 10) {
    log \$i = $i
    $i++
    }
}

The result is

[eventmacro message] $i = 0
[eventmacro message] $i = 1
[eventmacro message] $i = 2
[eventmacro message] $i = 3
[eventmacro message] $i = 4
[eventmacro message] $i = 5
[eventmacro message] $i = 6
[eventmacro message] $i = 7
[eventmacro message] $i = 8
[eventmacro message] $i = 9


Automacros

At this point, you can define macros and call them, typing 'eventMacro <macro name>' in OpenKore's console input.

Automacro is an automatic trigger for calling your macros, just like blocks in config.txt are automatic triggers for certain AI actions.

Automacro block consists of:

Automacro does not trigger if there is currently running macro in exclusive mode. Otherwise, automacro clears macro queue (which means that all currently running macros are stopped) before call.

The point of automacro is that you use them to check for certain conditions and call your macro when all conditions are fulfilled.

All possible conditions are listed on the category page.

Parameters

  • Each parameter can only be used once.
  • Parameters define the way the automacro or the called macro will work.
  • Most parameters have a default value that will be used when it is not defined.
call [<macro_name> | macro_block ]
  • call is the only required parameter in every automacro.
  • call defines which macro the automacro will execute.
  • call can be a macro name or a macro block.

Example when using a macro name:

automacro <automacro name> {
    <automacro conditions and parameters (and only them)>
    call myMacro
}
macro myMacro {
    <macro instructions (and only them, as this is regular macro)>
    # for example:
    do move prontera
    do move payon
}

Example when using a macro block:

automacro <automacro name> {
    <automacro conditions and parameters (and only them)>
    call {
        <macro instructions (and only them, as this is regular macro)>
        # for example:
        do move prontera
        do move payon
    }
}


  • Two examples above do the same thing.
  • Note that the macro block used in the call parameter has the same rules as a normal macro block.


The first syntax is useful if you want more than one automacro to call one simple macro:

automacro First {
    <conditions> 
    call print
}
automacro Second {
    <conditions> 
    call print
}
macro print {
    log $.caller triggered
}

delay <seconds>
  • delay is an optional parameter.
  • delay defines the time in seconds to wait before executing the macro in call parameter.
  • If not used in the automacro the default value will be used, which is: 0.
  • Must have a numeric value.
automacro <automacro name> {
    <automacro conditions and parameters (and only them)>
    delay 5
    call myMacro
}
macro myMacro {
    <macro instructions (and only them, as this is regular macro)>
    log This is being logged 5 seconds after the automacro activated
}

run-once <boolean>
  • run-once is an optional parameter.
  • run-once defines if the automacro can activate only once, or multiple times.
  • If not used in the automacro the default value will be used, which is: 0.
  • When it's value is 1 the automacro will only activate once, when it's 0 it can activate multiple times.
  • To make an automacro with run-once value of 1 which already was already activated be able to run again you can use the command 'release' Macro Syntax.
automacro MyAuto1 {
    <automacro conditions and parameters (and only them)>
    run-once 1
    call myMacro
}
automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    run-once 0
    call myMacro
}
macro myMacro {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will be called by MyAuto1 only once
    log but this macro can be called by MyAuto2 many times
}

CheckOnAI [auto, manual, off]
  • CheckOnAI is an optional parameter.
  • CheckOnAI defines in which AI states the automacro can activate.
  • The default value for this parameter can be set in the config key eventMacro_CheckOnAI Configuration files.
  • If not used in the automacro the default value will be used, which is the config key eventMacro_CheckOnAI.
  • If eventMacro_CheckOnAI is not set in the config the default value will be used, which is: auto
  • It's values can be a combination of auto, manual and off, separated by comma.
automacro MyAuto1 {
    <automacro conditions and parameters (and only them)>
    CheckOnAI manual
    call myMacro1
}
macro myMacro1 {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will only be called by MyAuto when AI is manual
}

automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    CheckOnAI manual, off
    call myMacro2
}
macro myMacro2 {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will only be called by MyAuto2 when AI is manual or off
}

disabled <boolean>
  • disabled is an optional parameter.
  • disabled defines if the automacro is active of not.
  • If not used in the automacro the default value will be used, which is: 0.
  • When it's value is 1 the automacro won't activate ever, when it's 0 it can activate normally.
automacro MyAuto1 {
    <automacro conditions and parameters (and only them)>
    disabled 1
    call myMacro1
}
macro myMacro1 {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will never be called by MyAuto1
}

automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    disabled 0
    call myMacro2
}
macro myMacro2 {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will be called by MyAuto2 normally
}
overrideAI <boolean>
  • overrideAI is an optional parameter.
  • overrideAI defines if eventMacro will put itself in the AI queue.
  • If not used in the automacro the default value will be used, which is: 0.
  • When it's value is 0 the macro will be put into AI queue as 'eventMacro' and the next macro command will only be run if current AI is 'eventMacro'.
  • When it's value is 1 the macro will not be put into AI queue and the next macro command will always be run.
  • It's important to note that when it's value is 1 since it won't be put into AI queue normal AI functions will continue as normal, like mob hunting or autostorage.
automacro MyAuto1 {
    <automacro conditions and parameters (and only them)>
    overrideAI 0
    call myMacro1
}
macro myMacro1 {
    <macro instructions (and only them, as this is regular macro)>
    do move prontera
    log This will only be printed when the 'move prontera' has been completed, since 'move' takes the first place in AI queue.
}

automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    overrideAI 1
    call myMacro2
}
macro myMacro2 {
    <macro instructions (and only them, as this is regular macro)>
    do move prontera
    log This will be printed after a macro_delay has passed before the last command, because it won't check AI queue.
}

exclusive <boolean>
  • exclusive is an optional parameter.
  • exclusive defines if the macro can be interrupted or not.
  • If not used in the automacro the default value will be used, which is: 0.
  • When it's value is 0 the macro can be interrupted by other automacros.
  • When it's value is 1 the macro can not be interrupted by other automacros.
automacro MyAuto1 {
    <automacro conditions and parameters (and only them)>
    exclusive 0
    call myMacro1
}
macro myMacro1 {
    <macro instructions (and only them, as this is regular macro)>
    log This would probably cause a bug because the automacro would activate every AI cycle since the macro is interruptible.
}

automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    exclusive 1
    call myMacro2
}
macro myMacro2 {
    <macro instructions (and only them, as this is regular macro)>
    log Since exclusive is 1 the macro is now uninterruptible and will work properly.
}

priority <number>
  • priority is an optional parameter.
  • priority defines the priority for activation the automacro has between all automacros, the lower the priority, the sooner it will be checked.
  • If not used in the automacro the default value will be used, which is: 0.
  • Must have a numeric value.
automacro MyAuto1 {
    <automacro conditions and parameters (and only them)>
    priority 5
    call {
        log This automacro will be checked after MyAuto2 because it's priority is higher
    }
}

automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    priority 2
    call {
        log This automacro will be checked before MyAuto1 because it's priority is lower
    }
}

macro_delay <number>
  • macro_delay is an optional parameter.
  • macro_delay defines the time in seconds to wait between macro commands.
  • If not used in the automacro the default value will be used, which is: 1.
  • Must have a numeric value.
automacro MyAuto1 {
    <automacro conditions and parameters (and only them)>
    macro_delay 2
    call {
        log This will be printed at the macro execution
        log This will be printed 2 seconds after
    }
}

automacro MyAuto2 {
    <automacro conditions and parameters (and only them)>
    macro_delay 5
    call {
        log This will be printed at the macro execution
        log This will be printed 5 seconds after
    }
}

orphan [ terminate | reregister | reregister_safe | terminate_last_call ]
  • orphan is an optional parameter.
  • orphan defines how will eventMacro deal with macros when 'eventMacro' is cleaned out of AI queue.
  • The default value for this parameter can be set in the config key eventMacro_orphans Configuration files.
  • If not used in the automacro the default value will be used, which is the config key eventMacro_orphans.
  • If eventMacro_orphans is not set in the config the default value will be used, which is: terminate
  • The valid values and their descriptions are the following:
Value Description
terminate terminates the macro (equivalent to eventMacro stop)
terminate_last_call terminates only the last call of the queue, this means that if macro 'mac1' called 'mac2' which called 'mac3', who got orphaned, only 'mac3' gets terminated, and queue returns to 'mac2'.
reregister re-registers to AI queue, overriding other entries. This means to force the continuation of the macro.
reregister_safe re-registers to AI queue when AI gets idle. This means the macro will continue when all other tasks are done.
repeat <number>
  • repeat is an optional parameter.
  • repeat defines how many times the macro defined by call will be called.
  • If not used in the automacro the default value will be used, which is: 1.
  • Must have a numeric value.
automacro <automacro name> {
    <automacro conditions and parameters (and only them)>
    repeat 3
    call myMacro
}
macro myMacro {
    <macro instructions (and only them, as this is regular macro)>
    log This message will be printed 3 times, because the macro will be called 3 times
}

timeout <number>
  • timeout is an optional parameter.
  • timeout defines the time in seconds before this automacro can activate again after an activation.
  • If not used in the automacro the default value will be used, which is: 0.
  • Must have a numeric value.
automacro <automacro name> {
    <automacro conditions and parameters (and only them)>
    timeout 60
    call myMacro
}
macro myMacro {
    <macro instructions (and only them, as this is regular macro)>
    log This macro will only be called every 60 seconds
}


Conditions

  • Conditions are separated into 2 categories: state and event.
  • Most conditions set special variables when the automacro activates.
  • Most conditions accept variables in their code.
  • Each automacro can only have one event condition.
  • Most state conditions can be used more than once in each automacro.
  • Each condition will have it's detailed explanation below.
  • eventMacro has a modular condition system, each file inside eventMacro/Condition is a condition.
State
  • State conditions have a defined status of true or false.
  • An automacro will only activate when all of it's state conditions are true.


BaseLevel
  • Description: Checks the player base level.
  • Does not support percentages.
Syntax:
BaseLevel <Math condition operators>
Example:
BaseLevel >= 30
Set variables:
$.BaseLevelLast => Saves the last level that made BaseLevel become true

JobLevel
  • Description: Checks the player job level.
  • Does not support percentages.
Syntax:
JobLevel <Math condition operators>
Example:
JobLevel = 70
Set variables:
$.JobLevelLast => Saves the last job level that made JobLevel become true

CartCurrentWeight
  • Description: Checks the player's cart current weight.
  • Supports percentages.
Syntax:
CartCurrentWeight <Math condition operators>
Example:
CartCurrentWeight > 80%
CartCurrentWeight > 4000
Set variables:
$.CartCurrentWeightLast => Saves the last cart weight that made CartCurrentWeight become true
$.CartCurrentWeightLastPercent => Saves the last cart weight percentage that made CartCurrentWeight become true

CartMaxWeight
  • Description: Checks the player's cart max weight.
  • Does not support percentages.
Syntax:
CartMaxWeight <Math condition operators>
Example:
CartMaxWeight > 4000
Set variables:
$.CartMaxWeightLast => Saves the last cart max weight that made CartMaxWeight become true

CartCurrentSize
  • Description: Checks the player's cart current item quantity.
  • Supports percentages.
Syntax:
CartCurrentSize <Math condition operators>
Example:
CartCurrentSize > 80%
CartCurrentSize > 4000
Set variables:
$.CartCurrentSizeLast => Saves the last cart item quantity that made CartCurrentSize become true
$.CartCurrentSizeLastPercent => Saves the last cart item quantity percentage that made CartCurrentSize become true

CartMaxSize
  • Description: Checks the player's cart max item quantity.
  • Does not support percentages.
Syntax:
CartMaxSize <Math condition operators>
Example:
CartMaxSize > 4000
Set variables:
$.CartMaxSizeLast => Saves the last cart max item quantity that made CartMaxSize become true

CharCurrentWeight
  • Description: Checks the player's current weight.
  • Supports percentages.
Syntax:
CharCurrentWeight <Math condition operators>
Example:
CharCurrentWeight > 80%
CharCurrentWeight > 4000
Set variables:
$.CharCurrentWeightLast => Saves the last player weight that made CharCurrentWeight become true
$.CharCurrentWeightLastPercent => Saves the last player weight percentage that made CharCurrentWeight become true

CharMaxWeight
  • Description: Checks the player's max weight.
  • Does not support percentages.
Syntax:
CharMaxWeight <Math condition operators>
Example:
CharMaxWeight > 4000
Set variables:
$.CharMaxWeightLast => Saves the last player max weight that made CharMaxWeight become true

FreeStatPoints
  • Description: Checks the player's free stat points.
  • Does not support percentages.
Syntax:
FreeStatPoints <Math condition operators>
Example:
FreeStatPoints > 20
Set variables:
$.FreeStatPointsLast => Saves the last amount of free stat points that made FreeStatPoints become true

FreeSkillPoints
  • Description: Checks the player's free skill points.
  • Does not support percentages.
Syntax:
FreeSkillPoints <Math condition operators>
Example:
FreeSkillPoints > 20
Set variables:
$.FreeSkillPointsLast => Saves the last amount of free skill points that made FreeSkillPoints become true

CurrentHP
  • Description: Checks the player's current hp.
  • Supports percentages.
Syntax:
CurrentHP <Math condition operators>
Example:
CurrentHP > 80%
CurrentHP > 4000
Set variables:
$.CurrentHPLast => Saves the last player hp that made CurrentHP become true
$.CurrentHPLastPercent => Saves the last player hp percentage that made CurrentHP become true

MaxHP
  • Description: Checks the player's max hp.
  • Does not support percentages.
Syntax:
MaxHP <Math condition operators>
Example:
MaxHP > 4000
Set variables:
$.MaxHPLast => Saves the last player max hp that made MaxHP become true

CurrentSP
  • Description: Checks the player's current sp.
  • Supports percentages.
Syntax:
CurrentSP <Math condition operators>
Example:
CurrentSP > 80%
CurrentSP > 4000
Set variables:
$.CurrentSPLast => Saves the last player sp that made CurrentSP become true
$.CurrentSPLastPercent => Saves the last player sp percentage that made CurrentSP become true

MaxSP
  • Description: Checks the player's max sp.
  • Does not support percentages.
Syntax:
MaxSP <Math condition operators>
Example:
MaxSP > 4000
Set variables:
$.MaxSPLast => Saves the last player max sp that made MaxSP become true

InInventory
  • Description: Checks if the player has a certain quantity of an item in the inventory, uses item name.
  • Does not support percentages.
Syntax:
InInventory "<item name>" <Math condition operators>
Note the quotation marks.
Example:
InInventory "Red Potion" < 10
Set variables:
$.InInventoryLast => Saves the name of the last item that made InInventory become true
$.InInventoryLastAmount => Saves the amount in inventory of the last item that made InInventory become true

InInventoryID
  • Description: Checks if the player has a certain quantity of an item in the inventory, uses item ID.
  • Does not support percentages.
Syntax:
InInventoryID <item ID> <Math condition operators>
Example:
InInventoryID 501 < 10
Set variables:
$.InInventoryIDLast => Saves the ID of the last item that made InInventoryID become true
$.InInventoryIDLastAmount => Saves the amount in inventory of the last item that made InInventoryID become true

InStorage
  • Description: Checks if the player has a certain quantity of an item in the storage, uses item name.
  • Does not support percentages.
Syntax:
InStorage "<item name>" <Math condition operators>
Note the quotation marks.
Example:
InStorage "Blue Potion" > 100
Set variables:
$.InStorageLast => Saves the name of the last item that made InStorage become true
$.InStorageLastAmount => Saves the amount in storage of the last item that made InStorage become true

InStorageID
  • Description: Checks if the player has a certain quantity of an item in the storage, uses item ID.
  • Does not support percentages.
Syntax:
InStorageID <item ID> <Math condition operators>
Example:
InStorageID 507 100..500
Set variables:
$.InStorageIDLast => Saves the ID of the last item that made InStorageID become true
$.InStorageIDLastAmount => Saves the amount in storage of the last item that made InStorageID become true

InCart
  • Description: Checks if the player has a certain quantity of an item in the cart, uses item name.
  • Does not support percentages.
Syntax:
InCart "<item name>" <Math condition operators>
Note the quotation marks.
Example:
InCart "Blue Potion" > 100
Set variables:
$.InCartLast => Saves the name of the last item that made InCart become true
$.InCartLastAmount => Saves the amount in cart of the last item that made InCart become true

InCartID
  • Description: Checks if the player has a certain quantity of an item in the cart, uses item ID.
  • Does not support percentages.
Syntax:
InCartID <item ID> <Math condition operators>
Example:
InCartID 507 100..500
Set variables:
$.InCartIDLast => Saves the ID of the last item that made InCartID become true
$.InCartIDLastAmount => Saves the amount in cart of the last item that made InCartID become true

InventoryCurrentSize
  • Description: Checks the player current item count.
  • Supports percentages. (but it won't change anything since you can have 100 items max)
Syntax:
InventoryCurrentSize <Math condition operators>
Example:
InventoryCurrentSize > 70%
InventoryCurrentSize > 30
Set variables:
$.InventoryCurrentSizeLast => Saves the last player item count that made InventoryCurrentSize become true

SkillLevel
  • Description: Checks if the player has a certain level of a certain skill, uses skill Id or Handle.
  • Does not support percentages.
Syntax:
SkillLevel <skill ID or Handle> <Math condition operators>
Example:
SkillLevel NV_FIRSTAID = 0
SkillLevel 10 > 5
Set variables:
$.SkillLevelLastName => Saves the name of the last skill that made SkillLevel become true
$.SkillLevelLastID => Saves the ID of the last skill that made SkillLevel become true
$.SkillLevelLastHandle => Saves the Handle of the last skill that made SkillLevel become true
$.SkillLevelLastLevel => Saves the level of the last skill that made SkillLevel become true

Zeny
  • Description: Checks the player current zeny.
  • Does not support percentages.
Syntax:
Zeny <Math condition operators>
Example:
Zeny > 500000
Set variables:
$.ZenyLast => Saves the last zeny amount that made Zeny become true

StorageOpened
  • Description: Is true if storage is opened and it is set to 1 or storage is not opened and it is set to 0.
Syntax:
StorageOpened <1|0>
Example:
StorageOpened 1

ShopOpened
  • Description: Is true if your vending shop is opened and it is set to 1 or your vending shop is not opened and it is set to 0.
Syntax:
ShopOpened <1|0>
Example:
ShopOpened 1

InChatRoom
  • Description: Is true if you are in a chat room and it is set to 1 or you are not in a chat room and it is set to 0.
Syntax:
InChatRoom <1|0>
Example:
InChatRoom 0

ChatRoomNear
  • Description: Checks if there is a npc near which name matches the given regex.
Syntax:
NpcNear <Regex>
Example:
NpcNear /kafra/
NpcNear /special agent/
Set variables:
$.ChatRoomNearLastID => Saves the ID of the last chat room that made ChatRoomNear become true
$.ChatRoomNearLastOwnerID => Saves the ID of the owner of the last chat room that made ChatRoomNear become true
$.ChatRoomNearLastOwnerName => Saves the name of the owner of the last chat room that made ChatRoomNear become true
$.ChatRoomNearLastTitle => Saves the title of the last chat room that made ChatRoomNear become true

InMap
  • Description: Checks if the current map match one of the given maps.
Syntax:
InMap <comma separated list of maps>
Map can be a variable.
Example:
InMap prontra, geffen, gef_fild10
Set variables:
$.InMapLast => Saves the last map that made InMap become true

InLockMap
  • Description: Is true if you are in lockmap and it is set to 1 or you are not in lockmap and it is set to 0.
Syntax:
InLockMap <1|0>
Example:
InLockMap 1

InSaveMap
  • Description: Is true if you are in savemap and it is set to 1 or you are not in savemap and it is set to 0.
Syntax:
InSaveMap <1|0>
Example:
InSaveMap 0

IsInCoordinate
  • Description: Checks if the current coordinates match one of the given ones.
Syntax:
IsInCoordinate <comma separated list of pairs of x and y coordinates>
It also accepts ranges in place of coordinates. (like 100..200 for x and 50..100 for y)
Example:
IsInCoordinate 100 150
IsInCoordinate 120 100, 115 289, 158 236
IsInCoordinate 20..80 200, 50 60, 80 90..150, 100..200 150..200
IsInCoordinate 30..35 40..45
Set variables:
$.IsInCoordinateLast => Saves the last coordinate that made IsInCoordinate become true
$.IsInCoordinateLastMemberIndex => Saves the list index in condition that made IsInCoordinate become true

IsInMapAndCoordinate
  • Description: Checks if the current map and/or coordinates match one of the given maps.
Syntax:
IsInMapAndCoordinate <comma separated list of pairs of x and y coordinates and/or maps>
It also accepts ranges in place of coordinates. (like 100..200 for x and 50..100 for y)
You can use map, coordinates or map with coordinates
Example:
IsInMapAndCoordinate 100 150
IsInMapAndCoordinate prontera
IsInMapAndCoordinate prontra, geffen, gef_fild10
IsInMapAndCoordinate 120 100, 115 289, 158 236
IsInMapAndCoordinate prontera, 100 200, gef_fild10 100..150 250
IsInMapAndCoordinate gef_fild10 20..80 200, payon 50 60
Set variables:
$.IsInMapAndCoordinateLast => Saves the last coordinate that made IsInMapAndCoordinate become true
$.IsInMapAndCoordinateLastMemberIndex => Saves the list index in condition that made IsInMapAndCoordinate become true

InPvP
  • Description: Checks if the current pvp type of the map matches the given type.
Syntax:
InPvP <comma separated list of pvp types>
Valid pvp types: pvp, gvg and battleground
Example:
InPvP battleground, pvp
Set variables:
$.InPvPLast => Saves the last pvp type that made InPvP become true

InCity
  • Description: Checks if the player is in a city or not.
Syntax:
InCity <0 | 1>
When value is 0: Only true if map is not a city
When value is 1: Only true if map is a city
Example:
InCity 1
Set variables:
$.InCityLast => Saves the name of the last map that made InCity become true

InMapRegex
  • Description: Checks if the current map matches the given regex.
Syntax:
InMapRegex <Regex>
Example:
InMapRegex /field\d+$/
InMapRegex /^pay/
Set variables:
$.InMapRegexLast => Saves the name of the last map that made InMapRegex become true

NpcNear
  • Description: Checks if there is a npc near which name matches the given regex.
Syntax:
NpcNear <Regex>
Example:
NpcNear /kafra/
NpcNear /special agent/
Set variables:
$.NpcNearLast => Saves the name of the last npc that made NpcNear become true
$.NpcNearLastPos => Saves the position of the last npc that made NpcNear become true (can be used for 'talknpc' command)
$.NpcNearLastBinId => Saves the openkore ID of the last npc that made NpcNear become true (can be used for 'talk' command)
$.NpcNearLastDist => Saves the distance of the last npc that made NpcNear become true

NpcNearDist
  • Description: Checks if there is a npc in a given distance which name matches the given regex.
Syntax:
NpcNearDist <Regex> <Math condition operators>
Example:
NpcNearDist /kafra/ <= 4
NpcNearDist /special agent/ >= 5
Set variables:
$.NpcNearDistLast => Saves the name of the last npc that made NpcNearDist become true
$.NpcNearDistLastPos => Saves the position of the last npc that made NpcNearDist become true (can be used for 'talknpc' command)
$.NpcNearDistLastBinId => Saves the openkore ID of the last npc that made NpcNearDist become true (can be used for 'talk' command)
$.NpcNearDistLastDist => Saves the distance of the last npc that made NpcNearDist become true

NpcNotNear
  • Description: Checks if there's no npc near which name matches the given regex.
Syntax:
NpcNotNear <Regex>
Example:
NpcNotNear /kafra/
NpcNotNear /special agent/
Sets no variables
PlayerNear
  • Description: Checks if there is a player near which name matches the given regex.
Syntax:
PlayerNear <Regex>
Example:
PlayerNear /john/
PlayerNear /henry the best TM/i
Set variables:
$.PlayerNearLast => Saves the name of the last player that made PlayerNear become true
$.PlayerNearLastPos => Saves the position of the last player that made PlayerNear become true
$.PlayerNearLastBinId => Saves the openkore ID of the last player that made PlayerNear become true
$.PlayerNearLastDist => Saves the distance of the last player that made PlayerNear become true

PlayerNearDist
  • Description: Checks if there is a player in a given distance which name matches the given regex.
Syntax:
PlayerNearDist <Regex> <Math condition operators>
Example:
PlayerNearDist /bad gm/ < 10
PlayerNearDist /good guy healer/ <5
Set variables:
$.PlayerNearDistLast => Saves the name of the last player that made PlayerNearDist become true
$.PlayerNearDistLastPos => Saves the position of the last player that made PlayerNearDist become true
$.PlayerNearDistLastBinId => Saves the openkore ID of the last player that made PlayerNearDist become true
$.PlayerNearDistLastDist => Saves the distance of the last player that made PlayerNearDist become true

PlayerNotNear
  • Description: Checks if there's no player near which name matches the given regex.
Syntax:
PlayerNotNear <Regex>
Example:
PlayerNotNear /the guy I need to see/
PlayerNotNear /^(john|george|paul|ringo)$/i
Sets no variables
MobNear
  • Description: Checks if there is a mob near which name matches the given regex.
Syntax:
MobNear <Regex>
Example:
MobNear /(edga|maya|ifrit|bad mvps)/i
MobNear /oring/
Set variables:
$.MobNearLast => Saves the name of the last mob that made MobNear become true
$.MobNearLastPos => Saves the position of the last mob that made MobNear become true
$.MobNearLastBinId => Saves the openkore ID of the last mob that made MobNear become true
$.MobNearLastDist => Saves the distance of the last mob that made MobNear become true

MobNearDist
  • Description: Checks if there is a mob in a given distance which name matches the given regex.
Syntax:
MobNearDist <Regex> <Math condition operators>
Example:
MobNearDist /(Poporing|Drops|Poring|Marin)/ < 3
Set variables:
$.MobNearDistLast => Saves the name of the last mob that made MobNearDist become true
$.MobNearDistLastPos => Saves the position of the last mob that made MobNearDist become true
$.MobNearDistLastBinId => Saves the openkore ID of the last mob that made MobNearDist become true
$.MobNearDistLastDist => Saves the distance of the last mob that made MobNearDist become true

MobNotNear
  • Description: Checks if there's no mob near which name matches the given regex.
Syntax:
MobNotNear <Regex>
Example:
MobNotNear /mvp I am look for/
MobNotNear /edga/i
Sets no variables
JobID
  • Description: Checks if the Job ID of the current player job matches one of the given ones.
Syntax:
JobID <job ID 1>, <job ID 2>, <job ID 3>, etc
Example:
JobID 6, 4053
Set variables:
$.JobIDLast => Saves the ID of the last job that made JobID become true

JobIDNot
  • Description: Checks if the Job ID of the current player job does not match the given one.
Syntax:
JobIDNot <job ID>
Example:
JobIDNot 6
Set variables:
$.JobIDNotLast => Saves the ID of the condition that made JobIDNot become true

IsEquippedID
  • Description: Checks if the player has an item equipped which ID matches the given one.
Syntax:
IsEquippedID <comma separated list of pairs of equip place and ID>
Example:
IsEquippedID topHead 5055
IsEquippedID rightHand 13040, topHead 5055
IsEquippedID topHead 5055, leftHand 2112, robe 2510, shoes 2414, armor 2352, rightHand 1243
Set variables:
$.IsEquippedIDLastID => Saves the id of the last equip which made IsEquippedID become true
$.IsEquippedIDLastName => Saves the name of the last equip which made IsEquippedID become true
$.IsEquippedIDLastSlot => Saves the slot of the last equip which made IsEquippedID become true
$.IsEquippedIDLastListIndex => Saves the index in the condition list of the last equip which made IsEquippedID become true

IsNotEquippedID
  • Description: Checks if the player doesn't have an item equipped which ID matches the given one.
Syntax:
IsNotEquippedID <comma separated list of pairs of equip place and ID>
Example:
IsNotEquippedID topHead 5055
IsNotEquippedID rightHand 13040, topHead 5055
IsNotEquippedID topHead 5055, leftHand 2112, robe 2510, shoes 2414, armor 2352, rightHand 1243
Set variables:
$.IsNotEquippedIDLastIsEmpty => Saves wheter the slot was empty or not
$.IsNotEquippedIDLastSlot => Saves the slot which made IsNotEquippedID become true

ConfigKey
  • Description: Checks if the one or more of the given config keys match it's desired value.
Syntax:
ConfigKey <comma separated list of pairs of config key and value>
Config key and config value can be variables. (as in ConfigKey attackAuto $myattack or ConfigKey $vars{atk} 2)
Example:
ConfigKey attackAuto 2, itemsTakeAuto 2
Set variables:
$.ConfigKeyLastKey => Saves the key of the last config key that made ConfigKey become true
$.ConfigKeyLastValue => Saves the value of the last config key that made ConfigKey become true
$.ConfigKeyLastMemberIndex => Saves the list index in condition list that made ConfigKey become true

ConfigKeyNot
  • Description: Checks if the at least one of the config key pairs doesn't match their desired value.
Syntax:
ConfigKeyNot <comma separated list of pairs of config key and value>
Config key and config value can be variables. (as in ConfigKeyNot attackAuto $myattack or ConfigKeyNot $vars{atk} 2)
Example:
ConfigKeyNot $vars{atk} 2
ConfigKeyNot itemsTakeAuto 1, attackAuto 2
Set variables:
$.ConfigKeyNotLastKey => Saves the key of the last config key that made ConfigKeyNot become true
$.ConfigKeyNotLastWantedValue => Saves the desired value specified in the condifion of the last config key that made ConfigKeyNot become true
$.ConfigKeyNotLastKeyValue => Saves the value of the last config key that made ConfigKeyNot become true
$.ConfigKeyNotLastMemberIndex => Saves the list index in condition list that made ConfigKeyNot become true
Note: Good to be sure your keys are the way you want, example below.
automacro ConfigWasWrong {
    exclusive 1
    timeout 10
    overrideAI 1
    ConfigKeyNot itemsTakeAuto 2, attackAuto 2
    call {
        log There is a config key with the wrong configuration
        log The key is $.ConfigKeyNotLastKey
        log The wanted value is $.ConfigKeyNotLastWantedValue
        log The current key Value is $.ConfigKeyNotLastKeyValue
        log The Index is $.ConfigKeyNotLastMemberIndex
        log Changing value of key $.ConfigKeyNotLastKey from $.ConfigKeyNotLastKeyValue to $.ConfigKeyNotLastWantedValue
        do conf $.ConfigKeyNotLastKey $.ConfigKeyNotLastWantedValue
    }
}

This macro will make sure all config keys specified in ConfigKeyNot have the desired value.

ConfigKeyNotExist
  • Description: Checks if the at least one of the config keys doesn't exist in config.txt.
Syntax:
ConfigKeyNotExist <comma separated list config keys>
Config key can be a variable
Example:
ConfigKeyNotExist gameGuard, saveMap
Set variables:
$.ConfigKeyNotExistLastKey => Saves the last config key that made ConfigKeyNotExist become true
$.ConfigKeyNotExistLastMemberIndex => Saves the list index in condition list that made ConfigKeyNotExist become true
Note: Good to be sure your custom config keys were added (can auto-configure plugins), example below with perl sub to add missing keys:
automacro AddgameGuardMissingKey {
    exclusive 1
    timeout 10
    overrideAI 1
    CheckOnAI auto, manual, off
    ConfigKeyNotExist gameGuard
    call {
        $wantedkey = $.ConfigKeyNotExistLastKey
        $wantedvalue = 1
        call AddMissingKey
    }
}

automacro AddcmdOnLoginMissingKey {
    exclusive 1
    timeout 10
    overrideAI 1
    CheckOnAI auto, manual, off
    ConfigKeyNotExist cmdOnLogin
    call {
        $wantedkey = $.ConfigKeyNotExistLastKey
        $wantedvalue = c \@autoloot
        call AddMissingKey
    }
}

macro AddMissingKey {
    log There is a missing key in config.txt
    log The key is $wantedkey
    log The wanted value for it is is $wantedvalue
    log Adding key $wantedkey with value $wantedvalue with perl sub 'add_key'
    add_key("$wantedkey","$wantedvalue")
}

sub add_key {
    my ($key, $value) = @_;
    configModify($key, $value);
}

This macro will make sure you added the config keys for gameGuard and cmdOnLogin plugin.

InProgressBar
  • Description: Checks if the player is waiting for a progress bar to end.
Syntax:
InProgressBar <0 | 1>
When value is 0: Only true if not waiting for a progress bar
When value is 1: Only true if waiting for a progress bar
Example:
InProgressBar 1
Sets no variables
StatusActiveHandle
  • Description: Checks if the player has one of the given status, uses status HANDLE.
Syntax:
StatusActiveHandle <comma separated list of status handles>
Status handle can be a variable
Example:
StatusActiveHandle EFST_INC_AGI, EFST_IMPOSITIO
Set variables:
$.StatusActiveHandleLastName => Saves the name of the last stauts that made StatusActiveHandle become true
$.StatusActiveHandleLastHandle => Saves the handle of the last stauts that made StatusActiveHandle become true
$.StatusActiveHandleLastListIndex => Saves the list index in condition of the last stauts that made StatusActiveHandle become true

StatusInactiveHandle
  • Description: Checks if the player doesn't have one of the given status, uses status HANDLE.
Syntax:
StatusInactiveHandle <comma separated list of status handles>
Status handle can be a variable
Example:
StatusInactiveHandle EFST_BLESSING, EFST_CONCENTRATION
Set variables:
$.StatusInactiveHandleLastName => Saves the name of the last stauts that made StatusInactiveHandle become true
$.StatusInactiveHandleLastHandle => Saves the handle of the last stauts that made StatusInactiveHandle become true
$.StatusInactiveHandleLastListIndex => Saves the list index in condition of the last stauts that made StatusInactiveHandle become true

QuestActive
  • Description: Checks if the player has one of the given quests active, uses quest ID (use command 'quest list' to see ID).
Syntax:
QuestActive <comma separated list of quests ID>
Quest ID can be a variable
Example:
QuestActive 7121, 7122
Set variables:
$.QuestActiveLastID => Saves the ID of the last quest that made QuestActive become true
$.QuestActiveLastListIndex => Saves the list index in condition of the last quest that made QuestActive become true

QuestInactive
  • Description: Checks if the player has of the given quests inactive, uses quest ID (use command 'quest list' to see ID).
Syntax:
QuestInactive <comma separated list of quests ID>
Quest ID can be a variable
Example:
QuestInactive 7121, 7122
Set variables:
$.QuestInactiveLastID => Saves the ID of the last quest that made QuestInactive become true
$.QuestInactiveLastListIndex => Saves the list index in condition of the last quest that made QuestInactive become true

QuestOnTime
  • Description: Checks if the player has one of the given quests active, and this quest has a timer that hasn't ended yet, uses quest ID (use command 'quest list' to see ID).
Syntax:
QuestOnTime <comma separated list of quests ID>
Quest ID can be a variable
Example:
QuestOnTime 7121, 7122
Set variables:
$.QuestOnTimeLastID => Saves the ID of the last quest that made QuestOnTime become true
$.QuestOnTimeLastListIndex => Saves the list index in condition of the last quest that made QuestOnTime become true

QuestTimeOverdue
  • Description: Checks if the player has one of the given quests active, and this quest has a timer that has already ended, uses quest ID (use command 'quest list' to see ID).
Syntax:
QuestTimeOverdue <comma separated list of quests ID>
Quest ID can be a variable
Example:
QuestTimeOverdue 7121, 7122
Set variables:
$.QuestTimeOverdueLastID => Saves the ID of the last quest that made QuestTimeOverdue become true
$.QuestTimeOverdueLastListIndex => Saves the list index in condition of the last quest that made QuestTimeOverdue become true

QuestHuntCompleted
  • Description: Checks if the player has one of the given quests active, and this quest has a hunt mission which wasn't completed yet, uses quest ID and Mob ID (use command 'quest list' to see ID).
Syntax:
QuestHuntCompleted <comma separated list of pairs of quests ID and Mob ID>
Quest ID and/or Mob ID can be variables
Example:
QuestHuntCompleted 7122 1002, 7127 1004
Set variables:
$.QuestHuntCompletedLastQuestID => Saves the Quest ID of the last quest that made QuestHuntCompleted become true
$.QuestHuntCompletedLastMobID => Saves the Mob ID of the last quest that made QuestHuntCompleted become true
$.QuestHuntCompletedLastListIndex => Saves the list index in condition of the last quest that made QuestHuntCompleted become true

QuestHuntOngoing
  • Description: Checks if the player has one of the given quests active, and this quest has a hunt mission which has not been completed yet, uses quest ID and Mob ID (use command 'quest list' to see ID).
Syntax:
QuestHuntOngoing <comma separated list of pairs of quests ID and Mob ID>
Quest ID and/or Mob ID can be variables
Example:
QuestHuntOngoing 7122 1002, 7127 1004
Set variables:
$.QuestHuntOngoingLastQuestID => Saves the Quest ID of the last quest that made QuestHuntOngoing become true
$.QuestHuntOngoingLastMobID => Saves the Mob ID of the last quest that made QuestHuntOngoing become true
$.QuestHuntOngoingLastListIndex => Saves the list index in condition of the last quest that made QuestHuntOngoing become true

NoPlayerNear
  • Description: Checks if there are any players near, it's true when there's none.
Syntax:
NoPlayerNear 1
Example:
NoPlayerNear 1
Sets no variables.
NoPortalNear
  • Description: Checks if there are any portals near, it's true when there's none.
Syntax:
NoPortalNear 1
Example:
NoPortalNear 1
Sets no variables.
NoMobNear
  • Description: Checks if there are any mobs near, it's true when there's none.
Syntax:
NoMobNear 1
Example:
NoMobNear 1
Sets no variables.
NoNpcNear
  • Description: Checks if there are any npcs near, it's true when there's none.
Syntax:
NoNpcNear 1
Example:
NoNpcNear 1
Sets no variables.
PlayerNearCount
  • Description: Checks if the number of players near match the given math condition.
Syntax:
PlayerNearCount <Math condition operators>
Example:
PlayerNearCount > 5
Set variables:
$.PlayerNearCountLast => Saves the number of players that made PlayerNearCount become true

NpcNearCount
  • Description: Checks if the number of npcs near match the given math condition.
Syntax:
NpcNearCount <Math condition operators>
Example:
NpcNearCount > 5
Set variables:
$.NpcNearCountLast => Saves the number of npcs that made NpcNearCount become true

MobNearCount
  • Description: Checks if the number of mobs near match the given math condition.
Syntax:
MobNearCount <Math condition operators>
Example:
MobNearCount > 10
Set variables:
$.MobNearCountLast => Saves the number of mobs that made MobNearCount become true

PortalNearCount
  • Description: Checks if the number of portals near match the given math condition.
Syntax:
PortalNearCount <Math condition operators>
Example:
PortalNearCount > 5
Set variables:
$.PortalNearCountLast => Saves the number of portals that made PortalNearCount become true


Event

  • Event conditions don't have a defined status of true or false, they are only checked once an event happens.
  • When this event happens, the condition is checked, if it is true, and all the state conditions are also true, the automacro activates.
  • You can only have one event condition in each automacro.
PubMsg
  • Description: Is checked on public messages, is true when the message matches the given regex.
Syntax:
PubMsg <Regex>
Example:
PubMsg /(buff|bless)/
Set variables:
$.PubMsgLastName => Saves the name of the player which message activated PubMsg
$.PubMsgLastMsg => Saves the message which activated PubMsg

PubMsgDist
  • Description: Is checked on public messages, is true when the message matches the given regex and the distance match the given condition.
Syntax:
PubMsgDist <Regex> <Math condition operators>
Example:
PubMsgDist /(buff|bless)/ < 5
Set variables:
$.PubMsgDistLastName => Saves the name of the player which message activated PubMsgDist
$.PubMsgDistLastMsg => Saves the message which activated PubMsgDist
$.PubMsgDistLastPos => Saves the position of the player which message activated PubMsgDist
$.PubMsgDistLastDist => Saves the distance to the player which message activated PubMsgDist
$.PubMsgDistLastID => Saves the openkore ID of the player which message activated PubMsgDist

PubMsgName
  • Description: Is checked on public messages, is true when the message matches the given regex and the name of the player which sent it also matches it's given regex.
Syntax:
PubMsgName <Regex> <Regex>
The first regex is for the message, the second one is for the player name
Example:
PubMsgName /(buff|bless)/ /Player to buff/
PubMsgName /stop/ /GM/
Set variables:
$.PubMsgNameLastName => Saves the name of the player which message activated PubMsgName
$.PubMsgNameLastMsg => Saves the message which activated PubMsgName

PubMsgNameDist
  • Description: Is checked on public messages, is true when the message matches the given regex and the name of the player which sent it also matches it's given regex and the distance matches the condition.
Syntax:
PubMsgNameDist <Regex> <Regex> <Math condition operators>
The first regex is for the message, the second one is for the player name
Example:
PubMsgNameDist /(buff|bless)/ /Player to buff/ < 3
PubMsgNameDist /stop/ /GM/ >= 4
Set variables:
$.PubMsgNameDistLastName => Saves the name of the player which message activated PubMsgNameDist
$.PubMsgNameDistLastMsg => Saves the message which activated PubMsgNameDist
$.PubMsgNameDistLastPos => Saves the position of the player which message activated PubMsgNameDist
$.PubMsgNameDistLastDist => Saves the distance to the player which message activated PubMsgNameDist
$.PubMsgNameDistLastID => Saves the openkore ID of the player which message activated PubMsgNameDist

PrivMsg
  • Description: Is checked on private messages, is true when the message matches the given regex.
Syntax:
PrivMsg <Regex>
Example:
PrivMsg /(buff|bless)/
Set variables:
$.PrivMsgLastName => Saves the name of the player which message activated PrivMsg
$.PrivMsgLastMsg => Saves the message which activated PrivMsg

PrivMsgDist
  • Description: Is checked on private messages, is true when the message matches the given regex and the distance match the given condition.
Syntax:
PrivMsgDist <Regex> <Math condition operators>
Example:
PrivMsgDist /(buff|bless)/ < 5
Set variables:
$.PrivMsgDistLastName => Saves the name of the player which message activated PrivMsgDist
$.PrivMsgDistLastMsg => Saves the message which activated PrivMsgDist
$.PrivMsgDistLastPos => Saves the position of the player which message activated PrivMsgDist
$.PrivMsgDistLastDist => Saves the distance to the player which message activated PrivMsgDist
$.PrivMsgDistLastID => Saves the openkore ID of the player which message activated PrivMsgDist

PrivMsgName
  • Description: Is checked on private messages, is true when the message matches the given regex and the name of the player which sent it also matches it's given regex.
Syntax:
PrivMsgName <Regex> <Regex>
The first regex is for the message, the second one is for the player name
Example:
PrivMsgName /(buff|bless)/ /Player to buff/
PrivMsgName /stop/ /GM/
Set variables:
$.PrivMsgNameLastName => Saves the name of the player which message activated PrivMsgName
$.PrivMsgNameLastMsg => Saves the message which activated PrivMsgName

PrivMsgNameDist
  • Description: Is checked on private messages, is true when the message matches the given regex and the name of the player which sent it also matches it's given regex and the distance matches the condition.
Syntax:
PrivMsgNameDist <Regex> <Regex> <Math condition operators>
The first regex is for the message, the second one is for the player name
Example:
PrivMsgNameDist /(buff|bless)/ /Player to buff/ < 3
PrivMsgNameDist /stop/ /GM/ >= 4
Set variables:
$.PrivMsgNameDistLastName => Saves the name of the player which message activated PrivMsgNameDist
$.PrivMsgNameDistLastMsg => Saves the message which activated PrivMsgNameDist
$.PrivMsgNameDistLastPos => Saves the position of the player which message activated PrivMsgNameDist
$.PrivMsgNameDistLastDist => Saves the distance to the player which message activated PrivMsgNameDist
$.PrivMsgNameDistLastID => Saves the openkore ID of the player which message activated PrivMsgNameDist

PartyMsg
  • Description: Is checked on party messages, is true when the message matches the given regex.
Syntax:
PartyMsg <Regex>
Example:
PartyMsg /(buff|bless)/
Set variables:
$.PartyMsgLastName => Saves the name of the player which message activated PartyMsg
$.PartyMsgLastMsg => Saves the message which activated PartyMsg

PartyMsgDist
  • Description: Is checked on party messages, is true when the message matches the given regex and the distance match the given condition.
Syntax:
PartyMsgDist <Regex> <Math condition operators>
Example:
PartyMsgDist /(buff|bless)/ < 5
Set variables:
$.PartyMsgDistLastName => Saves the name of the player which message activated PartyMsgDist
$.PartyMsgDistLastMsg => Saves the message which activated PartyMsgDist
$.PartyMsgDistLastPos => Saves the position of the player which message activated PartyMsgDist
$.PartyMsgDistLastDist => Saves the distance to the player which message activated PartyMsgDist
$.PartyMsgDistLastID => Saves the openkore ID of the player which message activated PartyMsgDist

PartyMsgName
  • Description: Is checked on party messages, is true when the message matches the given regex and the name of the player which sent it also matches it's given regex.
Syntax:
PartyMsgName <Regex> <Regex>
The first regex is for the message, the second one is for the player name
Example:
PartyMsgName /(buff|bless)/ /Player to buff/
PartyMsgName /stop/ /GM/
Set variables:
$.PartyMsgNameLastName => Saves the name of the player which message activated PartyMsgName
$.PartyMsgNameLastMsg => Saves the message which activated PartyMsgName

PartyMsgNameDist
  • Description: Is checked on party messages, is true when the message matches the given regex and the name of the player which sent it also matches it's given regex and the distance matches the condition.
Syntax:
PartyMsgNameDist <Regex> <Regex> <Math condition operators>
The first regex is for the message, the second one is for the player name
Example:
PartyMsgNameDist /(buff|bless)/ /Player to buff/ < 3
PartyMsgNameDist /stop/ /GM/ >= 4
Set variables:
$.PartyMsgNameDistLastName => Saves the name of the player which message activated PartyMsgNameDist
$.PartyMsgNameDistLastMsg => Saves the message which activated PartyMsgNameDist
$.PartyMsgNameDistLastPos => Saves the position of the player which message activated PartyMsgNameDist
$.PartyMsgNameDistLastDist => Saves the distance to the player which message activated PartyMsgNameDist
$.PartyMsgNameDistLastID => Saves the openkore ID of the player which message activated PartyMsgNameDist

GuildMsg
  • Description: Is checked on guild messages, is true when the message matches the given regex.
Syntax:
GuildMsg <Regex>
Example:
GuildMsg /(buff|bless)/
Set variables:
$.GuildMsgLastName => Saves the name of the player which message activated GuildMsg
$.GuildMsgLastMsg => Saves the message which activated GuildMsg

GuildMsgDist
  • Description: Is checked on guild messages, is true when the message matches the given regex and the distance match the given condition.
Syntax:
GuildMsgDist <Regex> <Math condition operators>
Example:
GuildMsgDist /(buff|bless)/ < 5
Set variables:
$.GuildMsgDistLastName => Saves the name of the player which message activated GuildMsgDist
$.GuildMsgDistLastMsg => Saves the message which activated GuildMsgDist
$.GuildMsgDistLastPos => Saves the position of the player which message activated GuildMsgDist
$.GuildMsgDistLastDist => Saves the distance to the player which message activated GuildMsgDist
$.GuildMsgDistLastID => Saves the openkore ID of the player which message activated GuildMsgDist

GuildMsgName
  • Description: Is checked on guild messages, is true when the message matches the given regex and the name of the player which sent it also matches it's given regex.
Syntax:
GuildMsgName <Regex> <Regex>
The first regex is for the message, the second one is for the player name
Example:
GuildMsgName /(buff|bless)/ /Player to buff/
GuildMsgName /stop/ /GM/
Set variables:
$.GuildMsgNameLastName => Saves the name of the player which message activated GuildMsgName
$.GuildMsgNameLastMsg => Saves the message which activated GuildMsgName

GuildMsgNameDist
  • Description: Is checked on guild messages, is true when the message matches the given regex and the name of the player which sent it also matches it's given regex and the distance matches the condition.
Syntax:
GuildMsgNameDist <Regex> <Regex> <Math condition operators>
The first regex is for the message, the second one is for the player name
Example:
GuildMsgNameDist /(buff|bless)/ /Player to buff/ < 3
GuildMsgNameDist /stop/ /GM/ >= 4
Set variables:
$.GuildMsgNameDistLastName => Saves the name of the player which message activated GuildMsgNameDist
$.GuildMsgNameDistLastMsg => Saves the message which activated GuildMsgNameDist
$.GuildMsgNameDistLastPos => Saves the position of the player which message activated GuildMsgNameDist
$.GuildMsgNameDistLastDist => Saves the distance to the player which message activated GuildMsgNameDist
$.GuildMsgNameDistLastID => Saves the openkore ID of the player which message activated GuildMsgNameDist

NpcMsg
  • Description: Is checked on npc conversation messages, is true when the message matches the given regex.
Syntax:
NpcMsg <Regex>
Example:
NpcMsg /your return point was saved/
Set variables:
$.NpcMsgLastName => Saves the name of the npc which message activated NpcMsg
$.NpcMsgLastMsg => Saves the message which activated NpcMsg

NpcMsgDist
  • Description: Is checked on npc conversation messages, is true when the message matches the given regex and the distance match the given condition.
Syntax:
NpcMsgDist <Regex> <Math condition operators>
Example:
NpcMsgDist /please come near to me/ > 5
Set variables:
$.NpcMsgDistLastName => Saves the name of the npc which message activated NpcMsgDist
$.NpcMsgDistLastMsg => Saves the message which activated NpcMsgDist
$.NpcMsgDistLastPos => Saves the position of the npc which message activated NpcMsgDist
$.NpcMsgDistLastDist => Saves the distance to the npc which message activated NpcMsgDist
$.NpcMsgDistLastID => Saves the openkore ID of the npc which message activated NpcMsgDist

NpcMsgName
  • Description: Is checked on npc conversation messages, is true when the message matches the given regex and the name of the npc which sent it also matches it's given regex.
Syntax:
NpcMsgName <Regex> <Regex>
The first regex is for the message, the second one is for the npc name
Example:
NpcMsgName /You don't have zeny/ /kafra/
Set variables:
$.NpcMsgNameLastName => Saves the name of the npc which message activated NpcMsgName
$.NpcMsgNameLastMsg => Saves the message which activated NpcMsgName

NpcMsgNameDist
  • Description: Is checked on npc conversation messages, is true when the message matches the given regex and the name of the npc which sent it also matches it's given regex and the distance matches the condition.
Syntax:
NpcMsgNameDist <Regex> <Regex> <Math condition operators>
The first regex is for the message, the second one is for the npc name
Example:
NpcMsgNameDist /You need to be closer to punch me/ /punchable npc/ > 5
Set variables:
$.NpcMsgNameDistLastName => Saves the name of the npc which message activated NpcMsgNameDist
$.NpcMsgNameDistLastMsg => Saves the message which activated NpcMsgNameDist
$.NpcMsgNameDistLastPos => Saves the position of the npc which message activated NpcMsgNameDist
$.NpcMsgNameDistLastDist => Saves the distance to the npc which message activated NpcMsgNameDist
$.NpcMsgNameDistLastID => Saves the openkore ID of the npc which message activated NpcMsgNameDist

LocalMsg
  • Description: Is checked on local broadcast messages, is true when the message matches the given regex.
Syntax:
LocalMsg <Regex>
Example:
LocalMsg /airship is arriving/
Set variables:
$.LocalMsgLastMsg => Saves the message which activated LocalMsg

BusMsg
  • Description: Is checked on bus system messages, is true when the message matches the given regex.
Syntax:
BusMsg <Regex>
Example:
BusMsg /gm near/
Set variables:
$.BusMsgLastMsg => Saves the message which activated BusMsg

MapLoaded
  • Description: Is checked everytime a map change event occur (teleport, map changes), is true if the current map match one of the given ones.
Syntax:
MapLoaded <comma separated list of maps>
Map can be a variable.
Example:
MapLoaded prontera, geffen, gef_fild10
Set variables:
$.MapLoadedLast => Saves the last map that made MapLoaded become true

OnCharLogIn
  • Description: Is always true, activates everytime the character logs into the game.
Syntax:
OnCharLogIn 1
Example:
OnCharLogIn 1
Sets no variables
ZenyChanged
  • Description: Is checked everytime the amount of zeny changes, is true if the math condition is true.
  • Supports percentages. (based on total zeny before change and change amount)
Syntax:
ZennyChanged <Math condition operators>
Example:
ZennyChanged > 10%
ZennyChanged >= 1000
Set variables:
$.ZennyChangedLastChange => Saves the amount of zenny changed that made ZennyChanged activate
$.ZennyChangedLastZennyAfter => Saves the amount of zenny left after the change that made ZennyChanged activate

SimpleHookEvent
  • Description: Is checked every time the hook you set, is triggered.
Syntax:
SimpleHookEvent <hook name>
Example:
SimpleHookEvent target_died
Set all variables the hook have as:
$.SimpleHookEventLast <Capitalized variable name>


Example 1:
Plugins::callHook("target_died", {monster => $monsters_old{$ID}});

SimpleHookEvent target_died
$.SimpleHookEventLastMonster => monster ID in target_died hook
Example 2:
Plugins::callHook ('open_shop', {title => $shop{title}, items => \@items});

SimpleHookEvent open_shop
$.SimpleHookEventLastTitle
@.SimpleHookEventLastItems
$.SimpleHookEventLastItems[0]
Example 3:
my %hook_args = (
 serverIndex => $index,
 itemID => $itemID,
);
Plugins::callHook('packet_useitem', \%hook_args);

SimpleHookEvent packet_useitem
%.SimpleHookEventLastHook_args
$.SimpleHookEventLastHook_args{serverIndex}

Extras

Math condition operators

(<|<=|=|==|!=|!|>=|>|)\s*($number_qr%?|$general_wider_variable_qr)(?:\s*\.\.\s*($number_qr%?|$general_wider_variable_qr))

Operator Description Example
< <value> lower than <value> < 50
> <value> higher than <value> > 20
<= <value> lower or equal to <value> <= 10
>= <value> higher or equal to <value> >= 25
= <value> | == <value> | <value> equal to <value> = 150 | == 150 | 150
!= <value> | ! <value> not equal to <value> ! 1000 | != 1000
<value1>..<value2> between <value1> and <value2> 20..80
  • Note: <value> can be a number or a variable.

Examples:

Math_condition >= 50 # Only true if higher or equal to 50
Math_condition < $variable # Only true if lower than $variable value
  • Note2: <value> can be a percentage (even if it is a variable).

Examples:

Math_condition <= 10% # Only true if lower or equal to 10%
Math_condition != $variable # $variable value can be something like '50%', in which case it would only be true if different than 50%


Regex

To learn about regex plese refer to this link: regexp tutorial
Note: Regex in conditions support all types of variables

Perl Subroutines

eventMacro plugin support Perl subroutines in macros. You can now create any simple Perl function without limitations from the eval command.

Example No.1 - how to create a Perl Subroutine function in Macro

macro sub {
    $list = Orange, Milk, Soya, Peach
    if (existsInList("$list", "PeAch")) goto ok 
    log Not Match!!!; stop
    :ok
    log Match!!!
    $x = &eval(existsInList("$list", "PeAch"))
    log \$x = $x   # $x here is 1
}
sub existsInList {
    my ($list, $val) = @_;
    return 0 if ($val eq "");
    my @array = split / *, */, $list;
    $val = lc($val);
    foreach (@array) {
        s/^\s+//;
        s/\s+$//;
        s/\s+/ /g;
        next if $_ eq "";
        return 1 if lc eq $val;
    }
    return 0;
}


Example No.2 - how to create a re-writable file function using Perl Subroutine in Macro

automacro confHP1 {
    CurrentHP > 85%
    exclusive 1
    run-once 1
    call {
        $setting = Demon Pungus #becareful on your case, its case sensitive
        $attack = 1
        $teleport = 0
        $telesearch = 1
        call HP
    }
}

automacro confHP2 {
    CurrentHP < 75%
    exclusive 1
    run-once 1
    call {
        $setting = Demon Pungus #becareful on your case, its case sensitive
        $attack = 1
        $teleport = 2
        $telesearch = 1
        call HP
    }
}

macro HP {
    #Getting the value of the $setting monster name Ex: $setting $exist1 $exist2 $exist3
    $exist1 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{attack_auto}:"None")
    $exist2 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{teleport_auto}:"None")
    $exist3 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{teleport_search}:"None")
    log Old Values are $setting $exist1 $exist2 $exist3
    log Changing the values to $setting $attack $teleport $telesearch
    do eval Misc::mon_control("$::Macro::Data::varStack{setting}")->{attack_auto} = $attack; Misc::mon_control("$::Macro::Data::varStack{setting}")->{teleport_auto} = $teleport; Misc::mon_control("$::Macro::Data::varStack{setting}")->{teleport_search} = $telesearch
    log Writting mon_control.txt with new values
    rewrite()  # see the sub-routine function below
    log Reloading mon_control.txt
    do reload mon_control
    $exist1 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{attack_auto}:"None")
    $exist2 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{teleport_auto}:"None")
    $exist3 = &eval (defined Misc::mon_control("$setting")?Misc::mon_control("$setting")->{teleport_search}:"None")
    log New mon_control.txt Setting: $setting $exist1 $exist2 $exist3
    log Macro done
    #if $teleport = 0 ; means the Higher automacro HP is currently triggered
    #if $teleport = 2 ; means the Lower automacro HP is currently triggered
    if ($teleport < 2) goto releaseHighHp
    :releaseLowHp
        release confHP1
        stop
    :releaseHighHp
        release confHP2
        stop
}

sub rewrite {
    my $monster = Misc::mon_control("$::Macro::Data::varStack{setting}");
    my @lines = ();
    if (open(FILE, "<:utf8", Settings::getControlFilename("mon_control.txt"))) {
        while (<FILE>) {
            s/\x{FEFF}//g; chomp;
            if (/^#/ || /^\n/ || /^\r/) {
                push @lines,$_;
                next
            }
            /^(\d+|([a-zA-Z' ]+)*) -?\d/;
            if ("$::Macro::Data::varStack{setting}" eq $1 && defined $monster) {
                $_ = $1; s/\s+$//;
                push(@lines, ($_ . " $monster->{attack_auto} $monster->{teleport_auto} $monster->{teleport_search} $monster->{attack_lvl} $monster->{attack_jlvl} $monster->{attack_hp} $monster->{attack_sp} $monster->{weight}"));
            } else {
                push(@lines, $_);
            }
        }
        close FILE
    }
    open(FILE, ">:utf8", Settings::getControlFilename("mon_control.txt"));
    print FILE join "\n", @lines;
    close FILE;
}

Comments

The macro files allow comments, i.e. lines that are ignored by the eventMacro plugin.

  • Lines starting with a # will be treated as a comment.
  • Everything after a space and followed by a # will also be ignored.
macro happy {
    #this is a comment line
    log I'm Happy # this is also a comment
}

Will print:

[eventmacro message] I'm Happy

Examples with Explanations

I assume you already know how to use Console Commands and understand how they work. If not, before going further, read through all Console Commands and try out ones like a, ai, move, cart get, storage add, talk, deal, take, direction commands, sl, sm, relog, pm and others.

Keep another page with this manual open for cross reference.


Okay, so there are 2 types of blocks

  1. automacros – these trigger automatically
  2. macros – these do not trigger automatically but need to be called manually or by an automacro


Automacros

Automacros automatically trigger when certain conditions are met, just like how blocks in config.txt trigger depending on the conditions set in them.

The point of automacros is that you use them to check for conditions. When the condition is fulfilled, you can either respond to it in the automacro or call a macro to do it. The format for automacro is...

automacro <name> {
        condition 1
        condition 2
        …...
        …...
        call {
                command 1
                command 2
                …..
                …..
        }
        timeout <n seconds> #(if necessary)
}


For example, suppose you're playing manually but your slave priest is on Kore, and you want it to warn you if it's running out of sp, you can use an automacro like this....

automacro sp {
   CurrentSP < 200
   timeout 10
   call {
      do c sp low
   }
}


Taking it line by line,

  1. automacro sp { - you need to put automacro to tell kore that its an automacro. Then you put the name of the macro, in this case its “sp”. Then you need to put an opening bracket “{“ which tells Kore that the automacro's code begins there.
  2. CurrentSP < 200 – After the “{“, you put the conditions on successive lines. Here, there is only one condition and I think its clear that the condition is that sp should be below 200.
  3. timeout 10 – This isn't a condition or a command, it works the same way it works in normal Kore blocks, so this automacro cannot trigger within 10 seconds of it already having been triggered. I ALWAYS put timeouts, so even if my conditions are faulty, the automacro doesn't spam and mess up whatever my bot is doing. Otherwise if your automacro is messed up then you could die or something, so its better to put an appropriate timeout.
  4. call { – The word “call” tells Kore that now you're going to be putting commands, not conditions. The opening bracket “{“ tells Kore that the commands will start now. These commands are the ones that will get carried out when the conditions are met, here when sp goes below 200.
  5. do c sp low – “do” tells Kore that this is a command, something to be done. After “do”, just leave a space and type in the console command you want to execute exactly the way you do in the Kore console.
  6. } – This closing bracket “}” tells Kore that the commands have ended.
  7. } – This closing bracket “}” tells Kore that your automacro code has ended.

So basically whenever, the bot's sp goes below 200, it says in public chat “sp low”. This also has the advantage of making your bot not look like a bot =p.


Here's another macro which illustrates how you can use macros to handle weird situations which Kore is not equipped to deal with. When fighting against metalings, they often strip you and then your oh-so-smart bot punches! To get around this, put the weapon you use in default auto equip and use this macro.

automacro strip {
   StatusActiveHandle EFST_NOEQUIPWEAPON
   timeout 10
   call {
      do tele
      do relog 10
   }
}


Taking it line by line....

  1. automacro strip { - Tell Kore this is an automacro, and it's name is "strip". The '{' tells Kore the code of the automacro starts here.
  2. StatusActiveHandle EFST_NOEQUIPWEAPON - The only condition in this macro. This checks your list of statuses for the status handle "EFST_NOEQUIPWEAPON". Thus, when you are stripped by a Metaling, you get the "EFST_NOEQUIPWEAPON" status and this condition will be fulfilled.
  3. timeout 10 - Ensures automacro is not spammed, and 10 seconds is enough time to execute the automacro. So after 10 seconds, if for some reason you are still stripped, this automacro will trigger again. However, if you re-login and are stripped within 10 seconds, then macro will not trigger again untill the 10 seconds are up.
  4. call { - The word "call" and "{" tells Kore that the commands to be executed start after the '{'
  5. do tele - "do" tells Kore that what comes after is a console command to be carried out. Here, the command is "tele" so you teleport away from the Metaling, so that in case you lag or something, you aren't killed while executing the next instruction which is.....
  6. do relog 10 - Tells Kore to relogin in 10 seconds, because when you login again, your "strip weapon" status is cleared.
  7. } - The closing bracket '}' tells Kore the commands have ended.
  8. } - The closing bracket '}' tells Kore the macro code has ended.

Summarising, on being stripped, you teleport away from the monster and then relogin, with a timeout of 10 seconds to ensure that the automacro is not spammed. Since the weapon you're using is filled in the default weapon option, after re-logging in, Kore will automatically re-equip that weapon.


Let's try a more complicated macro. If you have a priest, you would want it to warp back to its lockmap or the nearest warp-able map near its lockmap. This macro does it. From the savemap, the bot takes the same route to the lockmap each time. So in the first map outside the town, just set it to move to a designated tile, and cast warp on a nearby tile, and then move to that tile. You will need delays to allow the spell to be cast and commands to be completed.

automacro warp {
    InMap gef_fild07
    InInventory "Blue Gemstone" > 0
    timeout 20
    call {
        do ai manual
        pause 1
        do move 319 187
        do sl 27 316 188
        pause 2
        do warp 1
        pause 1
        do move 316 188
        do ai on
    }
}


Taking it line by line,

  1. automacro warp { - As explained, the automacro's name is warp, and “{“ indicates that the automacro begins.
  2. InMap get_fild07 - The first condition, the automacro will only trigger if the map is gef_fild07.
  3. InInventory “Blue Gemstone” > 0 - Second condition, ensures there is atleast one blue gemstone in the inventory so that warp portal can be cast. Obviously you need a getAuto in config.txt for the gemstones.
  4. timeout 20 - Ensures that the bot does not spam the automacro. The timeout should be large enough to allow the completion of the automacro, so that the automacro does not trigger again while it is in execution.
  5. call { - Tells Kore that the commands start here.
  6. do ai manual - Frequently, I use this command in the more complicated and longer macros, so that Kore doesn't get diverted into doing something else while your macro is running, for example, attacking a monster or gathering up an item. In this case I'm using it so that the bot doesn't continue walking.
  7. pause 1 - Inserts a delay of 1 second before the next command is carried out, VERY IMPORTANT. If you don't use delays then Kore can and will miss steps in the macro and the result is a mess.
  8. do move 319 187 - The “move” console command is used to move your bot to a set location.
  9. do sl 27 316 188 - The “sl” console command is used to make your priest cast warp portal on a convenient spot near your location, in this case (316,188).
  10. pause 2 - Very Important. A delay of 2 seconds is put, allowing enough time to cast warp portal. If you priest has low dex, this delay should be increased.
  11. do warp 1 - Console command “warp” is used to select memo location 1.
  12. pause 1 - 1 second delay to allow the portal to form.
  13. do move 316 188 - Move to the portal and Voila! You have been warped to the map.
  14. do ai on - You set ai to manual at the beginning of this macro, so now you need to turn it back on.
  15. } - Closing bracket indicates end of commands.
  16. } - Closing bracket indicates end of automacro code.

Note the use of appropriate delays and timeouts in this automacro.


The EventMacro plugin also has many useful built-in variables which give you your position for example. It's all listed in the eventMacro manual. I just want to show how to extract your position from these variables.

$.pos gives you your position. Now to get your x and y coordinates the code is,

  $px = &arg ("$.pos", 1)
  $py = &arg ("$.pos", 2)

Here, the x coordinate is the 1st value in $.pos so we have a '1'. Similarly, the y coordinate is the second value in $.pos so we have a '2'.

If you have a “MobNear” condition in your automacro, $.MobNearLastPos gives the position of that monster. To extract the x and y coordinates the code is,

  $mx = &arg ("$.MobNearLastPos", 1)
  $my = &arg ("$.MobNearLastPos", 2)

"run-once"

Frequently, the run-once condition is used instead of a timeout. It allows the automacro to run only once so that the automacro isn't spammed. To get the automacro to run again, a release command needs to be executed. However, due to a rogue situation that the macro hangs and the release macro isn't executed, your automacro is effectively stuck. To get around this, use a timeout instead of using run-once.


How to write a macro

Now that you have some idea of what a macro is, try writing one

  • Figure out under exactly what conditions you want your automacro to trigger
  • Logically think out the steps your bot needs to perform in the automacro. Go step by step over this carefully.
  • Ensure you have inserted appropriate pauses between the steps.
  • Ensure you have a timeout or a run-once in your macro to prevent spamming of it.
  • Now put the code in eventMacros.txt and start the bot or reload eventMacros.txt. If all is fine you won't get any error messages. But if there is a problem in the syntax, say you missed out a “}”, then you will get an error message and the macro won't work. Figure out what the error is, correct it, and reload eventMacros.txt again to check if you corrected it properly or not.

Collected Macros

I would like to share some useful macros, hopefully not angering anyone here.

Identify with Magnifier

You got unidentified Items in your inventory and want to identify them using magnifiers? Use "eventMacro id" on console until all items are identified. You don't have to type anything else, the macro will identify the first item found, after that the second and so on.

macro id {
    $id = &inventory(Magnifier)
    do is $id
    pause 1
    do identify 0
}

Automatically refine Rough Stones (Ori / Elu)

This macro, once called, will automatically walk to the prontera forge and refine Rough Ori / Elu as long as there are more than 5 in your inventory. I did not find something like that yet, please post everything (better) I may have missed.

Just fire eventMacro ref to start. To stop manually, type eventMacro stop.

macro ref {
    do move prt_in 59 60
    call ref-while
}

macro ref-while {
    log start refining with
    $ori = &invamount(Rough Oridecon)
    $elu =  &invamount(Rough Elunium)
    log I have $ori Rough Oridecons
    log I have $elu Rough Eluniums
    while (&invamount(Rough Oridecon) > 4) {
        do talk 0
        pause 0.8
        do talk resp 0
        call ref-while
    }
    while (&inventory(Rough Elunium) > 4) {
        do talk 0
        pause 0.8
        do talk resp 1
        call ref-while
    }
    stop
}

FAQ

I get disconnected from map server when running a macro!
The commands are sent too fast. Increase macro_delay or add pause lines between your do commands


I'm getting Malformed UTF-8 character (fatal), what is this?
This error happens when your eventMacros.txt is not saved in UTF-8 encoding.
To solve it, open your eventMacros.txt and if you're using Notepad, when you are going to save, change Encoding to UTF-8. (If that does not help - do not use Notepad.)
If you're using Notepad++ or other text editor, go to Format > UTF-8 (without BOM) and save.

Author

EventMacro was written by Henrybk.
EventMacro was based on macro plugin which was first written by arachno has various contributors like ezza, daigaku, keplerbr, eternalhavest and technologyguild.
EventMacro was beta tested by emjustin.
Some of the most important ideas and functions were developed by allanon.