Ermm.. i got an idea but its not so clever becoz I dont know how to write plugins. I just can illustrate the logical route into macro plugins.. now here is the idea(dont laugh

)
Note:
1. Centre coordinate of portal is (x y)
2. All the ABCD route is a tangent to the circle line (centre coordinate= (px, py)):
$x = sqr(6**2 - ($y - py)**2) + px
3. The Diametre of the circle is 12 blocks
4. We need a) portal coordinate (x y), b) the target destination (x y)
In Theory:
1. The macro starts when we enter the yellow spot.
2. Macro
getCoordinates will set A, B, C, D spot based on the +-6 blocks from x and y (square)
3. Macro
bestDistance will determine which spot to choose (the nearest), so that we wont drop into the portal zone
4. Macro
find3Distance is the main logic to solve the puzzle.
Ex: Target Location - Dark Green Spot. Let say we are in pink spot, step 3 above will pick spot D as the new spot to stand. Then step 4 will choose 3 nearest spots from A,B,C,D that is close to spot D (the spot we are standing now). So, the best 3 spots is A, D, C and the bestDistance now will choose C as our new spot.
Then culculate again which is the nearest spot from D, C, B and the result is for sure B (goto B). Then culculate again from C, B, A which is the nearest spot... now it is B spot is the nearest. At this point, if the nearest spot is equal to our current post... just continue the journey... it is safe now!
Route: Pink(Start) -> D -> C -> B -> Dark Green(End)
Code: Select all
if (blockDistance($char->{pos},$portal->{pos}) < 6) {
my $target = "x y"; #the coordinate you wanna go in "x y" format
Plugins::callHook('portal_avoid', {px => $portal->{'pos'}{'x'}, py => $portal->{'pos'}{'y'}, target => $target});
}
Code: Select all
automacro portalRouteAvoid {
hook portal_avoid
eval AI::inQueue("route")
save px
save py
save target
exclusive 1
call avoid
}
macro avoid {
$target = $.hooksave2
call getCoordinates
call bestDistance
#go to nearest spot from our char 1st
:start
do move $coor
pause 2
if ($.pos = $coor) goto ok
#actually ($.pos = $coor) if statement is not nessessary coz OK will auto check if we really in $coor
goto start
:ok
call find3Distance
call bestDistance
if ($.pos = $coor) goto start
#($.pos = $coor) if statement is strictly nessessary
:end
do move $target
}
macro find3Distance {
# Listing all the 3 best/nearest coordinates (A>B>C>D) and its distance to the $target loc.
# Its like return $_coordinates for sub find3Distance($_A, $_B, $_C, $_D,$_coor) in normal plugins
do eval if ($_coor eq $_A) {@_c3 = ($_D, $_A, $_B)} elsif ($_coor eq $_B) {@_c3 = ($_A, $_B, $_C)} elsif ($_coor eq $_C) {@_c3 = ($_B, $_C, $_D)} elsif ($_coor eq $_D) {@_c3 = ($_C, $_D, $_A)} my @lines;foreach (@_c3) {my @_i = split(/ /, $_); my %_line; $_line{x} = abs($_target[0] - $_i[0]);$_line{y} = abs($_target[1] - $_i[1]); my $_d = sprintf("%.1f", sqrt($_line{x} ** 2 + $_line{y} ** 2));push @lines, $_i[0]." ". $_i[1] .", ". $_d;} $_coordinates = join("\n", @lines);
}
macro bestDistance {
# Choose the closest distance in $_coordinates and return the position value $coor (in macro var)
# Its like return $_coor (the best spot) for bestDistance($_coordinates) like using sub in normal plugins
do eval my $_dist;my $_dist1;my @_line = split(/\n/,$_coordinates); foreach (@_line) {($_dist) = "$_" =~ /, (.*)/; if (!defined $_dist1) {$_dist1 = $_dist; ($_coor) = "$_" =~ /(.*),/;} elsif ($_dist < $_dist1) {$_dist1 = $_dist;($_coor) = "$_" =~ /(.*),/} } $::Macro::Data::varStack{coor} = $_coor; $::Macro::Data::varStack{dist} = $_dist1;
}
macro getCoordinates {
# Set the 4 coordinates A,B,C,D shown in the illustration.
do eval @_target = split(/ /, $::Macro::Data::varStack{target}); ($_portalX, $_portalY) = ($::Macro::Data::varStack{'.hooksave0'}, $::Macro::Data::varStack{'.hooksave1'});$_A = ($_portalX - 6) . " " . ($_portalY + 6);$_B = ($_portalX + 6) . " " . ($_portalY + 6);$_C = ($_portalX + 6) . " " . ($_portalY - 6);$_D = ($_portalX - 6) . " " . ($_portalY - 6);@_c = ($_A, $_B, $_C, $_D);my @lines;foreach (@_c) {my @_i = split(/ /, $_); my %_line; $_line{x} = abs($::char->{'pos'}{'x'} - $_i[0]);$_line{y} = abs($::char->{'pos'}{'y'} - $_i[1]); my $_d = sprintf("%.1f", sqrt($_line{x} ** 2 + $_line{y} ** 2));push @lines, $_i[0]." ". $_i[1] .", ". $_d;} $_coordinates = join("\n", @lines);
}
macro find3Distance perl:
Code: Select all
if ($_coor eq $_A) {
@_c3 = ($_D, $_A, $_B)
} elsif ($_coor eq $_B) {
@_c3 = ($_A, $_B, $_C)
} elsif ($_coor eq $_C) {
@_c3 = ($_B, $_C, $_D)
} elsif ($_coor eq $_D) {
@_c3 = ($_C, $_D, $_A)
}
my @lines;
foreach (@_c3) {
my @_i = split(/ /, $_);
my %_line;
$_line{x} = abs($_target[0] - $_i[0]);
$_line{y} = abs($_target[1] - $_i[1]);
my $_d = sprintf("%.1f", sqrt($_line{x} ** 2 + $_line{y} ** 2));
push @lines, $_i[0]." ". $_i[1] .", ". $_d;
}
$_coordinates = join("\n", @lines);
macro bestDistance perl:
Code: Select all
my $_dist;my $_dist1;
my @_line = split(/\n/,$_coordinates);
foreach (@_line) {
($_dist) = "$_" =~ /, (.*)/;
if (!defined $_dist1) {
$_dist1 = $_dist; ($_coor) = "$_" =~ /(.*),/;
} elsif ($_dist < $_dist1) {
$_dist1 = $_dist;($_coor) = "$_" =~ /(.*),/
}
}
$::Macro::Data::varStack{coor} = $_coor;
$::Macro::Data::varStack{dist} = $_dist1;
macro getCoordinates perl:
Code: Select all
@_target = split(/ /, $::Macro::Data::varStack{target});
($_portalX, $_portalY) = ($::Macro::Data::varStack{'.hooksave0'}, $::Macro::Data::varStack{'.hooksave1'});
$_A = ($_portalX - 6) . " " . ($_portalY + 6);
$_B = ($_portalX + 6) . " " . ($_portalY + 6);
$_C = ($_portalX + 6) . " " . ($_portalY - 6);
$_D = ($_portalX - 6) . " " . ($_portalY - 6);
@_c = ($_A, $_B, $_C, $_D);
my @lines;
foreach (@_c) {
my @_i = split(/ /, $_);
my %_line;
$_line{x} = abs($::char->{'pos'}{'x'} - $_i[0]);
$_line{y} = abs($::char->{'pos'}{'y'} - $_i[1]);
my $_d = sprintf("%.1f", sqrt($_line{x} ** 2 + $_line{y} ** 2));push @lines, $_i[0]." ". $_i[1] .", ". $_d;
}
$_coordinates = join("\n", @lines);
Basically I just use distance as the main issue to calculate the route... it works in theory and with several test. But the test that i've done is not a portal ... I just take a random spot in a map assuming it is a portal

. Then use a move command to let the bot across that spot and the result is impressive. But the main prob is I'm using a macro, so definitely not as good as a normal plugins outcome.
Well this is just an idea, if you think it is possible to coding it into normal plugins... you got my bless.. and if you dont... just skip this post .