PDA

View Full Version : Openkore KS function, Killing Stealing Function


supapogz2
25th August 2005, 17:13
:D ##### ATTACK #####

if (AI::action eq "attack" && AI::args->{suspended}) {
AI::args->{ai_attack_giveup}{time} += time - AI::args->{suspended};
delete AI::args->{suspended};
}

if (AI::action eq "attack" && AI::args->{move_start}) {
# We've just finished moving to the monster.
# Don't count the time we spent on moving
AI::args->{ai_attack_giveup}{time} += time - AI::args->{move_start};
undef AI::args->{unstuck}{time};
undef AI::args->{move_start};

} elsif (AI::action eq "attack" && AI::args->{avoiding}) {
AI::args->{ai_attack_giveup}{time} = time + $monsters{AI::args->{ID}}{time_move_calc} + 3;
undef AI::args->{avoiding};

} elsif (((AI::action eq "route" && AI::action(1) eq "attack") || (AI::action eq "move" && AI::action(2) eq "attack"))
&& AI::args->{attackID} && timeOut($AI::Temp::attack_route_adjust, 1)) {
# We're on route to the monster; check whether the monster has moved
my $ID = AI::args->{attackID};
my $attackSeq = (AI::action eq "route") ? AI::args(1) : AI::args(2);
my $monster = $monsters{$ID};

if ($monster && $attackSeq->{monsterPos} && %{$attackSeq->{monsterPos}}
&& distance(calcPosition($monster), $attackSeq->{monsterPos}) > $attackSeq->{attackMethod}{maxDistance}) {
# Monster has moved; stop moving and let the attack AI readjust route
AI::dequeue;
AI::dequeue if (AI::action eq "route");

$attackSeq->{ai_attack_giveup}{time} = time;
debug "Target has moved more than $attackSeq->{attackMethod}{maxDistance} blocks; readjusting route\n", "ai_attack";

} elsif ($monster && $attackSeq->{monsterPos} && %{$attackSeq->{monsterPos}}
&& distance(calcPosition($monster), calcPosition($char)) <= $attackSeq->{attackMethod}{maxDistance}) {
# Monster is within attack range; stop moving
AI::dequeue;
AI::dequeue if (AI::action eq "route");

$attackSeq->{ai_attack_giveup}{time} = time;
debug "Target at ($attackSeq->{monsterPos}{x},$attackSeq->{monsterPos}{y}) is now within " .
"$attackSeq->{attackMethod}{maxDistance} blocks; stop moving\n", "ai_attack";
}
$AI::Temp::attack_route_adjust = time;
}

if (AI::action eq "attack" && timeOut(AI::args->{ai_attack_giveup}) && !$config{attackNoGiveup}) {
my $ID = AI::args->{ID};
$monsters{$ID}{attack_failed} = time if ($monsters{$ID});
AI::dequeue;
message "I cant reach you, i'll leave you alone hehehhh!\n", "ai_attack";
useTeleport(1) if ($config{'teleportAuto_dropTarget'});


} elsif (AI::action eq "attack" && !$monsters{$ai_seq_args[0]{ID}}) {
# Monster died or disappeared
$timeout{'ai_attack'}{'time'} -= $timeout{'ai_attack'}{'timeout'};
my $ID = AI::args->{ID};
AI::dequeue;

if ($monsters_old{$ID} && $monsters_old{$ID}{dead}) {
message "Target died\n", "ai_attack";
monKilled();
$monsters_Killed{$monsters_old{$ID}{'nameID'}}++;

# Pickup loot when monster's dead
if ($config{'itemsTakeAuto'} && $monsters_old{$ID}{dmgFromYou} > 0 && !$monsters_old{$ID}{ignore}) {
AI::clear("items_take");
ai_items_take($monsters_old{$ID}{pos}{x}, $monsters_old{$ID}{pos}{y},
$monsters_old{$ID}{pos_to}{x}, $monsters_old{$ID}{pos_to}{y});
} elsif (!ai_getAggressives()) {
# Cheap way to suspend all movement to make it look real
ai_clientSuspend(0, $timeout{'ai_attack_waitAfterKill'}{'timeout'});
}

## kokal start
## mosters counting
my $i = 0;
my $found = 0;
while ($monsters_Killed[$i]) {
if ($monsters_Killed[$i]{'nameID'} eq $monsters_old{$ID}{'nameID'}) {
$monsters_Killed[$i]{'count'}++;
monsterLog($monsters_Killed[$i]{'name'});
$found = 1;
last;
}
$i++;
}
if (!$found) {
$monsters_Killed[$i]{'nameID'} = $monsters_old{$ID}{'nameID'};
$monsters_Killed[$i]{'name'} = $monsters_old{$ID}{'name'};
$monsters_Killed[$i]{'count'} = 1;
monsterLog($monsters_Killed[$i]{'name'})
}
## kokal end

} else {
message "Target lost\n", "ai_attack";
}

} elsif (AI::action eq "attack") {
# The attack sequence hasn't timed out and the monster is on screen

# Update information about the monster and the current situation
my $args = AI::args;
my $followIndex = AI::findAction("follow");
my $following;
my $followID;
if (defined $followIndex) {
$following = AI::args($followIndex)->{following};
$followID = AI::args($followIndex)->{ID};
}

my $ID = $args->{ID};
my $myPos = $char->{pos_to};
my $monsterPos = $monsters{$ID}{pos_to};
my $monsterDist = distance($myPos, $monsterPos);

my ($realMyPos, $realMonsterPos, $realMonsterDist, $hitYou);
my $realMyPos = calcPosition($char);
my $realMonsterPos = calcPosition($monsters{$ID});
my $realMonsterDist = distance($realMyPos, $realMonsterPos);
if (!$config{'runFromTarget'}) {
$myPos = $realMyPos;
$monsterPos = $realMonsterPos;
}

my $cleanMonster = checkMonsterCleanness($ID);


# If the damage numbers have changed, update the giveup time so we don't timeout
if ($args->{dmgToYou_last} != $monsters{$ID}{dmgToYou}
|| $args->{missedYou_last} != $monsters{$ID}{missedYou}
|| $args->{dmgFromYou_last} != $monsters{$ID}{dmgFromYou}
|| $args->{lastSkillTime} != $char->{last_skill_time}) {
$args->{ai_attack_giveup}{time} = time;
debug "Update attack giveup time\n", "ai_attack", 2;
}
$hitYou = ($args->{dmgToYou_last} != $monsters{$ID}{dmgToYou}
|| $args->{missedYou_last} != $monsters{$ID}{missedYou});
$args->{dmgToYou_last} = $monsters{$ID}{dmgToYou};
$args->{missedYou_last} = $monsters{$ID}{missedYou};
$args->{dmgFromYou_last} = $monsters{$ID}{dmgFromYou};
$args->{missedFromYou_last} = $monsters{$ID}{missedFromYou};
$args->{lastSkillTime} = $char->{last_skill_time};


# Determine what combo skill to use
delete $args->{attackMethod};
my $lastSkill = Skills->new(id => $char->{last_skill_used})->name;
my $i = 0;
while (exists $config{"attackComboSlot_$i"}) {
if (!$config{"attackComboSlot_$i"}) {
$i++;
next;
}

if ($config{"attackComboSlot_${i}_afterSkill"} eq $lastSkill
&& ( !$config{"attackComboSlot_${i}_maxUses"} || $args->{attackComboSlot_uses}{$i} < $config{"attackComboSlot_${i}_maxUses"} )
&& ( !defined($args->{ID}) || $args->{ID} eq $char->{last_skill_target} )
&& checkSelfCondition("attackComboSlot_$i")
&& checkMonsterCondition("attackComboSlot_${i}_target", $monsters{$ID})) {

$args->{attackComboSlot_uses}{$i}++;
delete $char->{last_skill_used};
$args->{attackMethod}{type} = "combo";
$args->{attackMethod}{comboSlot} = $i;
$args->{attackMethod}{distance} = $config{"attackComboSlot_${i}_dist"};
$args->{attackMethod}{maxDistance} = $config{"attackComboSlot_${i}_dist"};
$args->{attackMethod}{isSelfSkill} = $config{"attackComboSlot_${i}_isSelfSkill"};
last;
}
$i++;
}

# Determine what skill to use to attack
if (!$args->{attackMethod}{type}) {
if ($config{'attackUseWeapon'}) {
$args->{attackMethod}{distance} = $config{'attackDistance'};
$args->{attackMethod}{maxDistance} = $config{'attackMaxDistance'};
$args->{attackMethod}{type} = "weapon";
} else {
$args->{attackMethod}{distance} = 30;
$args->{attackMethod}{maxDistance} = 30;
undef $args->{attackMethod}{type};
}

$i = 0;
while (exists $config{"attackSkillSlot_$i"}) {
if (!$config{"attackSkillSlot_$i"}) {
$i++;
next;
}

my $skill = Skills->new(name => $config{"attackSkillSlot_$i"});
if (checkSelfCondition("attackSkillSlot_$i")
&& (!$config{"attackSkillSlot_$i"."_maxUses"} ||
$monsters{$ID}{skillUses}{$skill->handle} < $config{"attackSkillSlot_$i"."_maxUses"})
&& (!$config{"attackSkillSlot_$i"."_maxAttempts"} || $args->{attackSkillSlot_attempts}{$i} < $config{"attackSkillSlot_$i"."_maxAttempts"})
&& (!$config{"attackSkillSlot_$i"."_monsters"} || existsInList($config{"attackSkillSlot_$i"."_monsters"}, $monsters{$ID}{'name'}))
&& (!$config{"attackSkillSlot_$i"."_notMonsters"} || !existsInList($config{"attackSkillSlot_$i"."_notMonsters"}, $monsters{$ID}{'name'}))
&& (!$config{"attackSkillSlot_$i"."_previousDamage"} || inRange($monsters{$ID}{dmgTo}, $config{"attackSkillSlot_$i"."_previousDamage"}))
&& checkMonsterCondition("attackSkillSlot_${i}_target", $monsters{$ID})
) {
$args->{attackSkillSlot_attempts}{$i}++;
$args->{attackMethod}{distance} = $config{"attackSkillSlot_$i"."_dist"};
$args->{attackMethod}{maxDistance} = $config{"attackSkillSlot_$i"."_dist"};
$args->{attackMethod}{type} = "skill";
$args->{attackMethod}{skillSlot} = $i;
last;
}
$i++;
}

if ($config{'runFromTarget'} && $config{'runFromTarget_dist'} > $args->{attackMethod}{distance}) {
$args->{attackMethod}{distance} = $config{'runFromTarget_dist'};
}
}

if ($args->{attackMethod}{maxDistance} < $args->{attackMethod}{distance}) {
$args->{attackMethod}{maxDistance} = $args->{attackMethod}{distance};
}

if ($char->{sitting}) {
ai_setSuspend(0);
stand();

} elsif (!$cleanMonster) {
# Drop target if it's already attacked by someone else
message "Lets Rock! eheheehe!!! ahihihihihi\n", "ai_attack";
sendMove(\$remote_socket, $realMyPos->{x}, $realMyPos->{y});
AI::dequeue;

} elsif ($config{attackCheckLOS} &&
$args->{attackMethod}{distance} > 2 &&
!checkLineSnipable($realMyPos, $realMonsterPos)) {
# We are a ranged attacker without LOS

# Calculate squares around monster within shooting range, but not
# closer than runFromTarget_dist
my @stand = calcRectArea2($realMonsterPos->{x}, $realMonsterPos->{y},
$args->{attackMethod}{distance},
$config{runFromTarget} ? $config{runFromTarget_dist} : 0);

my ($master, $masterPos);
if ($config{follow}) {
foreach (keys %players) {
if ($players{$_}{name} eq $config{followTarget}) {
$master = $players{$_};
last;
}
}
$masterPos = calcPosition($master) if $master;
}

# Determine which of these spots are snipable
my $best_spot;
my $best_dist;
for my $spot (@stand) {
# Is this spot acceptable?
# 1. It must have LOS to the target ($realMonsterPos).
# 2. It must be within $config{followDistanceMax} of
# $masterPos, if we have a master.
if (checkLineSnipable($spot, $realMonsterPos) &&
(!$master || distance($spot, $masterPos) <= $config{followDistanceMax})) {
# FIXME: use route distance, not pythagorean distance
my $dist = distance($realMyPos, $spot);
if (!defined($best_dist) || $dist < $best_dist) {
$best_dist = $dist;
$best_spot = $spot;
}
}
}

# Move to the closest spot
my $msg = "No LOS from ($realMyPos->{x}, $realMyPos->{y}) to target ($realMonsterPos->{x}, $realMonsterPos->{y})";
if ($best_spot) {
message "$msg; moving to ($best_spot->{x}, $best_spot->{y})\n";
ai_route($field{name}, $best_spot->{x}, $best_spot->{y});
} else {
warning "$msg; no acceptable place to stand\n";
AI::dequeue;
}

} elsif ($config{'runFromTarget'} && ($monsterDist < $config{'runFromTarget_dist'} || $hitYou)) {
#my $begin = time;
# Get a list of blocks that we can run to
my @blocks = calcRectArea($myPos->{x}, $myPos->{y},
# If the monster hit you while you're running, then your recorded
# location may be out of date. So we use a smaller distance so we can still move.
($hitYou) ? $config{'runFromTarget_dist'} / 2 : $config{'runFromTarget_dist'});

# Find the distance value of the block that's farthest away from a wall
my $highest;
foreach (@blocks) {
my $dist = ord(substr($field{dstMap}, $_->{y} * $field{width} + $_->{x}));
if (!defined $highest || $dist > $highest) {
$highest = $dist;
}
}

# Get rid of rediculously large route distances (such as spots that are on a hill)
# Get rid of blocks that are near a wall
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{'runFromTarget_dist'} * 2) {
delete $blocks[$i];
next;
}
}

# Find the block that's farthest to us
my $largestDist;
my $bestBlock;
foreach (@blocks) {
next unless defined $_;
my $dist = distance($monsterPos, $_);
if (!defined $largestDist || $dist > $largestDist) {
$largestDist = $dist;
$bestBlock = $_;
}
}

#message "Time spent: " . (time - $begin) . "\n";
#debug_showSpots('runFromTarget', \@blocks, $bestBlock);
AI::args->{avoiding} = 1;
move($bestBlock->{x}, $bestBlock->{y}, $ID);

} elsif (!$config{'runFromTarget'} && $monsterDist > $args->{attackMethod}{maxDistance}
&& timeOut($args->{ai_attack_giveup}, 0.5)) {
# The target monster moved; move to target
$args->{move_start} = time;
$args->{monsterPos} = {%{$monsterPos}};

# Calculate how long it would take to reach the monster.
# Calculate where the monster would be when you've reached its
# previous position.
my $time_needed;
if (objectIsMovingTowards($monsters{$ID}, $char, 45)) {
$time_needed = $monsterDist * $char->{walk_speed};
} else {
# If monster is not moving towards you, then you need more time to walk
$time_needed = $monsterDist * $char->{walk_speed} + 2;
}
my $pos = calcPosition($monsters{$ID}, $time_needed);

my $dist = sprintf("%.1f", $monsterDist);
debug "Target distance $dist is >$args->{attackMethod}{maxDistance}; moving to target: " .
"from ($myPos->{x},$myPos->{y}) to ($pos->{x},$pos->{y})\n", "ai_attack";

my $result = ai_route($field{'name'}, $pos->{x}, $pos->{y},
distFromGoal => $args->{attackMethod}{distance},
maxRouteTime => $config{'attackMaxRouteTime'},
attackID => $ID,
noMapRoute => 1,
noAvoidWalls => 1);
if (!$result) {
# Unable to calculate a route to target
$monsters{$ID}{attack_failed} = time if ($monsters{$ID});
AI::dequeue;
message "Unable to calculate a route to target, dropping target\n", "ai_attack";
}

} elsif ((!$config{'runFromTarget'} || $realMonsterDist >= $config{'runFromTarget_dist'})
&& (!$config{'tankMode'} || !$monsters{$ID}{dmgFromYou})) {
# Attack the target. In case of tanking, only attack if it hasn't been hit once.
if (!AI::args->{firstAttack}) {
AI::args->{firstAttack} = 1;
my $dist = sprintf("%.1f", $monsterDist);
my $pos = "$myPos->{x},$myPos->{y}";
debug "Ready to attack target (which is $dist blocks away); we're at ($pos)\n", "ai_attack";
}

$args->{unstuck}{time} = time if (!$args->{unstuck}{time});
if (!$monsters{$ID}{dmgFromYou} && timeOut($args->{unstuck})) {
# We are close enough to the target, and we're trying to attack it,
# but some time has passed and we still haven't dealed any damage.
# Our recorded position might be out of sync, so try to unstuck
$args->{unstuck}{time} = time;
debug("Attack - trying to unstuck\n", "ai_attack");
move($myPos->{x}, $myPos->{y});
}

if ($args->{attackMethod}{type} eq "weapon" && timeOut($timeout{ai_attack})) {
sendAttack(\$remote_socket, $ID,
($config{'tankMode'}) ? 0 : 7);
$timeout{ai_attack}{time} = time;
delete $args->{attackMethod};

} elsif ($args->{attackMethod}{type} eq "skill") {
my $slot = $args->{attackMethod}{skillSlot};
delete $args->{attackMethod};

ai_setSuspend(0);
if (!ai_getSkillUseType($skills_rlut{lc($config{"attackSkillSlot_$slot"})})) {
ai_skillUse(
$skills_rlut{lc($config{"attackSkillSlot_$slot"})},
$config{"attackSkillSlot_${slot}_lvl"},
$config{"attackSkillSlot_${slot}_maxCastTime"},
$config{"attackSkillSlot_${slot}_minCastTime"},
$config{"attackSkillSlot_${slot}_isSelfSkill"} ? $accountID : $ID,
undef,
"attackSkill");
} else {
ai_skillUse(
$skills_rlut{lc($config{"attackSkillSlot_$slot"})},
$config{"attackSkillSlot_${slot}_lvl"},
$config{"attackSkillSlot_${slot}_maxCastTime"},
$config{"attackSkillSlot_${slot}_minCastTime"},
$monsters{$ID}{pos_to}{x},
$monsters{$ID}{pos_to}{y},
"attackSkill");
}
$args->{monsterID} = $ID;

debug "Auto-skill on monster ".getActorName($ID).": ".qq~$config{"attackSkillSlot_$slot"} (lvl $config{"attackSkillSlot_${slot}_lvl"})\n~, "ai_attack";

} elsif ($args->{attackMethod}{type} eq "combo") {
my $slot = $args->{attackMethod}{comboSlot};
my $isSelfSkill = $args->{attackMethod}{isSelfSkill};
my $skill = Skills->new(name => $config{"attackComboSlot_$slot"})->handle;
delete $args->{attackMethod};

if (!ai_getSkillUseType($skill)) {
my $targetID = ($isSelfSkill) ? $accountID : $ID;
ai_skillUse(
$skill,
$config{"attackComboSlot_${slot}_lvl"},
$config{"attackComboSlot_${slot}_maxCastTime"},
$config{"attackComboSlot_${slot}_minCastTime"},
$targetID,
undef,
undef,
undef,
$config{"attackComboSlot_${slot}_waitBeforeUse"});
} else {
my $pos = ($isSelfSkill) ? $char->{pos_to} : $monsters{$ID}{pos_to};
ai_skillUse(
$skill,
$config{"attackComboSlot_${slot}_lvl"},
$config{"attackComboSlot_${slot}_maxCastTime"},
$config{"attackComboSlot_${slot}_minCastTime"},
$pos->{x},
$pos->{y},
undef,
undef,
$config{"attackComboSlot_${slot}_waitBeforeUse"});
}
$args->{monsterID} = $ID;
}

} elsif ($config{'tankMode'}) {
if ($ai_seq_args[0]{'dmgTo_last'} != $monsters{$ID}{'dmgTo'}) {
$ai_seq_args[0]{'ai_attack_giveup'}{'time'} = time;
}
$ai_seq_args[0]{'dmgTo_last'} = $monsters{$ID}{'dmgTo'};
}
}

# Check for kill steal while moving
if (AI::is("move", "route") && AI::args->{attackID} && AI::inQueue("attack")) {
my $ID = AI::args->{attackID};
if ($monsters{$ID} && !checkMonsterCleanness($ID)) {
message "ooppppss! i got you \n";
stopAttack();
$monsters{$ID}{ignore} = 1;

# Right now, the queue is either
# move, route, attack
# -or-
# route, attack
AI::dequeue;
AI::dequeue;
AI::dequeue if (AI::action eq "attack");
}
}

##### AUTO-ITEM USE #####

praetor
25th August 2005, 18:02
hmmmmmmmmmmmmmmmmmmmmmmmmmmmmm

dezmay
25th August 2005, 18:05
you had posted 2 thread for this KS so which one will be followed and what will be putted at the config.txt?

rubentan
25th August 2005, 18:10
not again..we do not support ksing and this wont work..
-closed