[Help] AutoWarp

Other plugins for extending OpenKore's functionality. This forum is only for posting new plugins and commenting on existing plugins. For support, use the Support forum.

Moderator: Moderators

Message
Author
beststorm
Noob
Noob
Posts: 5
Joined: 03 Nov 2009, 19:42
Noob?: No

[Help] AutoWarp

#1 Post by beststorm »

I've took a look in svn, search here in the forum, googled a lot and couldnt find a working "autowarper" plugin.

I found this two versions ill add here, but none of them are working properly.

Joseph's display the message "Preparing to cast a warp portal to..." but the bot continues walking away and get out of the map set in the config, so it will never warp anyway.

Hexos's version is generating these errors on loading:

Code: Select all

The error message is:
Plugin contains syntax errors:
Global symbol "%field" requires explicit package name at
C:/Users/pc/Desktop/openkore_ready/plugins/autowarper.pl line 172.
Global symbol "%field" requires explicit package name at
C:/Users/pc/Desktop/openkore_ready/plugins/autowarper.pl line 289.
I need some help to fix them cause i dunno how to edit plugins

Joseph:

Code: Select all

# autowarpn (completely new code by Joseph)
# licensed under gpl v2
# ported to 2.x by Kissa2k

package autowarpn;

use strict;
use Globals;
use Log qw(message);
use Utils;
use Network::Send;
use Misc;
use AI;

Plugins::register('autowarpn', 'Auto warp before walk to lockmap.', \&unload);

my $hooks = Plugins::addHooks(
   ['AI_pre', \&AI_hook],
   ['is_casting', \&casting_hook],
   ['parseMsg/pre', \&packet_hook],
);

my $cHook = Log::addHook(\&cHook);

sub unload {
   Plugins::delHooks($hooks);
}

sub cHook {
   my $type = shift;
    my $domain = shift;
   my $level = shift;
   my $currentVerbosity = shift;
   my $message = shift;
   
   if ($message =~ /Calculating lockMap route/ &&
     existsInList($config{autoWarp_from}, $field->baseName) &&
     $char->{skills}{AL_WARP} && $char->{skills}{AL_WARP}{lv} > 0) {
      AI::queue("autowarp");
      AI::args->{timeout} = 5;
      AI::args->{time} = time;
      AI::args->{map} = $field->baseName;
      message "Preparing to cast a warp portal to $config{autoWarp_to}\n";
   }
}

sub AI_hook {
   my $hookName = shift;

   if (AI::action eq "autowarp") {
      if ($field->baseName ne AI::args->{map} || $field->name ne AI::args->{map}) {
         AI::dequeue;
         return;
      }
      if (timeOut(AI::args)) {
         my $pos = getEmptyPos($char, 4);
         $messageSender->sendSkillUseLoc(27, 4, $pos->{x}, $pos->{y});
         stopAttack();
         message "Attempting to open warp portal at $pos->{x} $pos->{y}\n";
         AI::args->{timeout} = 15;
         AI::args->{time} = time;
      }
   }
}

sub packet_hook {
   my $hookName = shift;
   my $args = shift;
   my $switch = $args->{switch};
   my $msg = $args->{msg};

   if ($switch eq "011C") {
      $messageSender->sendWarpTele(27, $config{'autoWarp_to'}.".gat");
   }
}

sub casting_hook {
   my $hookName = shift;
   my $args = shift;

   # it's our warp portal! ok lets go in
   if ($args->{sourceID} eq $accountID && $args->{skillID} eq 27) {
      message "Moving into warp portal at $args->{x} $args->{y}\n";
      main::ai_route($field->baseName, $args->{x}, $args->{y},
         noSitAuto => 1,
         attackOnRoute => 0);
   }
}

sub getEmptyPos {
   my $obj = shift;
   my $maxDist = shift;

   # load info about everyone's location
   my %pos;
   for (my $i = 0; $i < @playersID; $i++) {
      next if (!$playersID[$i]);
      my $player = $players{$playersID[$i]};
      $pos{$player->{pos_to}{x}}{$player->{pos_to}{y}} = 1;
   }

   # crazy algorithm i made for spiral scanning the area around you
   # i wont bother to document it since im lazy and it already confuses me

   my @vectors = (-1, 0, 1, 0);

   my $vecx = int abs rand 4;
   my $vecy = $vectors[$vecx] ? 2 * int(abs(rand(2))) + 1 : 2 * int(abs(rand(2)));

   my ($posx, $posy);

   for (my $i = 1; $i <= $maxDist; $i++) {
      for (my $j = 0; $j < 4; $j++) {
         $posx = $obj->{pos_to}{x} + ( $vectors[$vecx] * $i * -1) || ( ($i*2) /2 );
         $posy = $obj->{pos_to}{y} + ( $vectors[$vecy] * $i * -1) || ( ($i*2) /-2 );
         for (my $k = 0; $k < ($i*2); $k++) {
            if ($field->isWalkable($posx, $posy) && !$pos{$posx}{$posy}) {
               my $pos = {x=>$posx, y=>$posy};
               return $pos if checkLineWalkable($obj->{pos_to}, $pos);
            }

            $posx += $vectors[$vecx];
            $posy += $vectors[$vecy];
         }
         $vecx = ($vecx+1)%4;
         $vecy = ($vecy+1)%4;
      }
   }
   return undef;
}

1;
Hexo55:

Code: Select all

# autowarper by Hexo55
# Edited from autowarpn by Joseph and Kissa2k 

package autowarper;

use strict;
use Globals;
use Log qw(message error);
use Utils;
use Network::Send;
use Misc;
use AI;
use Translation;

Plugins::register('autowarper', 'Autowarp for all your warping needs', \&unload);

my $hooks = Plugins::addHooks(
	 ['AI_pre', \&AI_hook],
	 ['packet_skilluse', \&warpopen_hook],
	 ['packet/warp_portal_list', \&warplist_hook],
	 ['Network::Receive::map_changed', \&mapchange_hook],
	 ['player_disappeared', \&playerdisappeared_hook],
	 ['packet_pre/area_spell_disappears', \&portaldisappeared_hook],
	 ['is_casting', \&casting_hook]
);

my $commandsID = Commands::register(
	 ["autowarp", "Autowarp for all your warping needs", \&cmdAutoWarp]
);


#global variables
my $map;
my $move_flag;
my @payload;
my $castTries;
my $isCasting;
my $timeoutBeforeCasting;
my $warpOpened;
my $warpNowOpen;
my $warpCoordinates;

sub unload {
	 Plugins::delHooks($hooks);
	 Commands::unregister($commandsID);
}

sub cmdAutoWarp {
	if (!$net || $net->getState() != Network::IN_GAME) {
		error TF("You must be logged in the game to use this command (%s).\n", shift);
		return;
	}
	elsif (AI::action eq "autowarp") {
		error T("We have already initiated autowarp, wait until it finishes.\n");
		return;
	}

	my (undef, $args_string) = @_;
	my @args = parseArgs($args_string);
	
	#initialize variables
	$castTries = 0;
	$warpOpened = 0;
	$warpNowOpen = 0;
	$move_flag = 0;
	
	if ($args[0] eq 'move') {
		$move_flag = 1;
		shift(@args);
	}

	$map = shift(@args);
	
	# Remove payload from args if it
	# the payload is currently in sight
	@payload = ();
	if (@args){
		foreach my $player (@{$playersList->getItems()}){
			last if (!@args);
			for (my $i = 0; $i < @args; $i++) {
				if ($args[$i] eq $player->{name}) {
					push(@payload, $args[$i]);
					splice(@args, $i, 1);
					last;
				}
			}	
		} 
	}
	
	if (@args) {
		error TF("Payload(s) %s is not in sight.\n", join(', ', @args));
	}
	
	if ($map =~ /^([a-zA-Z]+).*(\d*)$/) {
		# checks if you have the warp skill
		if (!($char->{skills}{AL_WARP}) || !($char->{skills}{AL_WARP}{lv} > 0)) {
			error T("Skill Warp Portal cannot be used because your character has no such skill.\n");
			return;
		}
		# checks if the destination you specify exists
		elsif (!defined $maps_lut{$map.'.rsw'}) {
			error TF("Map '%s' does not exist.\n", $map);
			return;
		}
				
		# add to AI::queue so that the bot will finish first
		# what it is doing before proceeding with autowarp
		# we also need to save AI::args->timeout into a temporary
		# variable since it is cleared whenever we call AI:queue
		# $temp variable is used when we are casting a skill so that
		# we will cast the warp portal after the skill has been cast.
		my $temp = AI::args->{timeout};
		AI::queue("autowarp");	
		AI::args->{timeout} = ($isCasting ? $temp+1 : 1);
		AI::args->{time} = time;
		$timeoutBeforeCasting = 0;
		# We need to stand to be able to cast the skill
		Commands::cmdStand();
		if(@payload) {
			message (sprintf("Now warping payload(s) %s.\n", join(', ', @payload)), "list");
		}	
		message(sprintf("Preparing to cast a warp portal to '%s'.\n", $map), "list");
	}
	else {
		error T("Syntax Error in function 'autowarp'\n" . 
						"Usage: autowarp [move] <field_name> [<player1> <player2> ...]\n");
	}
}

sub mapchange_hook {
	my $ai_string;
	if (@ai_seq) {
		$ai_string =  join(' ', @ai_seq);
	}
	
	# AI::Dequeue is not enough
	# since after moving into warp, the first
	# element in ai_seq is 'route' not 'autowarp'
	# because we invoke main::ai_route 
	if ($ai_string =~ /autowarp/) {
			AI::clear;
			return;
	}		
}

sub playerdisappeared_hook {
	my ($hookmname, $args) = @_;
	
	# This will run only if we are
	# autowarping, we have payloads, and
	# the warp is still open.
	if(AI::action eq "autowarp" && @payload && $warpNowOpen) {
		my $player = $args->{player};
    
    # Remove player from the payload list if
    # he disappeared.	
		for (my $i = 0; $i < @payload; $i++) {
			if ($payload[$i] eq $player->{name}) {
				message (sprintf("Payload %s disappeared.\n", $payload[$i]), "list");
				splice(@payload, $i, 1);
				last;
			}
		}
		
		if (!@payload && !$move_flag) {
			message ("No more Payload.\n", "list");
			AI::dequeue;
			return;
		}
		elsif (!@payload && $move_flag && $warpNowOpen) {
				message (sprintf("Moving into warp portal at (%d, %d).\n",$warpCoordinates->{x},$warpCoordinates->{y}), "list" );
				main::ai_route($field{name}, 	$warpCoordinates->{x}, $warpCoordinates->{y},
						noSitAuto => 1,
						attackOnRoute => 0);
				$move_flag = 0;
		}
	}
}

sub portaldisappeared_hook {
	my ($hookname, $args) = @_;
	
	# This will only run if we are autowarping
	# and we have casted a warp portal
	if(AI::action eq "autowarp" && $warpNowOpen){
		$warpNowOpen = 0;
		my $ID = $args->{ID};
		my $spell = $spells{$ID};
		if (($spell->{type} == 0x81) && ($spell->{sourceID} eq $accountID)) {
			# We need to cast another warp portal immediately 
			AI::args->{timeout} = 1;
			AI::args->{time} = time;
		}
	}
}	

sub AI_hook {
	my $hookName = shift;

	if (timeOut(AI::args)) {
		# If we are casting wait until
		# finishes
		if ($isCasting) {
			# Restore timeout
			AI::args->{timeout} = $timeoutBeforeCasting;
			AI::args->{time} = time;
			$isCasting = 0;
		}
		elsif (AI::action eq "autowarp") {
		
			# Check if we have reached $maxCastTries
			my $maxCastTries = defined($config{'autoWarp_maxCastTries'}) ? $config{'autoWarp_maxCastTries'} : 3;
			if ($castTries >= $maxCastTries) {
				error TF("Unable to cast skill Warp Portal in %d tries.\n", $castTries);
				AI::dequeue;
				return;
			}
			elsif ($warpOpened >= $maxCastTries) {
				error TF("I have already opened %d warp portals for the payloads, I will not open another.\n", $warpOpened);
				AI::dequeue;
				return;
			}	
		
			my $pos = getEmptyBlock($char, 8);
			if ($pos) {
				my $warplvl = $char->{skills}{AL_WARP}{lv};
				
				# This adds a skill task so as not to
				# interfere with current auto skills
				Commands::cmdUseSkill('sl', "27 $pos->{x} $pos->{y}");
				
				stopAttack();
				message (sprintf("Attempting to open warp portal at (%d, %d).\n",$pos->{x}, $pos->{y}), "list");
				# If we have failed to cast a warp, wait 
				# timeout before casting again
				AI::args->{timeout} = defined($config{'autoWarp_timeout'}) ? $config{'autoWarp_timeout'} : 15;
				AI::args->{time} = time;
				$castTries++;
			}
			else {
				error T("Cannot cast warp portal on current location, move to another location and try again.\n");
				AI::dequeue;
				return;
			}
		}		 
	}
}

sub warplist_hook { 
	if (AI::action eq "autowarp") {
	# checks if you have memo to your target destination
		for (my $i = 0; $i < @{$char->{warp}{memo}}; $i++) {
			last if ($char->{warp}{memo}[$i] eq $map);
			if (($i == @{$char->{warp}{memo}} - 1) && ($char->{warp}{memo}[$i] ne $map)) {
				error TF("You do not have a warp to '%s'.\n", $map);
				# You still need to do this to close the warp list
				$messageSender->sendWarpTele(27, $map. ".gat");
				AI::dequeue;
				return;
			} 
		}
		$messageSender->sendWarpTele(27, $map.".gat");
	}
}

sub warpopen_hook {
	my ($hookname, $args) = @_;
	
	if (AI::action eq "autowarp") {
	 # it's our warp portal!
		if ($args->{sourceID} eq $accountID && $args->{skillID} == 27) {
			$warpCoordinates->{x} = $args->{x};
			$warpCoordinates->{y} = $args->{y};
			$warpOpened++;
			$warpNowOpen = 1;
			$castTries = 0;
			if (@payload) {
					message("Waiting for the payload(s) to enter the warp portal.\n", "list");
					#extend timeout
					AI::args->{timeout} = 30;
					AI::args->{time} = time;
			}
			elsif (!$move_flag) {
				AI::dequeue;
				return;
			}
			elsif (!@payload && $move_flag && $warpNowOpen) {
				message (sprintf("Moving into warp portal at (%d, %d).\n",$warpCoordinates->{x},$warpCoordinates->{y}), "list" );
				main::ai_route($field{name}, 	$warpCoordinates->{x}, $warpCoordinates->{y},
						noSitAuto => 1,
						attackOnRoute => 0);
				$move_flag = 0;
			}
	 	}
	}
}

# This sub adds timeout in case we are
# casting a spell.
sub casting_hook {
	my ($hookname, $args) = @_;
	
	if ($args->{sourceID} eq $accountID) {
		# First we need to store the timeout before casting
		# so we can continue counting after we cast
		$timeoutBeforeCasting = AI::args->{timeout};
		AI::args->{timeout} = int($args->{castTime} / 1000) + 1;
		AI::args->{time} = time;
		$isCasting = 1;
	}
}

# My version of spiral scanning cells around the caster.
# This scans for an empty 3x3 cell around the caster
# up to $maxDist-1. This is slower than the previous
# algorithm since it has to scan more cells.
sub getEmptyBlock {
	my ($obj) = shift;
	my ($maxDist) = shift;
	my $cellPriority = $castTries;

	my $pos;
	
	#Get the position of all players
	foreach (@{$playersList->getItems()}) {
		$pos->{$_->{pos_to}{x}}->{$_->{pos_to}{y}} = 1;
	}

	my $vectorx = {
		1 => -1,
		-1 => 1
	};
		
	my $vectory = {
		-1 => -1,	
		1 => 1
	};
	
	my $target_pos;
	my $cell;
	for (my $i = 2; $i < $maxDist; $i++) {
		$cell->{x} = $i;
		$cell->{y} = $i;
			
		my $traversal_flag = 1;
		for (my $k = 0; $k < ($i*8); $k++) {
			$target_pos->{x} = $obj->{pos_to}{x} + $cell->{x};
			$target_pos->{y} = $obj->{pos_to}{y} + $cell->{y};
			
			
			if(is_subBlockEmpty($target_pos,$pos) && checkLineWalkable($obj->{pos_to}, $target_pos)) {
				# This ensures that if the warp skill failed, the next cast will
				# probably on a new spot.
				if ($cellPriority == 0 && int(rand(2)) == 1) {
					return $target_pos;
				}
				elsif($cellPriority > 0) {
					$cellPriority--;
				}
			}
			$cell->{$traversal_flag ? 'y':'x'} += $traversal_flag ? $vectorx->{$cell->{x}/$i}:$vectory->{$cell->{y}/$i};
			if ($traversal_flag && $vectory->{$cell->{y}/$i}) {
				$traversal_flag = 0;
			}
			elsif (!$traversal_flag && $vectorx->{$cell->{x}/$i}) {
				$traversal_flag = 1;
			}		
		}
	}
	return 0;
}

#Scans if the (3x3) subBlock is empty
sub is_subBlockEmpty {	
		my $center_pos = shift;
		my $pos = shift;
		my $vectors = [
			[0,0],
			[1,1],
			[1,0],
			[1,-1],
			[0,-1],
			[-1,-1],
			[-1,0],
			[-1,1],
			[0,1]
		];
		
		my $posx = 0; 
		my $posy = 0;

		foreach my $coord (@{$vectors}) {
			$posx = ${$coord}[0] + $center_pos->{x};
			$posy = ${$coord}[1] + $center_pos->{y};
			unless ($field->isWalkable($posx, $posy) && !$pos->{$posx}->{$posy}) {
				return 0;
			}
		}	
		return 1;
}
1;

luocongo
Human
Human
Posts: 22
Joined: 02 Aug 2009, 13:00
Noob?: Yes

Re: [Help] AutoWarp

#2 Post by luocongo »

I have same problem

please help us

Post Reply