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