ignore finding already targeted mobs

Runes of Magic/Radiant Arcana (http://www.runesofmagic.com)
Post Reply
Message
Author
ZZZZZ
Posts: 513
Joined: Sun Oct 21, 2012 1:42 am

ignore finding already targeted mobs

#1 Post by ZZZZZ » Wed Apr 16, 2014 6:52 am

Trying to add 3 targets to focus. I was hoping to use findNearestNameOrId() but I am unable to add a table to the ignore value. I tried editing the actual function to include a check for table but it's does not work properly.

Code: Select all

	function Focusgates()   -- gate ID: 112064
		counter = 1
		repeat
		if counter == 1 then
			gate1 = player:findNearestNameOrId(102727)
			if gate1 then
				player:target(gate1.Address)
				RoMScript("FocusUnit("..counter..",'target')")
				print("Focused 1st target")
			end
			yrest(1000);
		elseif counter == 2 then
			gate2 = player:findNearestNameOrId(102727, gate1.Address)
			if gate2 then
				player:target(gate2.Address)
				RoMScript("FocusUnit("..counter..",'target')")
				print("Focused 2nd target")
			end
			yrest(1000);
		elseif counter == 3 then
			gate3 = player:findNearestNameOrId(102727,  {gate1.Address, gate2.Address})
			if gate3 then
				player:target(gate3.Address)
				RoMScript("FocusUnit("..counter..",'target')")
				print("Focused 3rd target")
			end
				yrest(1000);
		end
		counter = counter + 1
		until counter == 4
	end
This is what I tried to change with the findNearestNameOrId function

Code: Select all

function CPlayer:findNearestNameOrId(_objtable, _ignoretable, evalFunc)
	if type(_objtable) == "number" or type(_objtable) == "string" then
		_objtable = {_objtable}
	end
	
	if (_ignoretable ~= nil or _ignoretable ~= 0) then
		_ignoretable = {_ignoretable}
	else
		_ignoretable = {0}
	end
	local closestObject = nil;
	local obj = nil;
	local objectList = CObjectList();
	local ignoreObj = false
	objectList:update();

	if( type(evalFunc) ~= "function" ) then
		evalFunc = function (unused) return true; end;
	end

	self:updateXYZ()
	for i = 0,objectList:size() do
		obj = objectList:getObject(i);

		if( obj ~= nil ) then
			for __, _objnameorid in pairs(_objtable) do
				ignoreObj = false
				for _v,_ignorenameorid in pairs(_ignoretable) do
					if obj.Address == _ignorenameorid then
						ignoreObj = true
						break
					end
				end
				if	(ignoreObj ~= true and obj.Address ~= player.Address and (obj.Id == tonumber(_objnameorid) or string.find(obj.Name, _objnameorid, 1, true) )) then
					if( evalFunc(obj.Address,obj) == true ) then
						if( closestObject == nil ) then
							closestObject = obj;
						else
							if( distance(self.X, self.Z, self.Y, obj.X, obj.Z, obj.Y) <
								distance(self.X, self.Z, self.Y, closestObject.X, closestObject.Z, closestObject.Y) ) then
								-- this node is closer
								closestObject = obj;
							end
						end
					end
				end
			end
		end
	end

   return closestObject;
end
I should probably just take what is there and try to figure out a separate function but there isn't much point if I can't even get this 1 working. I know that it will always return false if _ignorenameorid is not an address but for now that's all I need it to find.

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: ignore finding already targeted mobs

#2 Post by rock5 » Wed Apr 16, 2014 7:48 am

You could use the eval function, eg.

Code: Select all

local gatelist
function evalGate(address, obj)
    obj = obj or CObject(address)
    if not table.contain(gatelist, obj.Address) then
        table.insert(gatelist, obj.Address)
        return true
    else
        return false
    end
end

function Focusgates()
    gatelist = {}
    for counter = 1, 4 do
        local gate = player:findNearestNameOrId(102727,nil,evalGate)
        if gate then
            player:target(gate.Address)
            RoMScript("FocusUnit("..counter..",'target')")
            print("Focused target ".. counter)
        end
        yrest(1000)
    end
end
Something like that. This is untested and assumes the 'gate' variables are not needed later.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

ZZZZZ
Posts: 513
Joined: Sun Oct 21, 2012 1:42 am

Re: ignore finding already targeted mobs

#3 Post by ZZZZZ » Wed Apr 16, 2014 8:09 am

Didn't even know how to apply your own eval function so that helps. Still doesn't work though, only focus's 1 target and then stops.

Code: Select all

Type in 'q' (without quotes) to quit.
Command> ZZFocusgates()
Focused target 1
Command>
Only missed the s on the end of table.contains :)

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: ignore finding already targeted mobs

#4 Post by rock5 » Wed Apr 16, 2014 8:50 am

I can't see anything wrong. Are you sure there are more than 1, what is it, "Acropolis Blade Dancer" near by and in range? I thought you were targeting gates?
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

ZZZZZ
Posts: 513
Joined: Sun Oct 21, 2012 1:42 am

Re: ignore finding already targeted mobs

#5 Post by ZZZZZ » Wed Apr 16, 2014 8:57 am

Im just using that ID to test with, as gates are a pain due to only getting 1 hour every 4 hours to test on. And there are 3 of those where I am standing so it should work...

Code: Select all

function evalGate(address, obj)
    obj = obj or CObject(address)
    if table.contains(gatelist, obj.Address) then
        return false
    else
		table.insert(gatelist, obj.Address)
        return true
    end
end

function ZZFocusgates()
    gatelist = {}
	for i=1,3 do
		RoMScript("FocusUnit("..i..",'')")
	end
    for counter = 1, 3 do
		print(counter)
        gate = player:findNearestNameOrId(102727,nil,evalGate)
		--print(gate.Name)
        if gate then
            player:target(gate.Address)
            RoMScript("FocusUnit("..counter..",'target')")
            print("Focused target ".. counter)
        end
        yrest(1000)
    end
end

Code: Select all

Type in 'q' (without quotes) to quit.
Command> ZZFocusgates()
1
Focused target 1
2
3
Command>

User avatar
lisa
Posts: 8332
Joined: Tue Nov 09, 2010 11:46 pm
Location: Australia

Re: ignore finding already targeted mobs

#6 Post by lisa » Wed Apr 16, 2014 9:23 am

There is more than likely an easier way to do what ever you are trying to actually do, maybe just say what you really want to do and then we can offer better help.

The way I see it you only want 2 things from the gates in SW, you either want to watch if they get attacked or you want to attack them. Focusing them seems like you want to see if they get damaged.

So seems like you want to clear focus on 1,2,3 and then focus the 3 outter gates.

So if that is the case you would simply look through object list and target and focus them that way, no need to use findnearest at all.

Code: Select all

local count = 1
local objectList = CObjectList();
objectList:update();
local objSize = objectList:size()
for i = 0,objSize do
	local obj = objectList:getObject(i);
	if obj.Id == 102727 then
		-- target and focus here and use count for number of focus.
		count = count + 1
	end
end
Remember no matter you do in life to always have a little fun while you are at it ;)

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

ZZZZZ
Posts: 513
Joined: Sun Oct 21, 2012 1:42 am

Re: ignore finding already targeted mobs

#7 Post by ZZZZZ » Wed Apr 16, 2014 9:32 am

That's so much easier xD All 3 focus'ed. I'll have to remember to do that next time... thanks to both of you once again :D

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: ignore finding already targeted mobs

#8 Post by rock5 » Wed Apr 16, 2014 9:36 am

I figured it out. I shouldn't have added the addresses to the list in the eval function. What that causes is it adds all the addresses to the list with the first findNearestNameOrId. I should add the found objects to the list.

Code: Select all

local gatelist
function evalGate(address, obj)
    obj = obj or CObject(address)
    if not table.contains(gatelist, obj.Address) then
        return true
    else
       return false
    end
end

function Focusgates()
    gatelist = {}
    for counter = 1, 4 do
        local gate = player:findNearestNameOrId(102727,nil,evalGate)
        if gate then
			table.insert(gatelist, gate.Address)
            player:target(gate.Address)
            RoMScript("FocusUnit("..counter..",'target')")
            print("Focused target ".. counter)
        end
        yrest(100)
    end
end
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

User avatar
lisa
Posts: 8332
Joined: Tue Nov 09, 2010 11:46 pm
Location: Australia

Re: ignore finding already targeted mobs

#9 Post by lisa » Wed Apr 16, 2014 9:41 am

As a little more info, findNearestNameOrId basically goes through the object list just like the code I posted and it does a distance check and then returns the closest one after going through entire list. I have often wondered if having an option to return all occurances of the ID/Name would be handy, so basically you would return them in a table and in order of closest to furtherest.
Probably be better as a new function though as opposed to changing current function.

local table = player:findNameOrId()

table[1] would be the object of closest object with that name and Id and could use #table to know how many objects there is.

Just a thought I have every now and then, I use that same code I posted for you quite often.

Or maybe could just change findNearestNameOrId so it

return table[1], table

so any existing code would still just have that closest object but second returned value would be entire table, I think that would be handy =)
Remember no matter you do in life to always have a little fun while you are at it ;)

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: ignore finding already targeted mobs

#10 Post by rock5 » Wed Apr 16, 2014 9:55 am

Missed all those previous posts LoL.

Yeah, I would have suggested the loop like Lisa did, just I didn't know if you needed the 'closest' ones or not and adding code to return the closest was too much trouble. That's why I used the eval function. If you don't need the closest then Lisas code is better because it goes though the list only once and doesn't do any unnecessary checks.

As to the function, I think it was never done just because there hasn't been much need for it. There's some but not much. And it's easy enough to create the loop custom to your needs.
Or maybe could just change findNearestNameOrId so it

return table[1], table
Actually, that would be the easiest solution to implement as long as the table is not sorted. If we sorted the table too then that would require a bit more code. I don't know how much time that would add to the processing time. I'd probably leave the sorting to the user to sort the result per their requirements. They might not need it sorted by distance.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

User avatar
lisa
Posts: 8332
Joined: Tue Nov 09, 2010 11:46 pm
Location: Australia

Re: ignore finding already targeted mobs

#11 Post by lisa » Wed Apr 16, 2014 10:10 am

I'd have to test how much sorting actually affects things, time and PC resourcewise.

I use sort quite often and never thought to test that lol


Yeah I was going with the idea findNearest and so that implies wanting a distance check and might need the nearest or next nearest. If you sort them before the return then it is easier to return the nearest object just by using the table, otherwise you need a table of all objects required and also keep seperate the nearest.

I'll see if I can test the sorting tomorrow.
Remember no matter you do in life to always have a little fun while you are at it ;)

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

User avatar
lisa
Posts: 8332
Joined: Tue Nov 09, 2010 11:46 pm
Location: Australia

Re: ignore finding already targeted mobs

#12 Post by lisa » Thu Apr 17, 2014 12:55 am

ok testing done.

Code: Select all

function speedytest(test)
	local tt = {}
	local objectList = CObjectList();
	objectList:update();
	local objSize = objectList:size()
	print(objSize)
	for i = 0,objSize do
		local obj = objectList:getObject(i);
		if obj and test > i then
			obj.distance = distance(obj,player)
			table.insert(tt,obj)
		end
	end
	local timee = getTime()
	-- sort by distance
	local function distancesortfunc(a,b)
		return b.distance > a.distance
	end
	table.sort(tt, distancesortfunc)	
	print(deltaTime(getTime(),timee))
	print(#tt)
	return tt[1], tt
end

Code: Select all

Command> speedytest(10)
88
0.087768373616108
10
Command> speedytest(50)
87
0.67391739507573
50
Command> speedytest(80)
86
1.2600664165354
80
Command> speedytest(80)
86
1.2446684562518
80
Command> speedytest(80)
87
1.3416756060381
80
Command> speedytest(50)
89
0.68931535535926
50
Command> speedytest(5)
89
0.032335716595408
5
Ok so keep in mind it is only sorting the number of "found" objects, so the argument you set how many object to "find"
So with 5 objects the sort takes 0.032 of a second, with 50 it takes 0.689 with 80 it takes roughly 1.3 seconds.

So this is on my OLD laptop that can run 1 RoM and can barely load 2 RoM, I would assume with a PC and decent specs the times would be very very minimal.

Keep in mind it is only sorting found objects, so if there are 3 gates the time taken to sort will be less than 0.03 of a second.

I dunno I think it is worth it but if you are worried about it we could add in an extra arg to do the sorting otherwise it won't sort.

Thoughts?


Had a browse through default bot, 4 occurances of findnearest in player.lua, some in party.lua and 1 in functions.lua. So only ones to worry about are the ones in player.lua.

3 of them use an eval function which will return a small number of objects (ie lootable), so should only add milliseconds to it and 2 of those are an if else end, so only 1 would be done at a time and just after that they do a distance check, I would return the object + the distance, so obj.Distance would be in the table.

1 is looking for a specific NPC name and should only return 1 object.

So yeah I don't see it having a huge strain on default bot.
Remember no matter you do in life to always have a little fun while you are at it ;)

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

User avatar
lisa
Posts: 8332
Joined: Tue Nov 09, 2010 11:46 pm
Location: Australia

Re: ignore finding already targeted mobs

#13 Post by lisa » Thu Apr 17, 2014 1:15 am

ok my bad those times are in milliseconds and not seconds.
So 0.03 is actually 0.00003 of a second lol

Code: Select all

Command> local closest,all = speedytest(5) table.print(closest) table.print(all)

101
0.04824694222172
5
table: 038E44D0
distance:       13.658085800754
Name:   11
Attackable:     false
Z:      -1885.1999511719
Id:     1000
X:      4871.8999023438
Y:      104.9058303833
Type:   1
Address:        681839104
table: 038E3EE0
1:      table: 038E44D0
        distance:       13.658085800754
        Name:   11
        Attackable:     false
        Z:      -1885.1999511719
        Id:     1000
        X:      4871.8999023438
        Y:      104.9058303833
        Type:   1
        Address:        681839104
2:      table: 038E44A8
        distance:       424.10414421787
        Name:   22
        Attackable:     false
        Z:      -2165.2451171875
        Id:     1004
        X:      4543.712890625
        Y:      122.87091064453
        Type:   1
        Address:        681836544
3:      table: 038E4368
        distance:       538.95642029663
        Name:   33
        Attackable:     false
        Z:      -2189.5495605469
        Id:     103510
        X:      5301.1293945313
        Y:      103.055519104
        Type:   1
        Address:        662780928
4:      table: 038E43B8
        distance:       539.0308033348
        Name:   44
        Attackable:     false
        Z:      -2189.5512695313
        Id:     1000
        X:      5301.130859375
        Y:      113.6196975708
        Type:   1
        Address:        662786048
5:      table: 038E4458
        distance:       542.74012196656
        Name:   55
        Attackable:     false
        Z:      -2230
        Id:     1000
        X:      5275
        Y:      103.055519104
        Type:   1
        Address:        662814208
Remember no matter you do in life to always have a little fun while you are at it ;)

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: ignore finding already targeted mobs

#14 Post by rock5 » Thu Apr 17, 2014 2:55 am

lisa wrote:ok my bad those times are in milliseconds and not seconds.
I was going to say that. :)

I guess the important thing is it's basically a user function. The bot uses it's own object list search for things like findEnemy, so it doesn't really matter if it takes a bit longer.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

User avatar
lisa
Posts: 8332
Joined: Tue Nov 09, 2010 11:46 pm
Location: Australia

Re: ignore finding already targeted mobs

#15 Post by lisa » Thu Apr 17, 2014 3:17 am

been using this and did a few chars through minigames without issues.

Code: Select all

function CPlayer:findNearestNameOrId(_objtable, ignore, evalFunc)
	if type(_objtable) == "number" or type(_objtable) == "string" then
		_objtable = {_objtable}
	end
	local foundobjects = {}
	ignore = ignore or 0;
	local closestObject = nil;
	local obj = nil;
	local objectList = CObjectList();
	objectList:update();

	if( type(evalFunc) ~= "function" ) then
		evalFunc = function (unused) return true; end;
	end

	self:updateXYZ()
	for i = 0,objectList:size() do
		obj = objectList:getObject(i);

		if( obj ~= nil ) then
			for __, _objnameorid in pairs(_objtable) do
				if( obj.Address ~= ignore and obj.Address ~= self.Address and (obj.Id == tonumber(_objnameorid) or string.find(obj.Name, _objnameorid, 1, true) )) then
					if( evalFunc(obj.Address,obj) == true ) then
						obj.distance = distance(obj,self)
						table.insert(foundobjects,obj)
					end
				end
			end
		end
	end
	-- sort by distance
	local function distancesortfunc(a,b)
		return b.distance > a.distance
	end
	table.sort(foundobjects, distancesortfunc)
	if #foundobjects ~= 0 then
		return foundobjects[1], foundobjects
	end
	return -- means you found nothing, so returns nil
end
To be honest the code seems easier to follow and looks neater than all the distance checks against previous and such.
Remember no matter you do in life to always have a little fun while you are at it ;)

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: ignore finding already targeted mobs

#16 Post by rock5 » Thu Apr 17, 2014 3:35 am

Pretty straight forward.

Do we want to capitalize distance as per our naming conversions, or because it's a temporary value, it doesn't matter?

Although sorting an empty table doesn't cause any errors or anything I would put the table.sort in the if statement. Why try to sort an empty table?
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

User avatar
lisa
Posts: 8332
Joined: Tue Nov 09, 2010 11:46 pm
Location: Australia

Re: ignore finding already targeted mobs

#17 Post by lisa » Thu Apr 17, 2014 3:53 am

initially I did do .Distance but then the previous code I had for sorting was .distance and I just figured since it isn't going to be in every table then shouldn't matter.

Thinking more on it you are probably right though, .Distance

Code: Select all

function CPlayer:findNearestNameOrId(_objtable, ignore, evalFunc)
	if type(_objtable) == "number" or type(_objtable) == "string" then
		_objtable = {_objtable}
	end
	local foundobjects = {}
	ignore = ignore or 0;
	local closestObject = nil;
	local obj = nil;
	local objectList = CObjectList();
	objectList:update();

	if( type(evalFunc) ~= "function" ) then
		evalFunc = function (unused) return true; end;
	end

	self:updateXYZ()
	for i = 0,objectList:size() do
		obj = objectList:getObject(i);

		if( obj ~= nil ) then
			for __, _objnameorid in pairs(_objtable) do
				if( obj.Address ~= ignore and obj.Address ~= self.Address and (obj.Id == tonumber(_objnameorid) or string.find(obj.Name, _objnameorid, 1, true) )) then
					if( evalFunc(obj.Address,obj) == true ) then
						obj.Distance = distance(obj,self)
						table.insert(foundobjects,obj)
					end
				end
			end
		end
	end
	-- sort by distance
	local function distancesortfunc(a,b)
		return b.Distance > a.Distance
	end
	if #foundobjects ~= 0 then -- sort according to distance first
		table.sort(foundobjects, distancesortfunc)	
		return foundobjects[1], foundobjects -- return closest object, return all objects found
	end
	return -- means you found nothing, so returns nil
end
Remember no matter you do in life to always have a little fun while you are at it ;)

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: ignore finding already targeted mobs

#18 Post by rock5 » Thu Apr 17, 2014 4:41 am

Perfect. :D
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 31 guests