I've updated the plugin to work on the current version of openkore.
You must be a sage type and have freecast learnt and only works on bolts and thunderstorm, all other skills operate as per normal.
You must these lines to your config.txt:
Code: Select all
runFromTargetFree 1
runFromTargetFree_min 8
runFromTargetFree_mid 5
runFromTargetFree_max 10
You should set 'dist' in your spell's attackSkillSlot to one lower then whatever you set 'runFromTargetFree_min' to.
For instance using the above values:
Code: Select all
attackSkillSlot Fire Bolt {
lvl 6
dist 7 #one lower than runFromTargetFree_min
sp > 10
inLockOnly 1
monsters x,y,z #Aggressive or cast sensor monster you want to run from while casting
}
attackSkillSlot Fire Bolt {
lvl 8
dist 9 #one higher than runFromTargetFree_min
sp > 10
inLockOnly 1
monsters a,b,c #Some stationary monster you don't need to move from
}
Code: Select all
package freeCast;
# This plugin is licensed under the GNU GPL
# Copyright 2008 by DInvalid
# Portions Copyright 2005 by kaliwanagan
# --------------------------------------------------
# Experimental! Use on your own risk!
# How to install this thing..:
#
# The plugin will activate if:
# you have the skill free cast at level 1 or higher, and
# config is set:
# runFromTargetFree 1
# runFromTargetFree_min 7
# runFromTargetFree_mid 9
# runFromTargetFree_max 12
#
use strict;
use Plugins;
use Globals;
use Translation qw(T TF);
use Log qw(message warning error);
use AI;
use skill;
use Misc;
use Network;
use Network::Send;
use Utils;
use Math::Trig;
use Utils::Benchmark;
use Utils::PathFinding;
Plugins::register('Free Cast', 'experimental sage free cast support', \&Unload);
my $hook1 = Plugins::addHook('AI_post', \&call);
my $ID;
my $target;
my %timeout;
my ($myPos, $monsterPos,$monsterDist);
##
# round($number)
#
# Returns the rounded number
sub round {
my($number) = shift;
return int($number + .5 * ($number <=> 0));
}
sub Unload {
Plugins::delHook('AI_post', $hook1);
}
sub call {
my $i = AI::findAction("attack");
if (defined $i) {
my $args = AI::args($i);
$ID = $args->{ID};
$target = Actor::get($ID);
$myPos = $char->{pos_to};
$monsterPos = $target->{pos_to};
$monsterDist = round(distance($myPos, $monsterPos));
}
if (AI::action eq "skill_use") {
my $args = AI::args(AI::action);
my $s = $args->{skillHandle};
if ($s eq "MG_FIREBOLT" || $s eq "MG_COLDBOLT" || $s eq "MG_LIGHTNINGBOLT" || $s eq "MG_THUNDERSTORM") {
cast();
}
}
}
sub cast {
if (($char->{skills}{SA_FREECAST}{lv}) && main::timeOut(\%timeout)){
#message "Cast!\n";
my ($realMyPos, $realMonsterPos, $realMonsterDist, $hitYou);
my $realMyPos = calcPosition($char);
my $realMonsterPos = calcPosition($target);
my $realMonsterDist = round(distance($realMyPos, $realMonsterPos));
$myPos = $realMyPos;
$monsterPos = $realMonsterPos;
$hitYou = 0;
if ($config{'runFromTargetFree'} && ($realMonsterDist < $config{'runFromTargetFree_min'})) {
#my $begin = time;
my @blocks = calcRectArea($myPos->{x}, $myPos->{y},$config{'runFromTargetFree_mid'});
my $highest;
foreach (@blocks) {
my $dist = ord(substr($field->{dstMap}, $_->{y} * $field->{width} + $_->{x}));
if (!defined $highest || $dist > $highest) {
$highest = $dist;
}
}
my $pathfinding = new PathFinding;
use constant AVOID_WALLS => 4;
for (my $i = 0; $i < @blocks; $i++) {
# We want to avoid walls (so we don't get cornered), if possible
my $dist = ord(substr($field->{dstMap}, $blocks[$i]{y} * $field->{width} + $blocks[$i]{x}));
if ($highest >= AVOID_WALLS && $dist < AVOID_WALLS) {
delete $blocks[$i];
next;
}
$pathfinding->reset(
field => $field,
start => $myPos,
dest => $blocks[$i]);
my $ret = $pathfinding->runcount;
if ($ret <= 0 || $ret > $config{'runFromTargetFree_min'} * 2) {
delete $blocks[$i];
next;
}
delete $blocks[$i] unless (checkLineSnipable($blocks[$i], $realMonsterPos) || checkLineWalkable($blocks[$i], $realMonsterPos));
}
my $largestDist;
my $best_spot;
foreach (@blocks) {
next unless defined $_;
my $dist = distance($monsterPos, $_);
if (!defined $largestDist || $dist > $largestDist) {
$largestDist = $dist;
$best_spot = $_;
}
}
$char->move($best_spot->{x}, $best_spot->{y}, $ID) if ($best_spot);
} elsif ($config{'runFromTargetFree'} && ($realMonsterDist > $config{'runFromTargetFree_max'})) {
my $radius = $config{runFromTargetFree_max}-1;
my @blocks = calcRectArea2($realMonsterPos->{x}, $realMonsterPos->{y},
$radius,
$config{runFromTargetFree_mid});
my $best_spot;
my $best_dist;
for my $spot (@blocks) {
if (
(($config{attackCanSnipe} && checkLineSnipable($spot, $realMonsterPos)) || checkLineWalkable($spot, $realMonsterPos))
&& $field->isWalkable($spot->{x}, $spot->{y})
) {
my $dist = distance($realMyPos, $spot);
if (!defined($best_dist) || $dist < $best_dist) {
$best_dist = $dist;
$best_spot = $spot;
}
}
}
$char->move($best_spot->{x}, $best_spot->{y}, $ID) if ($best_spot);
}
}
$timeout{time} = time;
$timeout{timeout} = 1;
}
return 1;
http://pastebin.com/cs50nRi7
SVN link:
https://sourceforge.net/p/openkore/code ... reeCast.pl