bot fighting function
Posted: Sat Nov 27, 2010 6:15 pm
So im kinda lost and need some help -.-...
im trying to find out how the bot is really working.
Im guessing this is the function where the bot fights?
But I seriously cant find where the bot uses skills and actually kill the mob. Can any experienced in scripts or whatever help me out?
im trying to find out how the bot is really working.
Im guessing this is the function where the bot fights?
Code: Select all
function CPlayer:fight()
self:update();
if( not self:haveTarget() ) then
return false;
end
local target = self:getTarget();
self.IgnoreTarget = target.Address;
self.Fighting = true;
cprintf(cli.green, language[22], target.Name); -- engagin x in combat
-- Keep tapping the attack button once every few seconds
-- just in case the first one didn't go through
local function timedAttack()
self:update();
-- Obsolete. Interferes with undercutting skills
--[[if( self.Casting ) then
-- Don't interupt casting
return;
end;]]
-- Prevents looting when looting is turned off
-- (target is dead, or about to be dead)
if( self.Target ~= 0 ) then
local target = self:getTarget();
if( (target.HP/target.MaxHP) <= 0.1 ) then
return;
end
end;
if( settings.profile.hotkeys.MACRO ) then
RoMScript("UseSkill(1,1);");
else
keyboardPress(settings.profile.hotkeys.ATTACK.key);
end
end
-- Prep for battle, if needed.
--self:checkSkills();
-- local target = self:getTarget(); / double
self.lastHitTime = os.time();
local lastTargetHP = target.HP;
local move_closer_counter = 0; -- count move closer trys
self.Cast_to_target = 0; -- reset counter cast at enemy target
self.ranged_pull = false; -- flag for timed ranged pull for melees
local hf_start_dist = 0; -- distance to mob where we start the fight
-- check if timed ranged pull for melee
if(settings.profile.options.COMBAT_TYPE == "melee" and
settings.profile.options.COMBAT_RANGED_PULL == true and
self.Battling ~= true ) then
self.ranged_pull = true;
cprintf(cli.green, language[96]); -- we start with ranged pulling
end
-- normal melee attack only if ranged pull isn't used
if( settings.profile.options.COMBAT_TYPE == "melee" and
self.ranged_pull ~= true ) then
registerTimer("timedAttack", secondsToTimer(2), timedAttack);
-- start melee attack (even if out of range)
timedAttack();
end
local break_fight = false; -- flag to avoid kill counts for breaked fights
while( self:haveTarget() ) do
self:update();
-- If we die, break
if( self.HP < 1 or self.Alive == false ) then
if( settings.profile.options.COMBAT_TYPE == "melee" ) then
unregisterTimer("timedAttack");
end
self.Fighting = false;
break_fight = true;
-- return;
break;
end;
target = self:getTarget();
if( target.HP ~= lastTargetHP ) then
self.lastHitTime = os.time();
lastTargetHP = target.HP;
end
-- Long time break: Exceeded max fight time (without hurting enemy) so break fighting
if( os.difftime(os.time(), self.lastHitTime) > settings.profile.options.MAX_FIGHT_TIME ) then
printf(language[83]); -- Taking too long to damage target
player.Last_ignore_target_ptr = player.TargetPtr; -- remember break target
player.Last_ignore_target_time = os.time(); -- and the time we break the fight
self:clearTarget();
if( self.Battling ) then
yrest(1000);
keyboardHold( settings.hotkeys.MOVE_BACKWARD.key);
yrest(1000);
keyboardRelease( settings.hotkeys.MOVE_BACKWARD.key);
self:update();
end
break_fight = true;
break;
end
local dist = distance(self.X, self.Z, target.X, target.Z);
if( hf_start_dist == 0 ) then -- remember distance we start the fight
hf_start_dist = dist;
end
-- check if pulling phase should be finished
if( self.ranged_pull == true ) then
if( dist <= settings.options.MELEE_DISTANCE ) then
cprintf(cli.green, language[97]); -- Ranged pulling finished, mob in melee distance
self.ranged_pull = false;
elseif( os.difftime(os.time(), self.aggro_start_time) > 3 and
self.aggro_start_time ~= 0 ) then
cprintf(cli.green, language[98]); -- Ranged pulling after 3 sec wait finished
self.ranged_pull = false;
elseif( dist >= hf_start_dist-45 and -- mob not really coming closer
os.difftime(os.time(), self.aggro_start_time) > 1 and
self.aggro_start_time ~= 0 ) then
cprintf(cli.green, language[99]); -- Ranged pulling finished. Mob not really moving
self.ranged_pull = false;
end;
end
-- We're a bit TOO close...
if( dist < 5.0 and not player.Casting ) then
printf(language[24]);
keyboardHold( settings.hotkeys.MOVE_BACKWARD.key);
yrest(200);
keyboardRelease( settings.hotkeys.MOVE_BACKWARD.key);
self:update();
dist = distance(self.X, self.Z, target.X, target.Z);
end
-- Move closer to the target if needed
local suggestedRange = settings.options.MELEE_DISTANCE;
if( suggestedRange == nil ) then suggestedRange = 45; end;
if( settings.profile.options.COMBAT_TYPE == "ranged" or
self.ranged_pull == true ) then
if( settings.profile.options.COMBAT_DISTANCE ~= nil ) then
suggestedRange = settings.profile.options.COMBAT_DISTANCE;
else
suggestedRange = 155;
end
end
-- check if aggro before attacking
if( self.Battling == true and -- we have aggro
target.HP/target.MaxHP*100 > 90 and -- target is alive and no attacking us
-- Fix: there is a special dog mob 'Tatus', he switch from red to green at about 90%
-- there seems to be a bug, so that sometimes Tatus don't have us into the target but still attacking us
-- to prevent from skipping him while he is still attacking us, we do that special fix
target.Name ~= "Tatus" and
target.TargetPtr ~= self.Address and
target.TargetPtr ~= self.Pet.Address ) then -- but not from that mob
cprintf(cli.green, language[36], target.Name);
self:clearTarget();
break_fight = true;
break;
end;
if( dist > suggestedRange and not player.Casting ) then
-- count move closer and break if to much
move_closer_counter = move_closer_counter + 1; -- count our move tries
if( move_closer_counter > 3 and
(settings.profile.options.COMBAT_TYPE == "ranged" or
self.ranged_pull == true) ) then
cprintf(cli.green, language[84]); -- To much tries to come closer
self:clearTarget();
break_fight = true;
break;
end
printf(language[25], suggestedRange, dist);
-- move into distance
local angle = math.atan2(target.Z - self.Z, target.X - self.X);
local posX, posZ;
local success, reason;
if( settings.profile.options.COMBAT_TYPE == "ranged" or
self.ranged_pull == true ) then -- melees with timed ranged pull
if dist > suggestedRange then -- move closer
movedist = dist - suggestedRange
if movedist < 50 then movedist = 50 end;
posX = self.X + math.cos(angle) * (movedist);
posZ = self.Z + math.sin(angle) * (movedist);
success, reason = self:moveTo(CWaypoint(posX, posZ), true);
end
else -- normal melee
-- elseif( settings.profile.options.COMBAT_TYPE == "melee" ) then
success, reason = self:moveTo(target, true);
-- Start melee attacking
if( settings.profile.options.COMBAT_TYPE == "melee" ) then
timedAttack();
end
end
if( not success ) then
self:unstick();
end
yrest(500);
end
if( settings.profile.options.QUICK_TURN ) then
local angle = math.atan2(target.Z - self.Z, target.X - self.X);
self:faceDirection(angle);
camera:setRotation(angle);
yrest(50);
elseif( settings.options.ENABLE_FIGHT_SLOW_TURN ) then
-- Make sure we're facing the enemy
local angle = math.atan2(target.Z - self.Z, target.X - self.X);
local angleDif = angleDifference(angle, self.Direction);
local correctingAngle = false;
local startTime = os.time();
while( angleDif > math.rad(15) ) do
if( self.HP < 1 or self.Alive == false ) then
self.Fighting = false;
return;
end;
if( os.difftime(os.time(), startTime) > 5 ) then
printf(language[26]);
break;
end;
correctingAngle = true;
if( angleDifference(angle, self.Direction + 0.01) < angleDif ) then
-- rotate left
keyboardRelease( settings.hotkeys.ROTATE_RIGHT.key );
keyboardHold( settings.hotkeys.ROTATE_LEFT.key );
else
-- rotate right
keyboardRelease( settings.hotkeys.ROTATE_LEFT.key );
keyboardHold( settings.hotkeys.ROTATE_RIGHT.key );
end
yrest(100);
self:update();
target:update();
angle = math.atan2(target.Z - self.Z, target.X - self.X);
angleDif = angleDifference(angle, self.Direction);
end
if( correctingAngle ) then
keyboardRelease( settings.hotkeys.ROTATE_LEFT.key );
keyboardRelease( settings.hotkeys.ROTATE_RIGHT.key );
end
end
if( self:checkPotions() or self:checkSkills() ) then
-- If we used a potion or a skill, reset our last dist improvement
-- to prevent unsticking
self.LastDistImprove = os.time();
end
yrest(100);
self:update();
target = self:getTarget();
-- do we need that? Because the DO statement is allready a
-- while( self:haveTarget() statement / I will comment it out and see
-- what happens (d003232, 18.9.09)
-- if( not self:haveTarget() ) then
-- break;
-- end
end
self:resetSkills();
self.Cast_to_target = 0; -- reset cast to target counter
if( settings.profile.options.COMBAT_TYPE == "melee" ) then
unregisterTimer("timedAttack");
end
if( not break_fight) then
-- count kills per target name
local target_Name = target.Name;
if(target_Name == nil) then target_Name = "<UNKNOWN>"; end;
if(self.mobs[target_Name] == nil) then self.mobs[target_Name] = 0; end;
self.mobs[target_Name] = self.mobs[target_Name] + 1;
self.Fights = self.Fights + 1; -- count our fights
cprintf(cli.green, language[27], -- Fight finished. Target dead/lost
self.mobs[target_Name],
target_Name,
self.Fights,
os.difftime(os.time(),
self.BotStartTime_nr)/60);
else
cprintf(cli.green, language[177]); -- Fight aborted
end
-- check if onLeaveCombat event is used in profile
if( type(settings.profile.events.onLeaveCombat) == "function" ) then
local status,err = pcall(settings.profile.events.onLeaveCombat);
if( status == false ) then
local msg = sprintf(language[85], err);
error(msg);
end
end
-- give client a little time to update battle flag (to come out of combat),
-- if we loot even at combat we don't need the time
if( settings.profile.options.LOOT == true and
settings.profile.options.LOOT_IN_COMBAT ~= true ) then
-- yrest(800);
inventory:updateSlotsByTime(800);
end;
-- Monster is dead (0 HP) but still targeted.
-- Loot and clear target.
self:update();
if( not break_fight ) then
self:loot();
end
if( self.TargetPtr ~= 0 ) then
self:clearTarget();
end
self.Fighting = false;
-- update ~ 3-4 slots (about 50 ms each)
inventory:updateSlotsByTime(200);
end