bot fighting function

Runes of Magic/Radiant Arcana (http://www.runesofmagic.com)
Post Reply
Message
Author
WhiteTiger
Posts: 84
Joined: Tue Jun 22, 2010 8:06 am

bot fighting function

#1 Post by WhiteTiger »

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?

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
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?
User avatar
Administrator
Site Admin
Posts: 5353
Joined: Sat Jan 05, 2008 4:21 pm

Re: bot fighting function

#2 Post by Administrator »

See player:checkSkills(). It checks which skills are available and uses them appropriately.
WhiteTiger
Posts: 84
Joined: Tue Jun 22, 2010 8:06 am

Re: bot fighting function

#3 Post by WhiteTiger »

shit yeah.. thanx!
the one in

Code: Select all

		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
right?
User avatar
Administrator
Site Admin
Posts: 5353
Joined: Sat Jan 05, 2008 4:21 pm

Re: bot fighting function

#4 Post by Administrator »

Yes. That is where it is called. You'll have to find the actual function if you want to make changes to it. That function, however, then makes use of functions from the CSkill class in skill.lua.
Post Reply