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
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.