Page 4 of 4

Re: GW2 bot goals & ideas

Posted: Thu Oct 18, 2012 1:29 am
by Administrator
It's not really very functional right now.

Re: GW2 bot goals & ideas

Posted: Mon Oct 22, 2012 4:50 am
by rfehr
Administrator wrote:It's not really very functional right now.
That's not the problem, I still want to test the script,
can you advice me, how to use the Script.

Re: GW2 bot goals & ideas

Posted: Mon Oct 22, 2012 5:37 am
by lisa
rfehr wrote:That's not the problem, I still want to test the script,
can you advice me, how to use the Script.
I am curious how you can use something that is stated as not functional.

It is like having 4 flat tires on your car and saying you will drive it to the shops.

Re: GW2 bot goals & ideas

Posted: Mon Oct 22, 2012 11:28 am
by Chikitor
Lisa wrote:

I am curious how you can use something that is stated as not functional.

It is like having 4 flat tires on your car and saying you will drive it to the shops.

Thats not the problem, He still want to test the script, just give him advice about how to use a non-functional script.

Btw... Im so happy to see that you solarstrikers came over GW2. I played ROM for 3 years and was one of your most unconditional fans. I made some scripts for rom long ago, since you guys gave everyone the tools for people to develop by themselves. I wish I could help you (as an experienced tester) in this new developement adventure, and of course you can count on my little coding experience.

Thanks in advice and good luck in your efforts.

Re: GW2 bot goals & ideas

Posted: Mon Oct 22, 2012 12:31 pm
by Administrator
The scripts can be obtained via SVN.
https://code.google.com/p/gw2-bot/source/checkout

Re: GW2 bot goals & ideas

Posted: Mon Oct 22, 2012 6:05 pm
by lisa
Suddenly takes a holiday to avoid the hundreds of "how do I do this" questions lol

Re: GW2 bot goals & ideas

Posted: Tue Oct 23, 2012 2:31 pm
by Chikitor
About SVN update...

I was testing lisa's V8 script when I read your post about SVN update, so I updated scripts using SVN and guess what... "Permision denied" error. Thats cause some SVN clients like Tortoise (the one I use) has the disappointing manner of creating subfolders in every subfolder and so on. In my case a ".svn" subfolder was created in every single folder of the script folder (wow so many folders in just one phrase...). The error comes when "include" method is called at main.lua and try to include that .svn (its suposed to be just .lua there):

Code: Select all

include("classes/statemanager.lua")
local subdir = getDirectory(getExecutionPath() .. "/classes/states/")
for i,v in pairs(subdir) do	
	include("classes/states/"..v)	-- <<<< We need to avoid any disturbing subfolders like the ones created by svn clients
end
include("romcode.lua")
local version = "lisa V 8"
...
My weird solution (I bet you could code something smarter :) ):

Code: Select all

include("classes/statemanager.lua")
local subdir = getDirectory(getExecutionPath() .. "/classes/states/")
for i,v in pairs(subdir) do
	if v ~= ".svn" then
	include("classes/states/"..v)
	end
end
include("romcode.lua")
local version = "lisa V 8"
...

Re: GW2 bot goals & ideas

Posted: Tue Oct 23, 2012 6:52 pm
by lisa
tortoise SVN doesn't put a .svn folder in every folder, it is only in the initial folder. If you have .svn folders all over the place then you must be doing something wrong.

Just create new folder in /scripts/ and name it what ever you want, I use gw2 and variations of that.

Then right click that new folder, click SVN checkout.
put this in top bit and hit ok.

Code: Select all

https://gw2-bot.googlecode.com/svn/
svn1.jpg
In this image the folder was named gw1.

The only way I can think of you getting so many .svn is if you are using a really old version of tortoise.
Mine isn't the latest,
TortoiseSVN 1.7.7, Build 22907

besides that the code has already been changed a long time ago to only look for .lua files.

Code: Select all

local subdir = getDirectory(getExecutionPath() .. "/functions/")
for i,v in pairs(subdir) do
	if string.find(v,".lua") then
		include("functions/"..v)
	end
end

Re: GW2 bot goals & ideas

Posted: Wed Oct 24, 2012 3:20 am
by Chikitor
The only way I can think of you getting so many .svn is if you are using a really old version of tortoise.
Well I installed tortoise more than 2 years ago when I started using ROMbot and never updated it, so... yes probably its an old version. Also I had your V8 script in a "gw2" folder wich I tried to update, but seems that main.lua and any other file that I had previously in that folder wasn't updated, thats why I got that error, I wasn't using the latest main.lua as I thought. Anyway sorry for the mistake, I was just trying to help, not to make you work more than you use to :)

Re: GW2 bot goals & ideas

Posted: Fri Nov 02, 2012 7:15 pm
by Chikitor
Administrator wrote:It's not really very functional right now.
Well... maybe not really very functional but functional enough to show a smile :)

I've been testing your (and when I say your I refer to all members of solarstrike team) scripts and I found that this bot will be much better than rombot, even better than very functional. The states oriented philosophy is just so smart.

At the momment I haven't tested every script/state but I found AssistState so useful. When I started the script, my elementalist killed like 6 mobs in a row till he got out of targets. In fact you can use it as a static bot. The only problem is that I'm so poor at the momment... what I really need is cash. Even I use scepter/dagger build with my elementalist (what means that mobs use to get closer than with staff build) some mobs are killed far from my character and, as scripts says, loot state still doesn't implement looting far away corpses.

The good thing of AssistState is its smoothnes. Movements between targets seems erratic (less robotic than a waypoint path). The bad thing is that Movements are erratic, so you know where you start but not where you can get into if you go AFK for 2 hours.

I tried to implement a state that I could use while AFK at any spot (without making a new waypoint) and force my elementalist to loot every mob. I also tried to do so respecting your state/event structure (I thont think I succeeded at this point since I had to edit some other states). I doubt that you find useful even just one thing in this stuff, and don't even know if this is the place to post it, or if you aprove or not that users may violate your scrips, but I'll post it anyway just in the hope that someone find it useful.

I called it RadiusState since the radius of hunting area can be entered as a parameter, its based on AssistState but far away less elegant, just neat:

Code: Select all

radius.lua

--[[
	Child of State class.
]]

-- kill/loot in radius zone 
-- will loot monsters in combat if activated in profile
-- Using this state you may die but... usage: gw2/main radius:XXXX (minimum radius of 'maxdistance' will be set)

include("../state.lua");

RadiusState = class(State);

function RadiusState:constructor(originX, originZ, radius)
	self.name = "Radius";
	self.tabtime = getTime();
	self.originX = originX;	
	self.originZ = originZ;	
	if radius and tonumber(radius) >= profile['maxdistance'] then	
		self.radius = tonumber(radius);
	else 		
		self.radius = profile['maxdistance'];
	end	
end

function RadiusState:update()	
	logger:log('debug-states',"Coming to RadiusState:update()");

	statusupdate()		-- update Interaction
	targetupdate()		-- to get target cleared
	
	if distance(player.X, player.Z, self.originX, self.originZ) > self.radius then
			logger:log('info',"Too far from origin, we return origin at: %s %s", self.originX, self.originZ)
			self:returnToOrigin();
	end

	if  player.TargetMob ~= 0 then
		statusupdate()
		coordsupdate()
		if distance(player.X, player.Z, target.TargetX, target.TargetZ) < profile['maxdistance'] and 
		distance(target.TargetX, target.TargetZ,self.originX, self.originZ) < self.radius then
			if distance(player.X, player.Z, target.TargetX, target.TargetZ) < profile['fightdistance'] then
				local newCombat = CombatState()
				logger:log('info',"Target is at skill range, we push combat state");
				newCombat.getNewTarget = false			-- don't get new targets in combat state, just defend
				stateman:pushState(newCombat);
			else
				logger:log('info',"get new target in radius, we push Firstattack state");
				stateman:pushState(FirstattackState());	
			end
		else
			logger:log('info',"Target is too far away, we clear target");
			keyboardPress(key.VK_ESCAPE); --clear target
			self:returnToOrigin();
		end			
	else			--no target
		player:getNextTarget();		--get new target
		if  player.TargetMob == 0 then  --still no target
			--logger:log('info',"no more targets near, we return origin at: %s %s", self.originX, self.originZ)
			self:returnToOrigin();			
		end						
	end

end

function RadiusState:returnToOrigin()
	statusupdate()
	coordsupdate()	
	
	self.tabtime = getTime();	
	
	if distance(player.X, player.Z, self.originX, self.originZ) > profile['fightdistance'] then  --if we are far from origin we return origin			
		player:stopMoving();
		player:stopTurning();				
		local walking = true;
		while (walking) do				
			logger:log('info',"Moving to origin");
			coordsupdate() --Not sure if neccesary
			if distance(player.X, player.Z, self.originX, self.originZ) > profile['fightdistance'] then
				player:moveTo_step(self.originX, self.originZ, math.random()*20);			
				yrest(500);				
			else
				walking = false;
			end
			if ( deltaTime(getTime(), self.tabtime ) > 10000 ) then	-- just 10 secs to move to origin
				walking = false;
			end
		end				
	else	--if we are near origin we just turn around		
		logger:log('info',"Looking around");
		player:moveTo_step(self.originX+(math.random()*100), self.originZ+(math.random()*100), math.random()*100); --random movement
		yrest (1000);		
	end	
	player:stopMoving();
	player:stopTurning();
end

function RadiusState:handleEvent(event)

end

table.insert(events,{name = "Radius", func = RadiusState})
The state to force my lazy elementalist to touch the ground and loot:

Code: Select all

lootincombat.lua

--[[
	Child of State class.
]]

include("../state.lua");

LootInCombatState = class(State);

function LootInCombatState:constructor(corpseX , corpseZ)
	self.name = "LootInCombat";
	self.corpseX = corpseX;
	self.corpseZ = corpseZ;
	self.foundcorpse = false;
	self.movetime = getTime();
end

function LootInCombatState:update()	
	logger:log('debug-states',"Coming to LootInCombatState:update()");	
	coordsupdate()
	if distance(player.X, player.Z, self.corpseX, self.corpseZ) > 100 then		
		while not self.foundcorpse do
			logger:log('info',"Moving towards fallen foe");
			coordsupdate() --Not sure if neccesary
			if distance(player.X, player.Z, self.corpseX, self.corpseZ) > 100 then
				player:moveTo_step(self.corpseX, self.corpseZ, math.random()*20);			
				yrest(500);				
			else
				self.foundcorpse = true;
			end
			if ( deltaTime(getTime(), self.movetime ) > 5000 ) then	-- just 5 secs to find corpse
				self.foundcorpse = true;
			end
		end	
		player:stopTurning();	
		player:stopMoving();		
	end
	statusupdate()
	if player.Interaction == true and player.Ftext ~= language:message('InteractGreeting') and	player.Ftext ~= language:message('InteractTalk') then	
		while (player.Interaction and player.Ftext ~= language:message('InteractGreeting') and	player.Ftext ~= language:message('InteractTalk')) do	    -- try loot till no interaction, just in case you kill more than a mob at same place
			keyboardPress(keySettings['interact']);
			logger:log('info',"Looting corpse at: %s %s", self.corpseX, self.corpseZ);	
			yrest(500);
			statusupdate()
		end							
	else		
		logger:log('info',"No drop");					
	end		
	logger:log('info',"finished looting, popping")
	stateman:popState("loot finished");	
end
table.insert(events,{name = "LootInCombat", func = LootInCombatState})
Simple as a brick... and more dangerous since the character will loot even with several mobs hurting him. Its so dangerous that is a need to disabe it if u want to live so the right place to do it is at profile:

Code: Select all

['lootInCombat'] = true, --I included it just below 'loot' flag 
Unfortunately, I didnt found the way to target corpses. When you kill a mob in game the target dissapears inmediately, so the only way I found to loot a distant mob is to remember its last position. I bet theres a lot of elegant ways (like pushing events with coordinates in eventqueue, etc...) of doing that than messing in combat.lua, but Im lazy...

Code: Select all

combat.lua

....
....
self.wasFighting = false;		-- remember if we have used skill
	self.corpseX = 0;                 -- Not sure if neccesary to include corpse coords	
	self.corpseZ = 0;                 -- here at constructor, but its a way
end
....
....
....
....
targetupdate();
	statusupdate();
	if target.TargetX ~= 0 and target.TargetZ ~= 0 then
		self.corpseX = target.TargetX;             -- everytime we do targetupdate() we refresh
		self.corpseZ = target.TargetZ;             -- the coords of the future mob corpse
	end
....
....
....
....
			self.wasFighting = false
--			if profile['loot'] == true and deltaTime(getTime(), self.startFightTime) > 1000 then	-- ??? why wait ?
			if profile['loot'] == true  then	
				if profile['lootInCombat'] == true then   -- Only for brave ones...					
					stateman:pushState(LootInCombatState(self.corpseX , self.corpseZ));
					stateman:run();  -- had to do this... sorry
				else
					stateman:pushEvent("Loot", "finished combat");
				end
				
			end
			stateman:popState("combat ended");
			return
		end
....
....
....
....
-- no more targets, leave combat state
		if player.TargetMob == 0 then	-- still no target
			if profile['lootInCombat'] == true then		-- force loot before leaving state		
				stateman:pushState(LootInCombatState(self.corpseX , self.corpseZ));
				stateman:run();
			end		
			stateman:popState("end of combat state, no more targets");
			return
		end
....
....

So it will only loot when you have no target, but that doesn't mean that you are not at combat ---> danger.

If combat state is configured to get new targets it may not work properly (target coords will be refreshed and even if lootincombat state is pushed it wont go to propper coordinates) so if you want to ensure looting you should push lootincombat state before get new target routine, just below:

Code: Select all

 else	-- don't have a target
In order to call radius state from main using arguments I had to edit main.lua:

Code: Select all

main.lua

....
....
stateman = StateManager();
	for i = 2,#args do
		local foundpos = string.find(args[i], ":", 1, true);
		if foundpos then
			local var = string.sub(args[i], 1, foundpos-1);
			local val = string.sub(args[i], foundpos+1);
			if( var == "path" ) then
				wpName = val;
			end
			if( var == "multipath" ) then
				multipathName = val;
			end
			if( var == "radius" ) then	-- so usage should be gw2/main radius:10000		
				local radius = val;
				coordsupdate()
				local originX = player.X;
				--local originY = player.Y;
				local originZ = player.Z;
				defaultState = RadiusState(originX, originZ, radius);
				logger:log('info',"Origin set at: %s %s Radius: %s", originX, originZ, radius)
			end
			if( var == "state" ) then
				for k,v in pairs(events) do
					if string.lower(v.name) == string.lower(val) then
						defaultState = v.func();
					end
				end
			end
....
....
I also edited FirstAttack state... I have no reason for this edits, so dont ask much about it:

Code: Select all

firstattack.lua

....
....
if player.TargetMob ~= 0 then
		if profile['maxdistance'] > distance(player.X, player.Z, target.TargetX, target.TargetZ) then
			if player:moveTo_step(target.TargetX, target.TargetZ, profile['fightdistance']) then
				self.starttime = os.time()
				keyboardPress(key.VK_1)
				yrest(1000)
				stateman:popState("first attack done") 		--added this line but can't really explain why		
			end	
		else
			stateman:popState("Target to far away") keyboardPress(key.VK_ESCAPE)
		end
	else
		stateman:popState("first attack popped") return -- returned from combat or loot
	end
	--if os.difftime(os.time(),self.starttime) > 5 then stateman:popState("first attack no damage") keyboardPress(key.VK_ESCAPE) end  -- I comented this line for no special reason
end
....
....
This last edition may be unnecesary but I felt like doing it.

I tested radius state at Kessex Hills for a couple of hours while AFK... I went back just to see how my inventoy got full and how micromacro crashed instantly.So from my point of view this bot is allready a powerful tool... It will be amazing when finished... can't wait to see it :)

This post has the only purpose of encourage other users to test the bot, to mess with it. Although the chance of helping solarstrike team from user efforts is low, most times users experiences can help developers to find and solve new needs. So Solarstrike team: Thanks for this!! and dont be too cruel if you find something horrible above and you feel in the need of hurting me with a sharp object.

Re: GW2 bot goals & ideas

Posted: Fri Nov 02, 2012 9:38 pm
by lisa
Chikitor wrote:Well... maybe not really very functional but functional enough to show a smile
It makes me smile that I didn't have to spend an hour explaining how everything works ;)

I haven't commited my latest version but it gets all mobs direct from memory and targets them using memory, I'll be looking at a "lootable" flag in memory next.

Re: GW2 bot goals & ideas

Posted: Fri Nov 02, 2012 10:30 pm
by Chikitor
Talking about memmory reading... today (after patch) I had lots of memory readin errrors from useskills(). I had to change to useSkillKeypress() even for heal in order to bot for more than 2 minutes :)

Re: GW2 bot goals & ideas

Posted: Sat Nov 03, 2012 12:39 am
by lisa
yeah I'm still not happy with the skill stuff from memory, only bit I like is the skill ID. The cooldowns are unreliable.

In config_default.lua change this setting to true

Code: Select all

SETTINGS['useKeypress'] = true

Re: GW2 bot goals & ideas

Posted: Sat Nov 03, 2012 3:36 pm
by Chikitor
I wonder how you going to handle skills... not many skills to handle but some of them are tricky like ground targeting ones. Game interface will only let you cast those skills at mouse position or at player position if mouse pointer is over game interface (skills, chat, etc...). Anyway casting ground skills at player position can help, so I just let the mouse over the chat whan I go AFK. By the way with actual script skills are used if avaliable, so ground/radius skills doesn't hurt distant mobs. I bet you changed useSkills() in your newest version, but at the momment I added ranges to profile:

Code: Select all

--=== range of the skills (for scepter/dagger elementalist) ===--
	['skill1range'] = 900,
	['skill2range'] = 900,
	['skill3range'] = 240,
	['skill4range'] = 240,
	['skill5range'] = 300,	
	['skill7range'] = 1500, -- Arcane Blast
	['skill8range'] = 360, -- Arcane Wave
	['skill9range'] = 360, -- Arcane shield
And modified if clauses at player.lua including range check:

Code: Select all

if profile['skillXuse'] == true and os.difftime(os.time(),self.skillXused) > profile['skillXcd'] + SETTINGS['lagallowance'] and profile['skillXrange'] >= dist then
...
Not very functional :) since profile edition is needed if you change skills at game, but at least ground target and radius skills get more yield.

Re: GW2 bot goals & ideas

Posted: Sat Nov 03, 2012 7:06 pm
by lisa
yeah skills still need a lot of work, if the game has focus I could move the mouse to point at mobs for ground skills but I don't want the game to be forced to be focus in order to work properly, so trying to avoid that.

The cooldown remaining seems to be kept serverside, if you log out the skills will still have the exact same time remaining on cooldown after you log back in, even if it is a week later. The cooldown remaining doesn't appear to be kept in the same section of memory as other skill info though, still working on that.

I have a lot of R/L stuff going on atm so I'm not spending a huge amount of time working on the bot.