Code: Select all
--- untouched/openkore_ready/src/Utils.pm Sun Sep 08 22:00:04 2013
+++ openkore_ready/src/Utils.pm Fri Nov 01 22:30:21 2013
@@ -38,7 +38,7 @@
@{$Utils::DataStructures::EXPORT_TAGS{all}},
# Math
- qw(calcPosFromTime calcPosition calcTime checkMovementDirection countSteps distance
+ qw(calcPosFromTime calcPosition calcTime checkMovementDirection countSteps distance distance_steps
intToSignedInt intToSignedShort
blockDistance getVector moveAlong moveAlongVector
normalize vectorToDegree max min round ceil),
@@ -291,6 +291,31 @@
%line = %{$pos1};
}
return sqrt($line{x} ** 2 + $line{y} ** 2);
+}
+
+##
+# distance_steaps(r_hash1, r_hash2)
+# pos1, pos2: references to position hash tables.
+# Returns: the distance as a number.
+#
+# Calculates the maximum horizontal or vertical distance
+# between pos1 and pos2. Use this to find out if a position
+# is within your reach.
+#
+# FIXME: This is not actually the number of steps one
+# has to take to reach the target.
+#
+sub distance_steps {
+ my $pos1 = shift;
+ my $pos2 = shift;
+ return 0 if (!$pos1 || !$pos2);
+
+ my ($dx, $dy) = (
+ abs($pos1->{x} - $pos2->{x}),
+ abs($pos1->{y} - $pos2->{y})
+ );
+
+ return $dx > $dy ? $dx : $dy;
}
##
This fixes the annoying problem that openkore fails to pickup items so often:
Code: Select all
--- untouched/openkore_ready/src/AI/CoreLogic.pm Sat Jun 08 02:00:02 2013
+++ openkore_ready/src/AI/CoreLogic.pm Fri Nov 01 22:35:33 2013
@@ -736,14 +738,32 @@
if (AI::action eq "take" && !(my $item = $items{AI::args->{ID}})) {
AI::dequeue;
+ } elsif (AI::action eq "take" && ($item->{take_failed} < 2) && timeOut(AI::args->{ai_take_giveup})) {
+ $item->{take_failed}++;
+ my $myPos = $char->{pos};
+ my $dist = distance_steps($item->{pos}, $myPos);
+ if ($dist > 0) {
+ AI::args->{ai_take_giveup}{time} = time(); # reset timer
+ if (!$config{itemsTakeAuto_new}) {
+ $char->move($item->{pos}{x}, $item->{pos}{y});
+ } else {
+ my $pos = $item->{pos};
+ message TF("Routing to (%s, %s) to take %s (%s), distance %s\n", $pos->{x}, $pos->{y}, $item->{name}, $item->{binID}, $dist);
+ ai_route($field->baseName, $pos->{x}, $pos->{y}, maxRouteDistance => $config{'attackMaxRouteDistance'});
+ }
+ message TF("Failed to take %s (%s) from (%s, %s) to (%s, %s) --- moving towards item\n", $item->{name}, $item->{binID}, $char->{pos}{x}, $char->{pos}{y}, $item->{pos}{x}, $item->{pos}{y});
+ } else {
+ message TF("Failed to take %s (%s) from (%s, %s) to (%s, %s) --- standing on top of it\n", $item->{name}, $item->{binID}, $char->{pos}{x}, $char->{pos}{y}, $item->{pos}{x}, $item->{pos}{y});
+ AI::dequeue;
+ }
} elsif (AI::action eq "take" && timeOut(AI::args->{ai_take_giveup})) {
message TF("Failed to take %s (%s) from (%s, %s) to (%s, %s)\n", $item->{name}, $item->{binID}, $char->{pos}{x}, $char->{pos}{y}, $item->{pos}{x}, $item->{pos}{y});
$item->{take_failed}++;
---
This fixes a deadlock(!) situation openkore encounters when it tries to attack mobs that wont move and the attack position it want's to move to is not walkable.
Example: (Mushroom)(empty)(tree)(bot)
Code: Select all
--- untouched/openkore_ready/src/AI/Attack.pm Sat Apr 06 03:00:02 2013
+++ openkore_ready/src/AI/Attack.pm Tue Oct 29 23:40:22 2013
@@ -518,6 +521,29 @@
$args->{monsterPos} = {%{$monsterPos}};
my $pos = meetingPosition($target, $args->{attackMethod}{maxDistance});
+
+ if (not $field->isWalkable($pos->{x}, $pos->{y}) and distance_steps($realMyPos, $pos) < 2) {
+ # bad case of hitting a wall
+ # try to find an alternative position with the same distance
+ my ($tx, $ty, $td, $t) = (0,0,999, distance($realMonsterPos->{pos}, $pos));
+ for my $try ([-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]) {
+ next unless $field->isWalkable($pos->{x} + $try->[0], $pos->{y} + $try->[1]);
+ next if distance_steps($realMyPos, { x => $pos->{x} + $try->[0], y => $pos->{y} + $try->[1]}) < 1;
+ my $d = abs($t - distance({ x => $pos->{x} + $try->[0], y => $pos->{y} + $try->[1]}, $pos));
+ if ($d < $td) {
+ ($tx, $ty, $td) = ($pos->{x} + $try->[0], $pos->{y} + $try->[1], $d);
+ }
+ }
+ if ($td < 999) {
+ ($pos->{x}, $pos->{y}) = ($tx, $ty);
+ } else {
+ # now what?
+ # move one random step
+ while (not $field->isWalkable($pos->{x}, $pos->{y})) {
+ ($pos->{x}, $pos->{y}) = ($realMyPos->{x} + int(rand(3)-2), $realMyPos->{y} + int(rand(3)-2));
+ }
+ }
+ }
my $dist = sprintf("%.1f", $monsterDist);
debug "Target distance $dist is >$args->{attackMethod}{maxDistance}; moving to target: " .
I tried to be very careful, but I only tested it with melee characters. But I think the LOS checking may prevent this from happening for the others.
---
And now a new feature. Or maybe a bug fix? I don't know, but autoStorage already works for items in the cart; this will do the same for autoSell:
Code: Select all
--- untouched/openkore_ready/src/AI/CoreLogic.pm Sat Jun 08 02:00:02 2013
+++ openkore_ready/src/AI/CoreLogic.pm Fri Nov 01 22:35:33 2013
@@ -1483,6 +1503,37 @@
noSitAuto => 1);
}
} else {
+
+ if (!defined($args->{'emptiedCart'})) {
+ # get item to sell from cart
+ $args->{'emptiedCart'} = 1;
+ if ($char->cartActive) {
+ my @getItems;
+ my $cartInventory = $cart{inventory};
+ my $max;
+
+ $max = @{$cartInventory};
+ for (my $i = 0; $i < $max; $i++) {
+ my $cartItem = $cartInventory->[$i];
+ next unless ($cartItem);
+ my $control = items_control($cartItem->{name});
+ next unless ($control->{sell});
+ my $amount = $cartItem->{amount};
+ if ($amount > 0) {
+ my %obj;
+ $obj{index} = $i;
+ $obj{amount} = $amount;
+ push @getItems, \%obj;
+ debug "Scheduling $cartItem->{name} ($i) x $obj{amount} for getting from cart to sell\n", "ai_autoCart";
+ }
+ }
+ if (@getItems) {
+ cartGet(\@getItems);
+ return;
+ }
+ }
+ }
+
$args->{'npc'} = {};
getNPCInfo($config{'sellAuto_npc'}, $args->{'npc'});
if (!defined($args->{'sentSell'})) {