Page 1 of 2

Macro Mods

Posted: 06 Oct 2008, 06:43
by Jack The Ripper
Macros are so flexible, its almost like re-programing the bot to perform [awesome]! tasks, however, it misses one "key word', that kinda bothers a lot in my refine macro

Conclusion: it would be great to add a key word that returns current weight and max weight

Mods to be committed to macro SVN

Posted: 06 Oct 2008, 07:08
by Technology
It would be nice if someone that has expertise in the macro section (Ezza? ;) ) would commit all usefull macro mods.
other modifications that could be committed to extend macro functionality:
You could use the info below to complete the macro manual.
However please could the authors of the mods double check if the descriptions here match their purpose first?
- Special Variables: $.weight, $.maxweight
http://bibian.ath.cx/openkore/viewtopic.php?t=38257

- Command: lock (<name> | all)
A simple way to lock all automacro's with just 1 command.
- Special keyword: @venderitem(<name>)
Looks for an item in a players shop and returns ID or -1 if the item was not found.
- Special keyword: @venderprice(<indexID>)
Looks for an item in a players shop and returns its price.
original:
http://forums.openkore.com/viewtopic.php?f=32&t=858
improved:
http://forums.openkore.com/viewtopic.ph ... d=a#p13300

- Macro System: A Direct Macro Call in Multiple If Statement
http://forums.openkore.com/viewtopic.php?f=32&t=966

- Automacro Syntax: localtime <condition> <time>
http://forums.openkore.com/viewtopic.php?f=32&t=2444

- Special Variables: $.caster, $.casterName, $.casterID, $.casterLoc, $.casterSkill, $.casterTarget, $.casterDist
- Automacro Syntax: spell "<spell name>"

http://forums.openkore.com/viewtopic.php?f=32&t=594

- Automacro Syntax: location [not] (<mapname>|<$variable>) [<x1> <y1> [<x2> <y2>]] [, ...]
http://forums.openkore.com/viewtopic.php?f=32&t=2997

- Automacro Syntax: (<ItemName>|<$variable>) <condition> (<amount>|<$variable>)
- Automacro Syntax: weight <condition> (<amount>|<$variable>)[%]
- Automacro Syntax: cartweight <condition> (<amount>|<$variable>)[%]
- Automacro Syntax: hp <condition> (<amount>|<$variable>)[%]
- Automacro Syntax: sp <condition> (<amount>|<$variable>)[%]
- Automacro Syntax: spirit <condition> (<amount>|<$variable>)
- Automacro Syntax: soldout <condition> (<amount>|<$variable>)
- Automacro Syntax: zenny <condition> (<amount>|<$variable>)
- Automacro Syntax: job <condition> (<amount>|<$variable>)
- Automacro Syntax: base <condition> (<amount>|<$variable>)
- Automacro Syntax: agressives <condition> (<amount>|<$variable>)

http://forums.openkore.com/viewtopic.php?f=32&t=1608

So move this to Commit Queue?

[EDIT]
Some mods indeed need some extra care.
So what about having a stable version and branching off a tester version,
so ezza's stuff actually will get tested and she will be able to debug where possible?

While trying to attach a .patch file you get this message:
The extension patch is not allowed.
Could anyone enabled this please, as i see no reason why it should be not enabled?
anyways here it is:

Code: Select all

Index: Automacro.pm
===================================================================
--- Automacro.pm	(revision 6572)
+++ Automacro.pm	(working copy)
@@ -343,6 +343,12 @@
 
 # locks an automacro ##################
 sub lockAM {
+	if ($_[0] eq 'all') {
+		foreach (keys %automacro) {
+			$automacro{$_}->{disabled} = 1
+		}
+		return 1
+	}
 	if (defined $automacro{$_[0]}) {
 		$automacro{$_[0]}->{disabled} = 1;
 		return 1

Re: [Macro] New Key word

Posted: 06 Oct 2008, 17:13
by Jack The Ripper
see, someone agrees with me :D :D :D

Re: [Macro] New Key word

Posted: 07 Oct 2008, 13:26
by kLabMouse
Current Mod's commit status:

http://forums.openkore.com/viewtopic.php?f=32&t=966 Logic broken. Need to final state before committing.
http://forums.openkore.com/viewtopic.php?f=32&t=594 Not Tested Well. Need to final state before committing.
http://forums.openkore.com/viewtopic.php?f=32&t=1608 Not Tested Well. Need to final state before committing.
http://forums.openkore.com/viewtopic.php?f=32&t=2997 Need to be backward compatible.

Commited:
Command: lock (<name> | all)
Special Variables: $.weight, $.maxweight
Special keyword: @venderitem(<name>)
Special keyword: @venderprice(<name>)

Re: Macro Mods

Posted: 08 Oct 2008, 22:26
by ezza
Actually I'm very honoured seeing some1 is willing to bring all the mods that I've made to this level ( :o wow... kLabMouse checked my codes... yeehaaa!!!) even though the script drowned in failure. I dont mind at all... I'm just a script kiddy and my level to perl is 0 and you can see it very clear through the multiple-ifs mods that I've made. I'm sorry, thats all I can do right now for the multiple-ifs coz the unlimited multiple-ifs is a failure. Who am I to compete with the author of the perl language... thats the fact!!! So, to the perl expert out there... we hope that atleast you give us some guidance to make it a reality.


kLabMouse, what do you mean by:-
1. not tested well? - If you really mean a not well tested (I understand this as a failure) .. could you pls enlighten me abit how the codes should work. Thx.

2. backward compatible - I dont have any idea what is the meaning of this... I appreciate if you could explain a bit.

Re: Macro Mods

Posted: 13 Oct 2008, 07:19
by kLabMouse
ezza wrote:kLabMouse, what do you mean by:-
1. not tested well? - If you really mean a not well tested (I understand this as a failure) .. could you pls enlighten me abit how the codes should work. Thx.
Mean, that the special piece of code (for complex one), must have a so called "Test case", that test all it's abilities, and show, that all the code works perfect.
ezza wrote: 2. backward compatible - I don't have any idea what is the meaning of this... I appreciate if you could explain a bit.
If you change any of the existing code and functions. You must make them Compatible with old syntax, so users can use both old and new additions.

Re: Macro Mods

Posted: 13 Oct 2008, 22:45
by ezza
kLabMouse wrote:
ezza wrote:kLabMouse, what do you mean by:-
1. not tested well? - If you really mean a not well tested (I understand this as a failure) .. could you pls enlighten me abit how the codes should work. Thx.
Mean, that the special piece of code (for complex one), must have a so called "Test case", that test all it's abilities, and show, that all the code works perfect.
ezza wrote: 2. backward compatible - I don't have any idea what is the meaning of this... I appreciate if you could explain a bit.
If you change any of the existing code and functions. You must make them Compatible with old syntax, so users can use both old and new additions.

Ok, thx for the explainations.

Backward Compatible - I think the modified new codes will suits also the original syntax since this is just an issue of enabling the variable inside those syntaxes. If the user put a "$" infront of the syntax value, it will automatically try to match the existing var inside the varStack. If there is no "$" infront of it... the syntax will go/check normally. I've checked this several times and did not find any difficulties in triggering the syntax/conditions. I guaranty it will work.


As for the logic broken in the multiple-if's code. I admit that the codes is not perfect, since I'm not very good in regexp and perl (pls dont laugh). Ex: when there is & or | found at the place that its not should be.

Code: Select all

if (($name = Tarzan & Jane) && ($guild = ||||)) stop/goto/call
it should have written as...

Code: Select all

$n = Tarzan & Jane
$g = ||||
#then compare it with multiple-if
if (($name = $n) && ($guild = $g)) stop/goto/call
the multiple-if regexp failed if directly use any & and | in the value given , sorry :?

Re: Macro Mods

Posted: 14 Oct 2008, 07:24
by kLabMouse
ezza wrote:
Ok, thx for the explainations.

Backward Compatible - I think the modified new codes will suits also the original syntax since this is just an issue of enabling the variable inside those syntaxes. If the user put a "$" infront of the syntax value, it will automatically try to match the existing var inside the varStack. If there is no "$" infront of it... the syntax will go/check normally. I've checked this several times and did not find any difficulties in triggering the syntax/conditions. I guaranty it will work.
Well. We learn from our own bug's. So please. When you say, that one or more of the patches are in final state, tested well, etc. etc., I'll commit them to SVN.
Until then, i'll just patiently wait.

Re: Macro Mods

Posted: 14 Oct 2008, 18:23
by Technology
Hey guys,

Currently both @venderitem and @venderprice ONLY support stackable items,
since non-stackable items can occupy more than 1 index in the @::venderItemList.

I was thinking about a solution, that would allow more (full?) functionality and especially more control.
So i've changed the implementation of @venderprice like this:

- have an @venderItem aswell (note the uppercase letter, its not the same as @venderitem !):

Code: Select all

elsif ($kw eq 'venderItem') {$ret = join ',', getItemIDs($arg, \@::venderItemList)}
that will return a list of indexes (for non-stackables)

- have the @venderprice check on indexID like this: @venderprice(<indexID>)
(so we are certain that the right non-stackable item is checked.)

- have a new special keyword @venderamount(<indexID>)

Some other new special keywords:
- have a way to get the x'th item from a list: @listitem(<$listIndex>,<$list>)
- have a way to get list lenght: @listlenght(<$list>)
(for further control (incombination with WHILE) when doing more complex matters that involve price comparing)
(ex. of a list: $list = zero,one,two,bar,lol)
(ex. $listIndex for lol is 4)
Arrays anyone? ;)

I've made all this already, but need criticismn first.


A small macro example to show off this patches possebilities and provide a test case scenario:
(fill in venderName, itemName, itemMaxPrice, itemAmount to your desire, and see what it does)

Code: Select all

macro buyFromVender {
# CONSTANTS
	# TODO get $cvN from automacro
	$cvN = venderName

	# TODO get from text file and parse into lists
	$cbLstIs = itemName
	$cMaxP = itemMaxPrice
	# TODO remove when bought in that text file
	$cbMaxAmt = itemAmount

# CODE
# multi-buying non-stackable items
	$vLstLen = 1
	while ($vLstLen > 0) as mainloop

		$vID = @vender($cvN)
		if ($vID < 0) goto novender
		do vender $vID

	# check for items in our buylist in the vendlist
		$a = 0
		$bLstLen = @listlenght($cbLstIs)
		while ($a < $bLstLen) as checkbuylistloop

			# get item from our buylist
			$bLstI = @listitem($a, $cbLstIs)

		# compare buylist to items in the vender's vendlist
			# non-stackables can return a list
			$vLstInds = @venderItem($bLstI)
			if ($vLstInds <= 0) goto noitem
			$vLstLen = @listlenght($vLstInds)
			if ($vLstLen <= 0) goto noitem
			log found: $vLstLen item(s): $bLstI with index(es): $vLstInds

		# check the vender's list for the cheapest item (for non-stackables)
			$vMinP = -1
			$b = 0
			while ($b < $vLstLen) as pcheckloop
				$vLstInd = @listitem($b, $vLstInds)
				log checking vender's item with listindex: $vLstInd
				if ($b == 0) goto firstitem
				$vLstP = @venderprice($vLstInd)
				if ($vMinP <= $vLstP) goto tropexpensive
				:firstitem
				$minP = @venderprice($vLstInd)
				$vMinP = @venderprice($vLstInd)
				log found cheaper price: $vMinP zeny, for item: $bLstI

				:tropexpensive

				$b++
			end pcheckloop

			if ($vMinP > $maxP) goto tooexpensive

		# get the amount of stackables that can be bought in a bulk
			$bMaxAmt = 0
   			do eval $::Macro::Data::varStack{bMaxAmt} = int($.zeny / $vMinP)
			log Possible zenywise bulkbuyamount of stackables: $bMaxAmt
			if ($bMaxAmt == 0) goto notenoughzenny

		# check if the wanted itemAmount of non-stackable items is available, and buy 1
		# next will be bought in next checkbuylistloop
			# if more than 1 of the same items are in a shop, then the item is non-stackable for sure
			if ($vLstLen > 1) goto buyNstack

		# check if the wanted itemAmount of stackable items is available, if not buy all available
			log buying stackable item OR non-multiIndex non-stackable items
			$bMaxAmt = @venderamount($vLstInd)
			if ($bMaxAmt >= $cbMaxAmt) goto dobuy
			$cbMaxAmt = $bMaxAmt
			goto dobuy

			:buyNstack
			log buying non stackable item
			$cbMaxAmt = 1

			:dobuy
			$vLstLen--
			do vender $vID $vLstInd $cbMaxAmt
			do vender end

			$a++
		end checkbuylistloop

	end mainloop

	goto end

# MESSAGES
	:novender
	log no vender with name: $cvN
	goto end

	:noitem
	log vender: $cvN is not selling item: $bLstI
	goto end

	:tooexpensive
	log item: $bLstI costs more than: $cMaxP
	goto end

	:notenoughzenny
	log item: $bLstI costs more than your current zeny: $.zeny

	:end
	do vender end
	stop
}
Oh right, almost forgot, you also need the modifications in the macro plugin :P

Code: Select all

Index: Data.pm
===================================================================
--- Data.pm	(revision 6574)
+++ Data.pm	(working copy)
@@ -75,6 +75,7 @@
 	"vender"       . "|" .
 	"venderitem"   . "|" .
 	"venderprice"  . "|" .
+	"venderamount" . "|" .
 	"random"       . "|" .
 	"rand"         . "|" .
 	"[Ii]nvamount" . "|" .
@@ -83,7 +84,9 @@
 	"[Ss]toramount". "|" .
 	"config"       . "|" .
 	"eval"         . "|" .
-	"arg"
+	"arg"          . "|" .
+	"listitem"     . "|" .
+	"listlenght"
 ;
 
 1;
Index: Parser.pm
===================================================================
--- Parser.pm	(revision 6574)
+++ Parser.pm	(working copy)
@@ -13,8 +13,8 @@
 use Log qw(message warning error);
 use Macro::Data;
 use Macro::Utilities qw(refreshGlobal getnpcID getItemIDs getItemPrice getStorageIDs getInventoryIDs
-	getPlayerID getVenderID getRandom getRandomRange getInventoryAmount getCartAmount
-	getShopAmount getStorageAmount getConfig getWord q4rx);
+	getPlayerID getVenderID getRandom getRandomRange getInventoryAmount getCartAmount getShopAmount
+	getStorageAmount getVendAmount getConfig getWord q4rx getArgFromList getListLenght);
 
 our ($rev) = q$Revision$ =~ /(\d+)/;
 
@@ -191,7 +191,9 @@
 		elsif ($kw eq 'player')     {$ret = getPlayerID($arg)}
 		elsif ($kw eq 'vender')     {$ret = getVenderID($arg)}
 		elsif ($kw eq 'venderitem') {($ret) = getItemIDs($arg, \@::venderItemList)}
-		elsif ($kw eq 'venderprice'){($ret) = getItemPrice($arg, \@::venderItemList)}
+		elsif ($kw eq 'venderItem') {$ret = join ',', getItemIDs($arg, \@::venderItemList)}
+		elsif ($kw eq 'venderprice'){$ret = getItemPrice($arg, \@::venderItemList)}
+		elsif ($kw eq 'venderamount'){$ret = getVendAmount($arg, \@::venderItemList)}
 		elsif ($kw eq 'random')     {$ret = getRandom($arg)}
 		elsif ($kw eq 'rand')       {$ret = getRandomRange($arg)}
 		elsif ($kw eq 'invamount')  {$ret = getInventoryAmount($arg)}
@@ -201,6 +203,8 @@
 		elsif ($kw eq 'config')     {$ret = getConfig($arg)}
 		elsif ($kw eq 'arg')        {$ret = getWord($arg)}
 		elsif ($kw eq 'eval')       {$ret = eval($arg)}
+		elsif ($kw eq 'listitem')   {$ret = getArgFromList($arg)}
+		elsif ($kw eq 'listlenght') {$ret = getListLenght($arg)}
 		return unless defined $ret;
 		return $cmd if $ret eq '_%_';
 		$targ = q4rx $targ;
Index: Utilities.pm
===================================================================
--- Utilities.pm	(revision 6574)
+++ Utilities.pm	(working copy)
@@ -7,7 +7,8 @@
 our @ISA = qw(Exporter);
 our @EXPORT_OK = qw(ai_isIdle q4rx between cmpr match getArgs refreshGlobal getnpcID getPlayerID
 	getVenderID getItemIDs getItemPrice getInventoryIDs getStorageIDs getSoldOut getInventoryAmount
-	getCartAmount getShopAmount getStorageAmount getRandom getRandomRange getConfig getWord callMacro);
+	getCartAmount getShopAmount getStorageAmount getVendAmount getRandom getRandomRange getConfig
+	getWord callMacro getArgFromList getListLenght);
 
 use Utils;
 use Globals;
@@ -220,19 +221,18 @@
 	return @ids
 }
 
-# get item array price
+# get item price from its index
 # works with @venderprice
+# returns -1 if no shop is being visited
 sub getItemPrice {
-	my ($item, $pool) = (lc($_[0]), $_[1]);
-	my $price = 0;
-	for (my $id = 0; $id < @{$pool}; $id++) {
-		next unless $$pool[$id];
-		if (lc($$pool[$id]{name}) eq $item) {$price += $$pool[$id]{price}}
-	}
+	my ($itemIndex, $pool) = ($_[0], $_[1]);
+	my $price = -1;
+	if ($$pool[$itemIndex]) {$price = $$pool[$itemIndex]{price}}
 	return $price
 }
 
 # get storage array index
+# returns -1 if no matching items in storage
 sub getStorageIDs {
 	my $item = lc($_[0]);
 	my @ids;
@@ -277,7 +277,7 @@
 	return $amount
 }
 
-# get amount of an item in shop
+# get amount of an item in your shop
 sub getShopAmount {
 	my $arg = lc($_[0]);
 	my $amount = 0;
@@ -301,6 +301,15 @@
 	return $amount
 }
 
+# get amount of items for the specifical index in another venders shop
+# returns -1 if no shop is being visited
+sub getVendAmount {
+	my ($itemIndex, $pool) = ($_[0], $_[1]);
+	my $amount = -1;
+	if ($$pool[$itemIndex]) {$amount = $$pool[$itemIndex]{amount}}
+	return $amount
+}
+
 # returns random item from argument list
 sub getRandom {
 	my $arg = $_[0];
@@ -317,6 +326,30 @@
 	return $items[rand $id-1]
 }
 
+# returns given argument from a comma separated list
+# returns -1 if no such listID exists or when the list is empty or wrong
+sub getArgFromList {
+	my ($listID, $list) = split(/, \s*/, $_[0]);
+	my @items = split(/,\s*/, $list);
+	unless (@items) {
+		warning "[macro] wrong syntax in \@listItem\n", "macro";
+		return -1
+	}
+	if ($items[$listID]) {
+	return $items[$listID]
+		} else {
+		warning "[macro] the $listID number item does not exist in the list\n", "macro";
+		return -1
+	}
+}
+
+# returns the lenght of a comma separated list
+sub getlistLenght {
+	my $list = $_[0];
+	my @items = split(/,\s*/, $list);
+	return scalar(@items)
+}
+
 # returns random number within the given range  ###########
 sub getRandomRange {
 	my ($low, $high) = split(/,\s*/, $_[0]);
Summary:
- special keyword @venderprice(<indexID>)
returns an items price or -1 if the item is not found or if no shop is being visited.

- special keyword @venderItem(<itemName>)
returns a list of indexes (for multiple non-stackables) or a single item (for stackables or single non-stackables) or -1 if item was not found in the vender's list or if no shop is being visited.

- special keyword @listlenght(<$list>)
returns the list's lenght of indexes
(where $list = ind1,ind2,ind3,ind4, ...)

- special keyword @listitem(<listIndex>,<$list>)
returns the x'th item from a list or -1 if there is no such indexed item exists in the list.
(where $list = ind1,ind2,ind3,ind4,...)


[EDIT]
Comitted in macro plugin svn now.

Re: Macro Mods

Posted: 23 Dec 2008, 13:02
by Technology
Lastclick, make a diffpatch before commiting your code damnit.
By using a too old Parser.pm you undid all my latest changes!
Be more carefull ok?

This is the second time that this has happened now. :x
SVN system relies on people to not make such mistakes.
Conclusion, it sucks?