http://forums.openkore.com/viewtopic.php?t=139
http://forums.openkore.com/viewtopic.php?p=55936#p55936
Код: Выделить всё
################################
# Name of Plugin: follow_wait.pl
# Author: dijedodol@yahoo.com
# Instruction:
# follow_wait 1
# follow_wait_minDistance 5
# follow_wait_maxDistance 20
# follow_wait_preLostTimeOut 1
# follow_wait_timeout 0
# follow_wait_positionTimeOut 2
# follow_wait_searchAttackOnRoute 1
# Description:
# follow_wait = enable / disabled follow_wait
# follow_wait_minDistance = wait until this distance is reached
# follow_wait_maxDistance = distance before follow wait trigger lost check
# follow_wait_preLostTimeOut = when max distance is reached, keep ignoring for x sec before party member is marked as lost
# follow_wait_timeout = when party member is lost, wait x sec (sitting) until party member is arrived
# follow_wait_positionTimeOut = when party member is lost and wait timeout has been triggered, start moving to search for party member and check his latest location every x sec
# follow_wait_searchAttackOnRoute = openkore route AI, allow to attack monster or not while moving to search for party member
################################
package follow_wait;
use Time::HiRes qw(time);
use Plugins;
use Globals;
use Utils::DataStructures qw(existsInList);
use Log qw(message warning error debug);
Plugins::register('follow_wait', 'Wait for party member following you', \&unload, \&reload);
my $hooks = Plugins::addHooks(['mainLoop_pre', \&followWaitMainWrapper, undef]);
my $checkInterval = 500_000 / 1000_000;
my $lastCheckTick = 0;
my $isSearching = 0;
my $lostMemberUserId = 0;
my $preLostTimeOutTick = 0;
my $pauseMovementTimeOutTick = 0;
my $lostMemberPositionLastTick = 0;
sub unload {
Plugins::delHooks($hooks);
}
sub reload {
Plugins::delHooks($hooks);
}
sub followWaitMainWrapper {
return unless ($config{'follow_wait'});
return unless ((time() - $lastCheckTick) > $checkInterval);
followWaitMain();
$lastCheckTick = time();
}
sub followWaitMain {
return if (!$net || $net->getState() != Network::IN_GAME);
return unless ($AI == AI::AUTO);
return unless ($char->{party});
return unless (!AI::inQueue("storageAuto","storageGet","sellAuto","buyAuto"));
if ($isSearching != 1 && $isSearching != 2) {
resumeMovement();
}
if ($isSearching == 0) {
for (my $i = 0; $i < @partyUsersID; $i++) {
my $memberUserId = $partyUsersID[$i];
next if ($memberUserId eq "");
next if ($memberUserId eq $accountID);
next unless ($char->{'party'}{'users'}{$memberUserId}{'online'});
next unless $config{'follow_wait_list'} eq "" || existsInList($config{'follow_wait_list'}, $char->{'party'}{'users'}{$memberUserId}{'name'});
my $isMemberAround = isMemberAround($memberUserId);
if ($isMemberAround == 0) {
warning "Unknown party member User ID: " .$lostMemberUserId ."!\n";
next;
} elsif ($isMemberAround == 1) {
warning "Unexpected follow_wait searching own self!\n";
next;
} elsif ($isMemberAround == 2) {
#ignore offline party member
next;
} elsif ($isMemberAround == 3) {
#ignore unknown party member location
next;
} elsif ($isMemberAround == 4) {
#party member is on the different map, skip directly to party member search
$isSearching = 4;
$lostMemberUserId = $memberUserId;
last;
} elsif ($isMemberAround == 5) {
#party member is on the same map, try pausing movement to wait
$lostMemberUserId = $memberUserId;
if ($config{'follow_wait_timeout'} == 0) {
#skip directly to party member search, waiting has been disabled
$isSearching = 3;
} elsif ($config{'follow_wait_preLostTimeOut'}) {
#ignore until pre-lost timeout occured
warning "Party member pre-lost: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ."!\n";
$isSearching = 5;
$preLostTimeOutTick = time();
} else {
#wait party member until timeout
$isSearching = 1;
}
last;
} elsif ($isMemberAround == 255) {
#party member is currently on sight
next;
} else {
warning "Unexpected isMemberAround result: " .$isMemberAround ."!\n";
next;
}
}
} elsif ($isSearching == 1) {
$pauseMovementTimeOutTick = time();
pauseMovement();
$isSearching = 2;
} elsif ($isSearching == 2) {
my $isMemberAround = isMemberAround($lostMemberUserId);
if ($isMemberAround == 0) {
warning "Unknown party member User ID: " .$lostMemberUserId ."!\n";
$isSearching = 0;
resumeMovement();
} elsif ($isMemberAround == 1) {
warning "Unexpected follow_wait searching own self!\n";
$isSearching = 0;
resumeMovement();
} elsif ($isMemberAround == 2) {
warning "Canceling party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ." search due to user offline!\n";
$isSearching = 0;
resumeMovement();
} elsif ($isMemberAround == 3) {
if (Utils::timeOut($pauseMovementTimeOutTick, $config{'follow_wait_timeout'})) {
warning "Canceling party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ." wait due to timeout and unknown user location!\n";
$isSearching = 0;
resumeMovement();
}
} elsif ($isMemberAround == 255) {
warning "Party member arrived: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ."!\n";
$isSearching = 0;
resumeMovement();
} elsif ($isMemberAround == 4 || $isMemberAround == 5) {
if (Utils::timeOut($pauseMovementTimeOutTick, $config{'follow_wait_timeout'})) {
#timeout on waiting party member to arrive, initiate party member search
warning "Timeout waiting for party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} .", initiating party member search!\n";
if($isMemberAround == 4) {
#not on the same map
$isSearching = 4;
} else {
#on the same map
$isSearching = 3;
}
resumeMovement();
}
} else {
warning "Unexpected isMemberAround result: " .$isMemberAround ."!\n";
$isSearching = 0;
resumeMovement();
}
} elsif ($isSearching == 3) {
my $isMemberAround = isMemberAround($lostMemberUserId);
if ($isMemberAround == 0) {
warning "Unknown party member User ID: " .$lostMemberUserId ."!\n";
$isSearching = 0;
} elsif ($isMemberAround == 1) {
warning "Unexpected follow_wait searching own self!\n";
$isSearching = 0;
} elsif ($isMemberAround == 2) {
warning "Canceling party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ." search due to user offline!\n";
$isSearching = 0;
} elsif ($isMemberAround == 3) {
warning "Canceling party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ." search due to unknown user location!\n";
$isSearching = 0;
} elsif ($isMemberAround == 4) {
#not on the same map
$isSearching = 4;
} elsif ($isMemberAround == 5) {
if (Utils::timeOut($lostMemberPositionLastTick, $config{'follow_wait_positionTimeOut'})) {
#warning "Updating search location for party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ." too far away!\n";
$lostMemberPositionLastTick = time();
searchPartyMember($lostMemberUserId);
}
} elsif ($isMemberAround == 255) {
warning "Party member found: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ."!\n";
$isSearching = 0;
} else {
warning "Unexpected isMemberAround result: " .$isMemberAround ."!\n";
$isSearching = 0;
}
} elsif ($isSearching == 4) {
my $isMemberAround = isMemberAround($lostMemberUserId);
if ($isMemberAround == 0) {
warning "Unknown party member User ID: " .$lostMemberUserId ."!\n";
$isSearching = 0;
} elsif ($isMemberAround == 1) {
warning "Unexpected follow_wait searching own self!\n";
$isSearching = 0;
} elsif ($isMemberAround == 2) {
warning "Canceling party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ." search due to user offline!\n";
$isSearching = 0;
} elsif ($isMemberAround == 3) {
#unknown position on the same map, initiate wait
$isSearching = 1;
} elsif ($isMemberAround == 4) {
if (Utils::timeOut($lostMemberPositionLastTick, $config{'follow_wait_positionTimeOut'})) {
(my $memberMap = $char->{'party'}{'users'}{$memberUserId}{'map'}) =~ s/\.gat//;
if ($memberMap eq $config{'saveMap'} && $config{'follow_wait_saveMapTeleport'}) {
Misc::useTeleport(2);
} else {
#warning "Updating search location for party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ." not on the same map!\n";
$lostMemberPositionLastTick = time();
searchPartyMember($lostMemberUserId);
}
}
} elsif ($isMemberAround == 5) {
#on the same map
$isSearching = 3;
} elsif ($isMemberAround == 255) {
warning "Party member found: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ."!\n";
$isSearching = 0;
} else {
warning "Unexpected isMemberAround result: " .$isMemberAround ."!\n";
$isSearching = 0;
}
} elsif ($isSearching == 5) {
if (Utils::timeOut($preLostTimeOutTick, $config{'follow_wait_preLostTimeOut'})) {
my $isMemberAround = isMemberAround($lostMemberUserId);
if ($isMemberAround == 0) {
warning "Unknown party member User ID: " .$lostMemberUserId ."!\n";
$isSearching = 0;
} elsif ($isMemberAround == 1) {
warning "Unexpected follow_wait searching own self!\n";
$isSearching = 0;
} elsif ($isMemberAround == 2) {
warning "Canceling party member: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ." pre-lost due to user offline!\n";
$isSearching = 0;
} elsif ($isMemberAround == 3) {
#unknown position on the same map, initiate wait
$isSearching = 1;
} elsif ($isMemberAround == 4) {
#party member is on the different map
$isSearching = 4;
} elsif ($isMemberAround == 5) {
#party member is on the same map, try pausing movement to wait
if ($config{'follow_wait_timeout'} == 0) {
#skip directly to party member search, waiting has been disabled
$isSearching = 3;
} else {
#wait party member until timeout
$isSearching = 1;
}
} elsif ($isMemberAround == 255) {
#party member is currently on sight
warning "Pre-lost party member arrived: " .$char->{'party'}{'users'}{$lostMemberUserId}{'name'} ."!\n";
$isSearching = 0;
} else {
warning "Unexpected isMemberAround result: " .$isMemberAround ."!\n";
$isSearching = 0;
}
}
} else {
warning "Unexpected isSearching value: " .$isMemberAround ."!\n";
$isSearching = 0;
}
}
sub isMemberAround {
my $memberUserId = @_[0];
if ($memberUserId && $char->{'party'}{'users'}{$memberUserId}) {
if ($memberUserId eq $accountID) {
return 1;
} elsif (!$char->{'party'}{'users'}{$memberUserId}{'online'}) {
return 2;
} else {
(my $masterMap = $field->name) =~ s/\.gat//;
(my $memberMap = $char->{'party'}{'users'}{$memberUserId}{'map'}) =~ s/\.gat//;
if ($char->{'party'}{'users'}{$memberUserId}{'pos'}{'x'} == 0 && $char->{'party'}{'users'}{$memberUserId}{'pos'}{'y'} == 0) {
if ($masterMap eq $memberMap) {
return 3;
} else {
return 4;
}
} elsif ($masterMap ne $memberMap) {
return 4;
} else {
$memberDistance = Utils::distance($char->{'party'}{'users'}{$memberUserId}{'pos'}, $char->{'pos_to'});
if ($isSearching) {
if ($memberDistance <= $config{'follow_wait_minDistance'}) {
return 255;
} else {
return 5;
}
} else {
if ($memberDistance <= $config{'follow_wait_maxDistance'}) {
return 255;
} else {
return 5;
}
}
}
}
} else {
return 0;
}
}
sub searchPartyMember {
my $memberUserId = @_[0];
(my $memberMap = $char->{'party'}{'users'}{$memberUserId}{'map'}) =~ s/\.gat//;
my $memberX = $char->{'party'}{'users'}{$memberUserId}{'pos'}{'x'};
my $memberY = $char->{'party'}{'users'}{$memberUserId}{'pos'}{'y'};
if ($memberX == 0 && $memberY == 0) {
undef $memberX;
undef $memberY;
}
if (!AI::ai_getAggressives()) {
warning "Searching for party member: " .$char->{'party'}{'users'}{$memberUserId}{'name'} ." on map: " .$memberMap ."(" .$memberX .", " .$memberY .")!\n";
AI::clear("move", "route", "mapRoute");
AI::ai_route($memberMap, $memberX, $memberY,
attackOnRoute => $config{'follow_wait_searchAttackOnRoute'},
noSitAuto => 1,
notifyUponArrival => 1);
}
}
sub pauseMovement {
if (!$char->{'sitting'}) {
warning "Pausing AI movement!\n";
Commands::cmdSit();
}
}
sub resumeMovement {
if ($char->{'sitting'}) {
warning "AI movement has been resumed!\n";
Commands::cmdStand();
}
}
return 1;
Если рабочий, то добавляем в SVN