OpenKore 新增迴避技能 avoidSkill 外掛
OpenKore並無內建迴避技能的功能,需使用 plugins 附加此功能‧
1.將以下 avoidSkill 的程式碼(轉貼自 OpenKore 官方論壇)複製貼到記事本中
2.另存檔案為UTF-8編碼格式,檔案名稱命名為 avoidSkill.pl
3.放入 plugins 資料夾中
# avoidSkill by Joseph # original code from MessyKoreXP # licensed under GPL package avoidSkill; use strict; #use warnings; use Time::HiRes qw(time); use Globals; use Utils; use Misc; use AI; use Network::Send; use Commands; use Log qw(debug message warning error); use Skill; use encoding 'utf8'; Plugins::register('avoidSkill', 'React to skills.', \&onUnload); my $hooks = Plugins::addHooks( ['AI_pre', \&AI_hook], # ['is_casting', \&hookAvoidSkill] ['is_casting', \&avoidSkill, undef], ['packet_skilluse', \&avoidSkill, undef] ); my $prefix = "avoidSkill_"; my $prefix2 = "_afterCast"; sub onUnload { Plugins::delHooks($hooks); } sub avoidSkill { return if (!$config{autoAvoidSkill}); my (undef, $args) = @_; my $hookName = shift; # my $args = shift; my $sourceID = $args->{sourceID}; my $targetID = $args->{targetID}; my $source = $args->{source}; my $skill = $args->{skill}; my $skillID = $args->{skillID}; my $x = $args->{x}; my $y = $args->{y}; my $i = 0; #rufvin plugin #http://bibian.ath.cx/openkore/viewtopic.php?t=12123&postdays=0&postorder=asc&start=0 # while (exists $config{$prefix.$i}) { # my ($dist, %coords); # if ($x != 0 || $y != 0) { # # If $dist is positive we are in range of the attack? # $coords{x} = $x; # $coords{y} = $y; # $dist = judgeSkillArea($skillID) - distance($char->{pos_to}, \%coords); # } # if (existsInList($config{$prefix.$i}, $skill->name) && $sourceID ne $accountID) { # if ($dist > 0 || $targetID eq $accountID) { # AI::queue("avoidskill"); # AI::args->{timeout} = ($source->{casting}->{castTime} - $config{$prefix.$i."_delay"})/1000; # AI::args->{timeout} = 0 if (AI::args->{timeout}*1000 == $source->{casting}->{castTime} || AI::args->{timeout} < 0); # AI::args->{time} = time; # my $lvl; # my $skillUse = new Skills(name => $config{$prefix.$i."_use"}); # if ($config{$prefix.$i."_lvl"}>$char->{skills}{$skillUse->handle}->{lv} || !$config{$prefix.$i."_lvl"}) { # $lvl = $char->{skills}{$skillUse->handle}->{lv}; # } else { # $lvl = $config{$prefix.$i."_lvl"}; # } # AI::args->{lvl} = $lvl; # AI::args->{skillID} = $skillUse->id if ($lvl > 0); # if (ai_getSkillUseType($skillUse->handle)) { # AI::args->{char_state} = whenGroundStatus($char->{pos_to}, $skillUse->name); # } else { # AI::args->{char_state} = existsInList(join(",", keys %{$char->{statuses}}), $skillUse->name); # } # AI::args->{i} = $i; # Commands::run($config{$prefix.$i."_doCommand"}) if ($config{$prefix.$i."_doCommand"} ne ""); # } # } # $i++; # } ######################################### my $skill = new Skill(idn => $skillID); $skill = $skill->getName(); my $source = Actor::get($sourceID); debug "checking if we should avoid $skill from $source\n"; for (my $i = 0; exists $config{"avoidSkill_$i"}; $i++) { next if (!$config{"avoidSkill_$i"}); if (existsInList($config{"avoidSkill_$i"}, $skill)) { # if source is specified, make sure type is correct next if ($config{"avoidSkill_$i"."_source"} && $config{"avoidSkill_$i"."_source"} ne $source->{actorType}); debug "checking avoid radius on $skill\n"; # check if we are inside the skill area of effect my $inRange; my ($left,$right,$top,$bottom); if ($x != 0 || $y != 0) { $left = $x - $config{"avoidSkill_$i"."_radius"}; $right = $x + $config{"avoidSkill_$i"."_radius"}; $top = $y - $config{"avoidSkill_$i"."_radius"}; $bottom = $y + $config{"avoidSkill_$i"."_radius"}; $inRange = 1 if ($left <= $char->{pos_to}{x} && $right >= $char->{pos_to}{x} && $top <= $char->{pos_to}{y} && $bottom >= $char->{pos_to}{y}); } elsif ($targetID eq $accountID) { $inRange = 1; } if ($inRange) { if ($char->{sitting}) { main::stand(); } if ($config{"avoidSkill_$i"."_method"} == 0) { my $found = 1; my $count = 0; my %move; do { ($move{x}, $move{y}) = getRandPosition($config{"avoidSkill_${i}_step"}); $count++; if ($count > 100) { $found = 0; last; } } while ($left <= $move{x} && $right >= $move{x} && $top <= $move{y} && $bottom >= $move{y}); if ($found) { stopAttack(); sendMove(\$remote_socket, $move{x}, $move{y}); message "Avoid skill $skill, random move to $move{x}, $move{y}.\n"; } # Methods (choose one) # 0 - Random position outside <avoidSkill_#_radius> by <avoidSkill_#_step> # 1 - Move to opposite side by <avoidSkill_#_step> # 2 - Move nearest enemy. # 3 - Teleport # 4 - Attack (monsters only) # 5 - Use skill. (monsters only) } elsif ($config{"avoidSkill_$i"."_method"} == 1) { my $dx = $x - $char->{pos_to}{x}; my $dy = $y - $char->{pos_to}{y}; my %random; my %move; my $found = 1; my $count = 0; do { $random{x} = int(rand($config{"avoidSkill_$i"."_step"})) + 1; $random{y} = int(rand($config{"avoidSkill_$i"."_step"})) + 1; if ($dx >= 0) { $move{x} = $char->{pos_to}{x} - $random{x}; } else { $move{x} = $char->{pos_to}{x} + $random{x}; } if ($dy >= 0) { $move{y} = $char->{pos_to}{y} - $random{y}; } else { $move{y} = $char->{pos_to}{y} + $random{y}; } $count++; if ($count > 100) { $found = 0; last; } } while (!($field->isWalkable($x, $y))); if ($found) { stopAttack(); sendMove(\$remote_socket, $move{x}, $move{y}); message "Avoid skill $skill, move to $move{x}, $move{y}.\n"; } } elsif ($config{"avoidSkill_$i"."_method"} == 2) { my %src; $src{x} = $source->{pos_to}{x}; $src{y} = $source->{pos_to}{y}; my $found = 0; my $count = 0; my ($ex_left, $ex_right, $ex_top, $ex_bottom); my ($in_left, $in_right, $in_top, $in_bottom); my %move; my %nearest; do { $ex_left = $src{'x'} - $count; $ex_right = $src{'x'} + $count; $ex_top = $src{'y'} - $count; $ex_bottom = $src{'y'} + $count; $count++; $in_left = $src{'x'} - $count; $in_right = $src{'x'} + $count; $in_top = $src{'y'} - $count; $in_bottom = $src{'y'} + $count; my $nearest_dist = 9999; for ($move{'y'} = $in_top; $move{'y'} <= $in_bottom; $move{'y'}++) { for ($move{'x'} = $in_left; $move{'x'} <= $in_right; $move{'x'}++) { if (($move{'x'} < $ex_left || $move{'x'} > $ex_right) && ($move{'y'} < $ex_top || $move{'y'} > $ex_bottom)) { next if (($left <= $move{'x'} && $right >= $move{'x'} && $top <= $move{'y'} && $bottom >= $move{'y'}) || !($field->isWalkable($move{x}, $move{y}))); my $dist = distance(\%move, \%src); if ($dist < $nearest_dist) { $nearest_dist = $dist; $nearest{'x'} = $move{'x'}; $nearest{'y'} = $move{'y'}; $found = 1; } } } } } while (($count < 100) && (!$found)); if ($found) { stopAttack(); sendMove(\$remote_socket, $nearest{x}, $nearest{y}); message "Avoid skill $skill, move to nearest position $nearest{'x'}, $nearest{'y'}.\n"; } } elsif ($config{"avoidSkill_$i"."_method"} == 3) { message "Avoid skill $skill, use random teleport.\n"; main::useTeleport(1); } elsif ($config{"avoidSkill_$i"."_method"} == 4) { return unless ($source->{actorType} eq 'Monster'); message "Avoid skill $skill, attack to $source->{name}\n"; # may not care about portal distance, oh well stopAttack(); main::attack($sourceID); } elsif ($config{"avoidSkill_$i"."_method"} == 5 && timeOut($AI::Timeouts::avoidSkill_skill, 3)) { return unless ($source->{actorType} eq 'Monster'); message "Avoid skill $skill, use ".$config{"avoidSkill_$i"."_skill"}." to $source->{name}\n"; $skill = new Skill(name => $config{"avoidSkill_$i"."_skill"}); message "Use ".$skill->getHandle." on target\n"; if (main::ai_getSkillUseType($skill->getHandle)) { my $pos = ($config{"avoidSkill_${i}_isSelfSkill"}) ? $char->{pos_to} : $monsters{$sourceID}{pos_to}; main::ai_skillUse( $skill->getHandle, $config{"avoidSkill_$i"."_lvl"}, $config{"avoidSkill_$i"."_maxCastTime"}, $config{"avoidSkill_$i"."_minCastTime"}, $pos->{x}, $pos->{y}); } else { main::ai_skillUse( $skill->getHandle, $config{"avoidSkill_$i"."_lvl"}, $config{"avoidSkill_$i"."_maxCastTime"}, $config{"avoidSkill_$i"."_minCastTime"}, $config{"avoidSkill_${i}_isSelfSkill"} ? $accountID : $sourceID); } $AI::Timeouts::avoidSkill_skill = time; } } last; } } } sub AI_hook { AI::dequeue if (AI::action eq "avoidskill" && AI::args->{skillID} eq ""); if (AI::action eq "avoidskill" && timeOut(AI::args)) { my $i = AI::args->{i}; my $skillUse = new Skills(id => AI::args->{skillID}); if (ai_getSkillUseType($skillUse->handle)) { if (whenGroundStatus($char->{pos_to}, $skillUse->name) == AI::args->{char_state}) { $messageSender->sendSkillUseLoc(AI::args->{skillID}, AI::args->{lvl}, $char->{pos_to}{x}, $char->{pos_to}{y}); } elsif (!AI::args->{dequeue} && $config{$prefix.$i.$prefix2}) { AI::args->{timeout} = $config{$prefix.$i.$prefix2."_wait"}; AI::args->{time} = time; my $lvl; my $skillUseAfter = new Skills(name => $config{$prefix.$i.$prefix2."_use"}); if ($config{$prefix.$i.$prefix2."_lvl"}>$char->{skills}{$skillUseAfter->handle}->{lv} || !$config{$prefix.$i.$prefix2."_lvl"}) { $lvl = $char->{skills}{$skillUseAfter->handle}->{lv}; } else { $lvl = $config{$prefix.$i.$prefix2."_lvl"}; } AI::args->{lvl} = $lvl; AI::args->{skillID} = $skillUseAfter->id if ($lvl > 0); AI::args->{char_state} = whenGroundStatus($char->{pos_to}, $skillUseAfter->name); AI::args->{dequeue} = 1; } else { Commands::run($config{$prefix.$i.$prefix2."_doCommand"}) if ($config{$prefix.$i.$prefix2."_doCommand"} ne ""); AI::dequeue; } } else { if (existsInList(join(",", keys %{$char->{statuses}}), $skillUse->name) == AI::args->{char_state}) { $messageSender->sendSkillUse(AI::args->{skillID}, AI::args->{lvl}, $accountID); } elsif (!AI::args->{dequeue} && $config{$prefix.$i.$prefix2}) { AI::args->{timeout} = $config{$prefix.$i.$prefix2."_wait"}; AI::args->{time} = time; my $lvl; my $skillUseAfter = new Skills(name => $config{$prefix.$i.$prefix2."_use"}); if ($config{$prefix.$i.$prefix2."_lvl"}>$char->{skills}{$skillUseAfter->handle}->{lv} || !$config{$prefix.$i.$prefix2."_lvl"}) { $lvl = $char->{skills}{$skillUseAfter->handle}->{lv}; } else { $lvl = $config{$prefix.$i.$prefix2."_lvl"}; } AI::args->{lvl} = $lvl; AI::args->{skillID} = $skillUseAfter->id if ($lvl > 0); AI::args->{char_state} = existsInList(join(",", keys %{$char->{statuses}}), $skillUseAfter->name); AI::args->{dequeue} = 1; } else { Commands::run($config{$prefix.$i.$prefix2."_doCommand"}) if ($config{$prefix.$i.$prefix2."_doCommand"} ne ""); AI::dequeue; } } } } sub getRandPosition { my $range = shift; my $x_pos = shift; my $y_pos = shift; my $x_rand; my $y_rand; my $x; my $y; if ($x_pos eq "" || $y_pos eq "") { $x_pos = $char->{'pos_to'}{'x'}; $y_pos = $char->{'pos_to'}{'y'}; } do { $x_rand = int(rand($range)) + 1; $y_rand = int(rand($range)) + 1; if (int(rand(2))) { $x = $x_pos + $x_rand; } else { $x = $x_pos - $x_rand; } if (int(rand(2))) { $y = $y_pos + $y_rand; } else { $y = $y_pos - $y_rand; } } while (!($field->isWalkable($x, $y))); my @ret = ($x, $y); return @ret; } |
並在config.txt新增以下設定
avoidSkill <要避免的技能名稱> { radius <要避免的技能的半徑範圍格數> source <施放者類型,Monster=魔物;Player=玩家。若二者都有則留空白。有分大小寫> method <以下數字選一個> # 0 - 隨機移動至半徑 <avoidSkill_#_radius> 以外 <avoidSkill_#_step> 格的地方 # 1 - 往施法點反方向移動 <avoidSkill_#_step> 格 # 2 - 移動至最接近的施法者 # 3 - 瞬移飛走(免服不適用) # 4 - 攻擊施法者(只能用在魔物) # 5 - 使用技能(只能用在魔物) # (methods 0-1 的選項) step <要移動多遠的格數> # (method 5 的選項) skill <用來對付魔物的技能> # lvl <技能等級> isSelfSkill 0 # 技能是否用在自己身上 maxCastTime # like normal skill slots minCastTime # like normal skill slots } |
範例:
avoidSkill 傳送之陣,病毒散撥,滑動陷阱,定位陷阱,魔耗陷阱,睡魔陷阱,霜凍陷阱 { source radius 1 method 1 step 5 } |



您的迴避技能 不能使用 他出現 語法錯誤 謝謝^^