Bot stopped working.. help plz :)

Runes of Magic/Radiant Arcana (http://www.runesofmagic.com)
Post Reply
Message
Author
ginokid
Posts: 35
Joined: Tue Jul 28, 2009 10:30 pm

Bot stopped working.. help plz :)

#1 Post by ginokid » Wed Dec 09, 2009 4:42 pm

I check everyday for updates for the bot. It get's an error now & never did before.
I tried deleting the micromacro folder and reinstalling after I restarted my pc and it didn't help.

Here's the error:

Code: Select all

Wed Dec 09 16:34:27 2009 : Executing script 'bot.lua'
--------------------------------------------------------------------------------

Wed Dec 09 16:34:27 2009 : Language: english
Wed Dec 09 16:34:50 2009 : Using static char address 0x901990, player address 0x15046900
In main thread:
stack traceback:
	...nd Settings/gino/Desktop/micromacro/lib/mods/xml.lua:309: in function 'open'
	...ngs/gino/Desktop/micromacro/scripts/rom/settings.lua:537: in function 'loadProfile'
	scripts\rom\bot.lua:140: in function 'foo'
	...nts and Settings\gino\Desktop\micromacro\lib\lib.lua:489: in function <...nts and Settings\gino\Desktop\micromacro\lib\lib.lua:487>

----------TRACEBACK END----------

Wed Dec 09 16:34:50 2009 : ...ngs/gino/Desktop/micromacro/scripts/rom/settings.lua:537: XML Parse Error.
File: ...sktop/micromacro/scripts/rom/profiles/mycharactername.xml
Line: 95
Column: 4
Message: mismatched tag
Wed Dec 09 16:34:50 2009 : Execution error: Runtime error
Here's my settings.lua

Code: Select all

settings_default = {
	hotkeys = {
		MOVE_FORWARD = {key = _G.key.VK_W, modifier = nil},
		MOVE_BACKWARD = {key = _G.key.VK_S, modifier = nil},
		ROTATE_LEFT = {key = _G.key.VK_A, modifier = nil},
		ROTATE_RIGHT = {key = _G.key.VK_D, modifier = nil},
		STRAFF_LEFT = {key = _G.key.VK_Q, modifier = nil},
		STRAFF_RIGHT = {key = _G.key.VK_E, modifier = nil},
		JUMP = {key = _G.key.VK_SPACE, modifier = nil},
		TARGET = {key = _G.key.VK_TAB, modifier = nil},
		TARGET_FRIEND = {key = _G.key.J, modifier = nil},
		START_BOT = {key = _G.key.VK_DELETE, modifier = nil},
		STOP_BOT = {key = _G.key.VK_END, modifier = nil}
	},
	options = {
		ENABLE_FIGHT_SLOW_TURN = false,
		MELEE_DISTANCE = 45,
		LANGUAGE = "english",
		USE_CLIENT_LANGUAGE = true,		-- automatic use client language after loading the bot
		DEBUGGING = false,
		DEBUGGING_MACRO = false,		
		ROMDATA_PATH = nil,
	},
	profile = {
		options = {
			-- common options
			HP_LOW = 85,
			MP_LOW_POTION = 50,
			HP_LOW_POTION = 40,
			COMBAT_TYPE = "melee",
			COMBAT_RANGED_PULL = "true",	-- only for melee classes , use ranged skill to pull
			COMBAT_DISTANCE = 200,
			ANTI_KS = true,
			WAYPOINTS = "demo.xml",
			RETURNPATH = nil,
			PATH_TYPE = "waypoints",
			WANDER_RADIUS = 500,
			WAYPOINT_DEVIATION = 0,
			LOOT = true,
			LOOT_TIME = 2000,
			LOOT_AGAIN = 2000,				-- second loot try if rooted after x ms
			LOOT_IN_COMBAT = true,
			LOOT_DISTANCE = nil,
			LOOT_PAUSE_AFTER = 10,			-- probability in % for short pause after loot to look more human
			MAX_FIGHT_TIME = 12,
			DOT_PERCENT = 90,
			LOGOUT_TIME = 0,
			LOGOUT_SHUTDOWN = false,
			LOGOUT_WHEN_STUCK = true,
			MAX_UNSTICK_TRIALS = 10,
			TARGET_LEVELDIF_BELOW = 99,
			TARGET_LEVELDIF_ABOVE = 99,
			QUICK_TURN = false,
			MP_REST = 15,
			HP_REST = 15,
			RES_AUTOMATIC_AFTER_DEATH = false,	-- automatic resurrect after death true|false,
			HEALING_POTION = 0,				-- shopping options, how many to buy/have in inventory
			MANA_POTION = 0,				-- shopping options, how many to buy/have in inventory
			ARRAY_QUIVER = 0,				-- shopping options, how many to buy/have in inventory
			THROWN_BAG = 0,					-- shopping options, how many to buy/have in inventory
			POISON = 0,						-- shopping options, how many to buy/have in inventory
			RELOAD_AMMUNITION = false,		-- false|arrow|thrown

			
			-- expert options
			MAX_SKILLUSE_NODMG = 3,				-- maximum casts without damaging the target before break it
			MAX_TARGET_DIST = 999,			-- maximum distance to select a target (helpfull to limit at small places)
			AUTO_ELITE_FACTOR = 5,			-- mobs with x * your HP value counts as 'Elite' and we will not target it
			AUTO_TARGET = true,				-- bot will target mobs automaticly (set it to false if you want to use the bot only as fight support)
			SKILL_GLOBALCOOLDOWN = 1200,	-- Global Skill Use Cooldown (1000ms) we use a little more
			SKILL_USE_PRIOR = 0,			-- cast x ms before cooldown is finished
			PK_COUNTS_AS_DEATH = true,		-- count playerkill's as death
			POTION_COOLDOWN = 15,			-- always 15
			POTION_COOLDOWN_HP = 0,			-- will only be used if not 0, if 0 POTION_COOLDOWN will be used
			POTION_COOLDOWN_MANA = 0,		-- will only be used if not 0, if 0 POTION_COOLDOWN will be used
			SIT_WHILE_RESTING = false,		-- sit while using the rest function
			USE_MANA_POTION = "best",		-- which mana potion type to use: best | minstack
			USE_HP_POTION = "best",			-- which HP potion type to use: best | minstack 			
			WAYPOINTS_REVERSE = false,		-- use the waypoint file in reverse order
			WAYPOINT_PASS = 100,			-- skip a waypoint if we pass in distance x while fighting a mob (go to as melee)
			WAYPOINT_PASS_DEGR = 90,		-- skip a waypoint if we touched one and the next is at least x degrees in front
			MAX_DEATHS = 10,				-- maximal death if automatic resurrect befor logout
			WAIT_TIME_AFTER_RES = 8000,		-- time to wait after resurrection, needs more on slow PCs
			RETURNPATH_SUFFIX = "_return",	-- suffix for default naming of returnpath
			HARVEST_SCAN_WIDTH = 5,			-- steps horizontal
			HARVEST_SCAN_HEIGHT = 5,		-- steps vertical
			HARVEST_SCAN_STEPSIZE = 60,		-- wide of every step
			HARVEST_SCAN_TOPDOWN = false,	-- true = top->down  false = botton->up
			HARVEST_SCAN_XMULTIPLIER = 1.0,	-- multiplier for scan width
			HARVEST_SCAN_YMULTIPLIER = 1.1,	-- multiplier for scan line height
			HARVEST_SCAN_YREST = 10,		-- scanspeed
			HARVEST_SCAN_YMOVE = 1.1,		-- move scan area top/down ( 1=middle of screen )
			HARVEST_TIME = 45,				-- how long we maximum harvest a node
			USE_SLEEP_AFTER_RESUME = false, -- enter sleep mode after pressing pause/resume key
			IGNORE_MACRO_ERROR = false, 	-- ignore missing MACRO hotkey error (only temporary option while beta)
			DEBUG_INV = false,	 			-- to help to find the item use error (only temporary option while beta)
			DEBUG_LOOT = false,	 			-- debug loot issues
			DEBUG_TARGET = false, 			-- debug targeting issues
			DEBUG_HARVEST = false, 			-- debug harvesting issues
			DEBUG_WAYPOINT = false, 		-- debug waypoint issues
			DEBUG_AUTOSELL = false, 		-- debug autosell issues
			
			-- debug skill use issues
			DEBUG_SKILLUSE = {
				ENABLE 		= false,
				TIMEGAP		= true,		-- show the time gap between cast starts
				ONCOOLDOWN	= true,		-- show the time in ms that we are before the cooldown
				NOCOOLDOWN	= true,		-- show the time in ms that we are over the cooldown
				HPLOW		= true 
				},
			
			-- expert inventar
			INV_MAX_SLOTS = 60,	 			-- maximal slots to update in the inventory:update()
			INV_UPDATE_INTERVAL = 300,	 	-- full inventory update every x seconds (only used indirect atm)
			INV_AUTOSELL_ENABLE = false,	-- autosell items at merchant true|false
			INV_AUTOSELL_FROMSLOT = 0,		-- autosell from slot #
			INV_AUTOSELL_TOSLOT = 0,		-- autosell to slot #
			INV_AUTOSELL_QUALITY = "white",	-- itemcolors to sell
			INV_AUTOSELL_IGNORE = nil,		-- itemnames never so sell
			INV_AUTOSELL_NOSELL_DURA = 0,	-- durability > x will not sell, 0=sell all
			INV_AUTOSELL_STATS_NOSELL = nil,	-- stats (text search at right tooltip side) that will not be selled
			INV_AUTOSELL_STATS_SELL = nil,		-- stats (text search at right tooltip side) that will be selled, even if in nosell

			
		},	
		hotkeys = {  }, 
		skills = {}, 
		friends = {},
		mobs = {},
		events = {
			onDeath = nil,
			onLoad = nil,
			onLeaveCombat = nil,
			onSkillCast = nil,
			onLevelup = nil,
		}
	},
};

bot =	{ 		-- global bot values
		ClientLanguage,		-- ingame language of the game [ DE|RU|FR|ENUS|ENEU 
		GetTimeFrequency,	-- calculated CPU frequency for calculating with the getTime() function
		LastSkillKeypressTime = getTime(),	-- remember last time we cast (press key)
		IgfAddon = false,	-- check if igf addon is active
		};		

settings = settings_default;

check_keys = { name = { } };
function checkKeySettings( _name, _key, _modifier)
-- args are the VK in stringform like "VK_CONTROL", "VK_J", ..

	local hf_check_where;
	if( bindings ) then	-- keys are from bindings.txt
		hf_check_where = language[141];		-- Datei settings.xml
	else
		hf_check_where = language[140];		-- Ingame -> System -> Tastenbelegung
	end
	
	local msg = nil;
	-- no empty keys pls
	if( _key == nil) then
		msg = sprintf(language[115], _name);	-- key for \'%s\' is empty!
		msg = msg .. hf_check_where;
	end

	-- check if all keys are valid virtual keys (VK)
	if( _key ) then
		if( key[_key]  == nil  and
			string.upper(_key) ~= "MACRO" ) then	-- hotekey MACRO is a special case / it's not a virtual key
			msg = sprintf(language[116], _key, _name);	-- The hotkey ... is not a valid key
			msg = msg .. hf_check_where;
		end
	end;

	-- no modifiers allowed at the moment
	if( _modifier ) then
		if( key[_modifier]  == nil ) then
			msg = sprintf(language[117], _modifier, _name);	-- The modifier ... is not a valid key
			msg = msg .. hf_check_where;
		end
	end;

	-- now we check for double key settings
	-- we translate the strings "VK..." to the VK numbers
	if( string.upper(_key) ~= "MACRO" ) then
		_key = key[_key];
	end
	_modifier = key[_modifier];

	-- check the using of modifiers
	-- they are not usable at the moment
	if( _modifier ~= nil) then
		msg = sprintf(language[118], -- we don't support modifiers
		   getKeyName(_modifier), getKeyName(_key), _name);

	end

	-- error output
	if( msg ~= nil) then
		-- only a warning for TARGET_FRIEND / else an error
		if(_name == "TARGET_FRIEND") then
			cprintf(cli.yellow, msg .. language[119]);	-- can't use the player:target_NPC() function
		else
			error(msg, 0);
		end
	end

	-- check for double key settings
	for i,v in pairs(check_keys) do
		if( v.name ~= _nil and	-- empty entries from deleted settings.xml entries
		    v.key == _key  and
		    string.upper(_key) ~= "MACRO" and	-- hotkey MACRO is allowed to set more then once
		    v.modifier == _modifier ) then
			local modname;

			if( v.modifier ) then 
				modname = getKeyName(v.modifier).."+";
			else
				modname = "";
			end;

			local errstr = sprintf(language[121],	-- assigned the key \'%s%s\' double
				modname, 
				getKeyName(v.key), 
				v.name, _name) .. 
				hf_check_where;
			error(errstr, 0);
		end
	end;

	check_keys[_name] = {};
	check_keys[_name].name = _name;
	check_keys[_name].key = _key;
	check_keys[_name].modifier = _modifier;

end


function settingsPrintKeys()
-- That function prints the loaded key settings to the MM window and to the log

	local msg;
	msg ="QUICK_TURN = "..tostring(settings.profile.options.QUICK_TURN);	-- we wander around
	logMessage(msg);		-- log keyboard settings
	
	if( bindings ) then		-- we read from bindings.txt
		msg = sprintf(language[167], "bindings.txt");	-- Keyboard settings are from
	else				-- we read settings.xml
		msg = sprintf(language[167], "settings.xml");	-- Keyboard settings are from
	end

--	cprintf(cli.green, msg.."\n");	-- Keyboard settings are from
	logMessage(msg);		-- log keyboard settings

	for i,v in pairs(check_keys) do

		if(v.name) then

			msg = string.sub(v.name.."                               ", 1, 30);	-- function name

			local modname;
			if( v.modifier ) then 
				modname = getKeyName(v.modifier).."+";	-- modifier name
			else
				modname = "";
			end;
			
			local keyname;
			if( string.upper(v.key) == "MACRO" ) then
				keyname = "MACRO";
			else
				keyname = getKeyName(v.key);
			end
			
			msg = msg..modname..keyname;	-- add key name
--			printf(msg.."\n");			-- print line
			logMessage(msg);			-- log keyboard settings
		
		end;
	end;

end


function settings.load()
	local filename = getExecutionPath() .. "/settings.xml";
	local root = xml.open(filename);
	local elements = root:getElements();
	check_keys = { };	-- clear table, because of restart from createpath.lua

	-- Specific to loading the hotkeys section of the file
	local loadHotkeys = function (node)
		local elements = node:getElements();
		for i,v in pairs(elements) do
			-- If the hotkey doesn't exist, create it.
			settings.hotkeys[ v:getAttribute("description") ] = { };
			settings.hotkeys[ v:getAttribute("description") ].key = key[v:getAttribute("key")];
			settings.hotkeys[ v:getAttribute("description") ].modifier = key[v:getAttribute("modifier")];

			if( key[v:getAttribute("key")] == nil ) then
				local err = sprintf(language[122],	-- does not have a valid hotkey!
				  v:getAttribute("description"));
				error(err, 0);
			end

			checkKeySettings( v:getAttribute("description"),
			  v:getAttribute("key"), 
			  v:getAttribute("modifier") );
		end
	end

	local loadOptions = function (node)
		local elements = node:getElements();
		for i,v in pairs(elements) do
			settings.options[ v:getAttribute("name") ] = v:getAttribute("value");
		end
	end

	-- Load RoM keyboard bindings.txt file
	local function load_RoM_bindings_txt()
		local filename, file;
		
		local userprofilePath = os.getenv("USERPROFILE");
		local documentPaths = {
			userprofilePath .. "\\My Documents\\" .. "Runes of Magic", -- English
			userprofilePath .. "\\Eigene Dateien\\" .. "Runes of Magic", -- German
			userprofilePath .. "\\Mes Documents\\" .. "Runes of Magic", -- French
			userprofilePath .. "\\Omat tiedostot\\" .. "Runes of Magic", -- Finish
			userprofilePath .. "\\Belgelerim\\" .. "Runes of Magic", -- Turkish
			userprofilePath .. "\\Mina Dokument\\" .. "Runes of Magic", -- Swedish
			userprofilePath .. "\\Dokumenter\\" .. "Runes of Magic", -- Danish
			userprofilePath .. "\\Documenti\\" .. "Runes of Magic", -- Italian
			userprofilePath .. "\\Mijn documenten\\" .. "Runes of Magic", -- Dutch
			userprofilePath .. "\\Moje dokumenty\\" .. "Runes of Magic", -- Polish
			userprofilePath .. "\\Mis documentos\\" .. "Runes of Magic", -- Spanish
		};

		-- Use a user-specified path from settings.xml
		if( settings.options.ROMDATA_PATH ) then
			table.insert(documentPaths, settings.options.ROMDATA_PATH);
		end

		-- Select the first path that exists
		for i,v in pairs(documentPaths) do
			if( string.sub(v, -1 ) ~= "\\" and string.sub(v, -1 ) ~= "/" ) then
				v = v .. "\\"; -- Append the trailing backslash if necessary.
			end

			local filename = v .. "bindings.txt"
			if( fileExists(filename) ) then
				file = io.open(filename, "r");
				local tmp = filename;
				cprintf(cli.green, language[123], filename);	-- read the hotkey settings from your bindings.txt
			end
		end

		-- If we wern't able to locate a document path, return.
		if( file == nil ) then
			return;
		end

		-- delete hotkeys from settings.xml in check table to avoid double entries / wrong checks
		check_keys["MOVE_FORWARD"] = nil;
		check_keys["MOVE_BACKWARD"] = nil;
		check_keys["ROTATE_LEFT"] = nil;
		check_keys["ROTATE_RIGHT"] = nil;
		check_keys["STRAFF_LEFT"] = nil;
		check_keys["STRAFF_RIGHT"] = nil;
		check_keys["JUMP"] = nil;
		check_keys["TARGET"] = nil;
		check_keys["TARGET_FRIEND"] = nil;
		
		-- Load bindings.txt into own table structure
		bindings = { name = { } };
		-- read the lines in table 'lines'
		for line in file:lines() do
			for name, key1, key2 in string.gfind(line, "(%w*)%s([%w+]*)%s*([%w+]*)") do
				bindings[name] = {};
				bindings[name].key1 = key1;
				bindings[name].key2 = key2;

				--settings.hotkeys[name].key = 
			end
		end

		local function bindHotkey(bindingName)
			local links = { -- Links forward binding names to hotkey names
				MOVEFORWARD = "MOVE_FORWARD",
				MOVEBACKWARD = "MOVE_BACKWARD",
				TURNLEFT = "ROTATE_LEFT",
				TURNRIGHT = "ROTATE_RIGHT",
				STRAFELEFT = "STRAFF_LEFT",
				STRAFERIGHT = "STRAFF_RIGHT",
				JUMP = "JUMP",
				TARGETNEARESTENEMY = "TARGET",
				TARGETNEARESTFRIEND = "TARGET_FRIEND",	
			};

			local hotkeyName = bindingName;
			if(links[bindingName] ~= nil) then
				hotkeyName = links[bindingName];
			end;


			if( bindings[bindingName] ~= nil ) then
				if( bindings[bindingName].key1 ~= nil ) then
					-- Fix key names
					bindings[bindingName].key1 = string.gsub(bindings[bindingName].key1, "CTRL", "CONTROL");

					if( string.find(bindings[bindingName].key1, '+') ) then
						local parts = explode(bindings[bindingName].key1, '+');
						-- parts[1] = modifier
						-- parts[2] = key

						settings.hotkeys[hotkeyName].key = key["VK_" .. parts[2]];
						settings.hotkeys[hotkeyName].modifier = key["VK_" .. parts[1]];
						checkKeySettings(hotkeyName, "VK_" .. parts[2], "VK_" .. parts[1] );
					else
						settings.hotkeys[hotkeyName].key = key["VK_" .. bindings[bindingName].key1];
						checkKeySettings(hotkeyName, "VK_" .. bindings[bindingName].key1 );
					end
					
				else
					local err = sprintf(language[124], bindingName);	-- no ingame hotkey for
					error(err, 0);
				end
			end
		end

		bindHotkey("MOVEFORWARD");
		bindHotkey("MOVEBACKWARD");
		bindHotkey("TURNLEFT");
		bindHotkey("TURNRIGHT");
		bindHotkey("STRAFELEFT");
		bindHotkey("STRAFERIGHT");
		bindHotkey("JUMP");
		bindHotkey("TARGETNEARESTENEMY");
		bindHotkey("TARGETNEARESTFRIEND");
	end

	-- check ingame settings
	-- only if we can find the bindings.txt file
	local function check_ingame_settings( _name, _ingame_key)
	-- no more needed, because we take the keys from the file if we found the file
		
		if( not bindings ) then		-- no bindings.txt file loaded
			return
		end;
		
		if( settings.hotkeys[_name].key ~= key["VK_"..bindings[_ingame_key].key1] and
		settings.hotkeys[_name].key ~= key["VK_"..bindings[_ingame_key].key2] ) then
			local msg = sprintf(language[125], _name);	-- settings.xml don't match your RoM ingame
			error(msg, 0);
		end
	end


	function checkHotkeys(_name, _ingame_key)
		if( not settings.hotkeys[_name] ) then
			error(language[126] .. _name, 0);	-- Global hotkey not set
		end
		
		-- check if settings.lua hotkeys match the RoM ingame settings
		-- check_ingame_settings( _name, _ingame_key);
	end


	for i,v in pairs(elements) do
		local name = v:getName();

		if( string.lower(name) == "hotkeys" ) then
			loadHotkeys(v);
		elseif( string.lower(name) == "options" ) then
			loadOptions(v);
		end
	end


-- TODO: don't work at the moment, becaus MACRO hotkey not available at this time
-- will first be available after reading profile file
	-- read language from client if not set in settings.xml
--	if( not settings.options.LANGUAGE ) then
--		local hf_language = RoMScript("GetLanguage();");	-- read clients language
--		if( hf_language == "DE" ) then
--			settings.options.LANGUAGE = "deutsch";
--		elseif(hf_language == "ENEU" ) then
--			settings.options.LANGUAGE = "english";
--		elseif(hf_language == "FR" ) then
--			settings.options.LANGUAGE = "french";
--		else
--			settings.options.LANGUAGE = "english";		
--		end
--	end

	-- Load language files
	-- Load "english" first, to fill in any gaps in the users' set language.
	local function setLanguage(name)
		include("/language/" .. name .. ".lua");
	end

	local lang_base = {};
	setLanguage("english");
	for i,v in pairs(language) do lang_base[i] = v; end;
	setLanguage(settings.options.LANGUAGE);
	for i,v in pairs(lang_base) do
		if( language[i] == nil ) then
			language[i] = v;
		end
	end;
	lang_base = nil; -- Not needed anymore, destroy it.
	logMessage("Language: " .. settings.options.LANGUAGE);


	load_RoM_bindings_txt();	-- read bindings.txt from RoM user folder

	-- Check to make sure everything important is set
	--           bot hotkey name    RoM ingame key name         
	checkHotkeys("MOVE_FORWARD",   "MOVEFORWARD");
	checkHotkeys("MOVE_BACKWARD",  "MOVEBACKWARD");
	checkHotkeys("ROTATE_LEFT",    "TURNLEFT");
	checkHotkeys("ROTATE_RIGHT",   "TURNRIGHT");
	checkHotkeys("STRAFF_LEFT",    "STRAFELEFT");
	checkHotkeys("STRAFF_RIGHT",   "STRAFERIGHT");
	checkHotkeys("JUMP",           "JUMP");
	checkHotkeys("TARGET",         "TARGETNEARESTENEMY");
	checkHotkeys("TARGET_FRIEND",  "TARGETNEARESTFRIEND");
	
end


function settings.loadProfile(_name)
	-- Delete old profile settings (if they even exist), restore defaults
	settings.profile = settings_default.profile;

	local filename = getExecutionPath() .. "/profiles/" .. _name .. ".xml";
	local root = xml.open(filename);
	local elements = root:getElements();

	local loadOptions = function(node)
		local elements = node:getElements();

		for i,v in pairs(elements) do
			settings.profile.options[v:getAttribute("name")] = v:getAttribute("value");
		end
	end

	local loadHotkeys = function(node)
		local elements = node:getElements();

		for i,v in pairs(elements) do
			settings.profile.hotkeys[v:getAttribute("name")] = {};
			settings.profile.hotkeys[v:getAttribute("name")].name = v:getAttribute("name");
			settings.profile.hotkeys[v:getAttribute("name")].key = key[v:getAttribute("key")];
			settings.profile.hotkeys[v:getAttribute("name")].modifier = key[v:getAttribute("modifier")];

			if( key[v:getAttribute("key")] == nil ) then
				local err = sprintf(language[127], tostring(v:getAttribute("name")), _name );	-- Please set a valid key
				error(err, 0);
			end

			checkKeySettings(v:getAttribute("name"),
			  v:getAttribute("key"), 
			  v:getAttribute("modifier") );

		end
	end

	local loadOnLoadEvent = function(node)
		local luaCode = node:getValue();
		if( luaCode == nil ) then return; end;

		if( string.len(luaCode) > 0 and string.find(luaCode, "%w") ) then
			settings.profile.events.onLoad = loadstring(luaCode);
			assert(settings.profile.events.onLoad, sprintf(language[151], "onLoad"));

			if( type(settings.profile.events.onLoad) ~= "function" ) then
				settings.profile.events.onLoad = nil;
			end;
		end
	end

	local loadOnDeathEvent = function(node)
		local luaCode = node:getValue();
		if( luaCode == nil ) then return; end;

		if( string.len(luaCode) > 0 and string.find(luaCode, "%w") ) then
			settings.profile.events.onDeath = loadstring(luaCode);
			
			assert(settings.profile.events.onDeath, sprintf(language[151], "onDeath"));

			if( type(settings.profile.events.onDeath) ~= "function" ) then
				settings.profile.events.onDeath = nil;
			end;
		end
	end

	local loadOnLeaveCombatEvent = function(node)
		local luaCode = node:getValue();
		if( luaCode == nil ) then return; end;

		if( string.len(luaCode) > 0 and string.find(luaCode, "%w") ) then
			settings.profile.events.onLeaveCombat = loadstring(luaCode);
			assert(settings.profile.events.onLeaveCombat, sprintf(language[151], "onLeaveCombat"));

			if( type(settings.profile.events.onLeaveCombat) ~= "function" ) then
				settings.profile.events.onLeaveCombat = nil;
			end;
		end
	end

	local loadOnLevelupEvent = function(node)
		local luaCode = node:getValue();
		if( luaCode == nil ) then return; end;

		if( string.len(luaCode) > 0 and string.find(luaCode, "%w") ) then
			settings.profile.events.onLevelup = loadstring(luaCode);
			assert(settings.profile.events.onLevelup, sprintf(language[151], "onLevelup"));

			if( type(settings.profile.events.onLevelup) ~= "function" ) then
				settings.profile.events.onLevelup = nil;
			end;
		end
	end

	local loadOnSkillCastEvent = function(node)
		local luaCode = node:getValue();
		if( luaCode == nil ) then return; end;

		if( string.len(luaCode) > 0 and string.find(luaCode, "%w") ) then
			settings.profile.events.onSkillCast= loadstring(luaCode);
			assert(settings.profile.events.onSkillCast, sprintf(language[151], "onSkillCast"));

			if( type(settings.profile.events.onSkillCast) ~= "function" ) then
				settings.profile.events.onSkillCast = nil;
			end;
		end
	end


	local skillSort = function(tab1, tab2)
		if( tab2.priority < tab1.priority ) then
			return true;
		end;

		return false;
	end

	local loadSkills = function(node)
		local elements = node:getElements();

		for i,v in pairs(elements) do
			local name, hotkey, modifier, level;
			name = v:getAttribute("name");
--			hotkey = key[v:getAttribute("hotkey")];
			modifier = key[v:getAttribute("modifier")];
			level = v:getAttribute("level");

			-- using the MACRO key as hotkey is also a valid key
			if( string.upper( v:getAttribute("hotkey") ) == "MACRO" ) then
				hotkey = "MACRO";						-- set MACRO as hotkey
			else
				hotkey = key[v:getAttribute("hotkey")];	-- read the virtual key numer
			end

			checkKeySettings( v:getAttribute("name"),
			  v:getAttribute("hotkey"), 
			  v:getAttribute("modifier") );

			-- Over-ride attributes
			local priority, maxhpper, maxmanaper, cooldown, inbattle, pullonly, maxuse, autouse, rebuffcut;
			priority = v:getAttribute("priority");
			maxhpper = tonumber(v:getAttribute("hpper"));
			targetmaxhpper = tonumber(v:getAttribute("targethpper"));
			targetmaxhp = tonumber(v:getAttribute("targethp"));
			maxmanaper = tonumber(v:getAttribute("manaper"));
			cooldown = tonumber(v:getAttribute("cooldown"));
			inbattle = v:getAttribute("inbattle");
			pullonly = v:getAttribute("pullonly");
			maxuse = tonumber(v:getAttribute("maxuse"));
			rebuffcut = tonumber(v:getAttribute("rebuffcut"));
			autouse = v:getAttribute("autouse");
		-- Ensure that autouse is a proper type.
			if( not (autouse == true or autouse == false) ) then
				autouse = true;
			end;


			-- check if 'wrong' options are set
			if( v:getAttribute("mana")      or
			    v:getAttribute("manainc")   or
			    v:getAttribute("rage")      or
			    v:getAttribute("energy")    or
			    v:getAttribute("concentration")      or
			    v:getAttribute("range")     or
			    v:getAttribute("minrange")  or
			    v:getAttribute("type")      or
			    v:getAttribute("target")    or
			    v:getAttribute("casttime") ) then
					local msg = sprintf(language[128], name, _name);	-- are no valid options for your skill
					error(msg, 0);
			end;
			if( v:getAttribute("modifier") ) then
				local msg = sprintf(language[129], name, _name);	-- modifier not supported

				error(msg, 0);
			end;

			if( name == nil) then
				local msg = sprintf(language[130], _name);	-- empty\' skill name
				error(msg, 0);
			end;

			if( inbattle ~= nil ) then
				if( inbattle == "true" or 
					inbattle == true ) then
					inbattle = true;
				elseif( inbattle == "false"  or
					inbattle == false ) then
					inbattle = false;
				else
					local msg = sprintf(language[131], inbattle, name, _name);	-- wrong option inbattle

					error(msg, 0);
				end;
			end

			if( pullonly ~= nil ) then
				if( pullonly == "true" or
					pullonly == true ) then
					pullonly = true;
				else
					local msg = sprintf(language[132], pullonly, name, _name);	-- wrong option pullonly

					error(msg, 0);
				end;
			end

			if( level == nil or level < 1 ) then
				level = 1;
			end

			local baseskill = database.skills[name];
			if( not baseskill ) then
				local err = sprintf("ERROR: \'%s\' is not defined in the database!", name);
				error(err, 0);
			end

			local tmp = CSkill(database.skills[name]);
			tmp.hotkey = hotkey;
			tmp.modifier = modifier;
			tmp.Level = level;

			if( toggleable ) then tmp.Toggleable = toggleable; end;
			if( priority ) then tmp.priority = priority; end
			if( targetmaxhpper ) then tmp.TargetMaxHpPer = targetmaxhpper; end;
			if( targetmaxhp ) then tmp.TargetMaxHp = targetmaxhp; end;
			if( maxhpper ) then tmp.MaxHpPer = maxhpper; end;
			if( maxmanaper ) then tmp.MaxManaPer = maxmanaper; end;
			if( cooldown ) then tmp.Cooldown = cooldown; end;
			if( inbattle ~= nil ) then tmp.InBattle = inbattle; end;
			if( pullonly == true ) then tmp.pullonly = pullonly; end;
			if( maxuse ) then tmp.maxuse = maxuse; end;
			if( rebuffcut ) then tmp.rebuffcut = rebuffcut; end;
			if( autouse == false ) then tmp.AutoUse = false; end;

			table.insert(settings.profile.skills, tmp);
		end

		table.sort(settings.profile.skills, skillSort);
	end

	local loadFriends = function(node)
		local elements = node:getElements();

		for i,v in pairs(elements) do

			local name = v:getAttribute("name");
			
			if( name ) then name = trim(name); end;

			if( name ) then 
		
				-- fix, because getAttribute seems not to recognize the escape characters
				-- for special ASCII characters
				name = string.gsub (name, "\\132", string.char(132));	-- ä
				name = string.gsub (name, "\\142", string.char(142));	-- Ä
				name = string.gsub (name, "\\148", string.char(148));	-- ö
				name = string.gsub (name, "\\153", string.char(153));	-- Ö
				name = string.gsub (name, "\\129", string.char(129));	-- ü
				name = string.gsub (name, "\\154", string.char(154));	-- Ü
				name = string.gsub (name, "\\225", string.char(225));	-- ß

				table.insert(settings.profile.friends, name);
			end
		end
	end

	local loadMobs = function(node)
		local elements = node:getElements();

		for i,v in pairs(elements) do
		
			local name = v:getAttribute("name");

			if( name ) then name = trim(name); end;

			if( name ) then 
				
				-- fix, because getAttribute seems not to recognize the escape characters
				-- for special ASCII characters
				name = string.gsub (name, "\\132", string.char(132));	-- ä
				name = string.gsub (name, "\\142", string.char(142));	-- Ä
				name = string.gsub (name, "\\148", string.char(148));	-- ö
				name = string.gsub (name, "\\153", string.char(153));	-- Ö
				name = string.gsub (name, "\\129", string.char(129));	-- ü
				name = string.gsub (name, "\\154", string.char(154));	-- Ü
				name = string.gsub (name, "\\225", string.char(225));	-- ß

				table.insert(settings.profile.mobs, name);
			end
		end
	end

	local hf_temp = _name;	-- remember profile name shortly

	for i,v in pairs(elements) do
		local name = v:getName();

		if( string.lower(name) == "options" ) then
			loadOptions(v);
		elseif( string.lower(name) == "hotkeys" ) then
			loadHotkeys(v);
		elseif( string.lower(name) == "skills" ) then
			loadSkills(v);
		elseif( string.lower(name) == "friends" ) then
			loadFriends(v);
		elseif( string.lower(name) == "mobs" ) then
			loadMobs(v);
		elseif( string.lower(name) == "onload" ) then
			loadOnLoadEvent(v);
		elseif( string.lower(name) == "ondeath" ) then
			loadOnDeathEvent(v);
		elseif( string.lower(name) == "onleavecombat" ) then
			loadOnLeaveCombatEvent(v);
		elseif( string.lower(name) == "onlevelup" ) then
			loadOnLevelupEvent(v);
		elseif( string.lower(name) == "onskillcast" ) then
			loadOnSkillCastEvent(v);
		elseif( string.lower(name) == "skills_warrior"  and
		        player.Class1 == CLASS_WARRIOR ) then
			loadSkills(v);
		elseif( string.lower(name) == "skills_scout"  and
		        player.Class1 == CLASS_SCOUT ) then
			loadSkills(v);
		elseif( string.lower(name) == "skills_rogue"  and
		        player.Class1 == CLASS_ROGUE ) then
			loadSkills(v);
		elseif( string.lower(name) == "skills_mage"  and
		        player.Class1 == CLASS_MAGE ) then
			loadSkills(v);
		elseif( string.lower(name) == "skills_priest"  and
		        player.Class1 == CLASS_PRIEST ) then
			loadSkills(v);
		elseif( string.lower(name) == "skills_knight"  and
		        player.Class1 == CLASS_KNIGHT ) then
			loadSkills(v);
		elseif( string.lower(name) == "skills_warden"  and
		        player.Class1 == CLASS_WARDEN ) then
			loadSkills(v);
		elseif( string.lower(name) == "skills_druid"  and
		        player.Class1 == CLASS_DRUID ) then
			loadSkills(v);
		else		-- warning for other stuff and misspellings
			if ( string.lower(name) ~= "skills_warrior"     and
			     string.lower(name) ~= "skills_scout"       and
		 	     string.lower(name) ~= "skills_rogue"       and
	 		     string.lower(name) ~= "skills_mage"        and
			     string.lower(name) ~= "skills_priest"      and
			     string.lower(name) ~= "skills_knight"      and
			     string.lower(name) ~= "skills_warden"  and
			     string.lower(name) ~= "skills_druid" )     then
				cprintf(cli.yellow, tostring(language[60]), string.lower(tostring(name)),
					tostring(hf_temp));
			end;
		end
	end


	-- checks for MACRO hotkey
	-- print error if new macro option isn't defined
	if( not settings.profile.hotkeys.MACRO ) then
		cprintf(cli.yellow, language[900]);
		cprintf(cli.yellow, language[901]);
		cprintf(cli.yellow, language[902]);
		cprintf(cli.yellow, language[903]);
		cprintf(cli.yellow, language[904], "VK_0"); -- TODO: Change VK_0 to the actual hotkey we should use
		local msg = sprintf(language[905], _name);
		error(msg, 0);
	end

	-- check if new macro option is working / ingame macro defined and assigned
	-- check it with a function with defined return values
	settings.options.DEBUGGING_MACRO = true;
	local hf_return = RoMScript("1234;ChatFrame1:AddMessage(\"MACRO test: send value 1234 to macro place 2\");");
	if( hf_return ~= 1234 ) then	-- return values not found
--		RoMScript("ChatFrame1:AddMessage(\"MACRO test: test failed !!! No return values found!\");");	-- overwrite return values
		cprintf(cli.yellow, language[906] );	-- Define ingame an empty macro 

		if ( settings.profile.hotkeys.MACRO.key) then
			hf_temp = getKeyName(settings.profile.hotkeys.MACRO.key);
		else
			local hf_temp ="<UNKNOWN>";	-- if ignore, key must not be set, so give value
		end

		local msg = sprintf(language[904], hf_temp );

		error(msg, 0);
	else								-- return values found, clear it and send message
		cprintf(cli.green, "MACRO Test: ok\n" );	
		RoMScript("xxxx; ChatFrame1:AddMessage(\"MACRO test: successful\");");	-- overwrite values
	end
	settings.options.DEBUGGING_MACRO = false;


	-- MACRO is working, we can automaticly reset the langugae
	-- remember game client language
	local hf_langu = RoMScript("GetLanguage();");
	if( not hf_langu ) then
		local msg = sprintf(language[62]);	-- Error while reading the language settings
--		error(msg, 0);
		cprintf(cli.yellow, msg);
		hf_langu = "ENEU";
	end
	bot.ClientLanguage = hf_langu;	-- remember clients language

	-- reset bot language to clients language
	if( settings.options.USE_CLIENT_LANGUAGE ) then
		local hf_language;
		if( bot.ClientLanguage == "DE" ) then
			hf_language = "deutsch";
		elseif(bot.ClientLanguage  == "FR" ) then
			hf_language = "french";
		elseif(bot.ClientLanguage  == "RU" ) then
			hf_language = "russian";
		else
			hf_language = "english";		
		end

		if( settings.options.LANGUAGE ~= hf_language ) then		-- load new language?

			local function setLanguage(_name)
				include(getExecutionPath() .. "/language/" .. _name .. ".lua");
			end

			local lang_base = {};
			
			for i,v in pairs(language) do lang_base[i] = v; end;	-- remember current language value to fill gaps with that

			setLanguage(hf_language);
			for i,v in pairs(lang_base) do
				if( language[i] == nil ) then
					language[i] = v;
				end
			end;
			lang_base = nil; -- Not needed anymore, destroy it.
			logMessage("Load Language according to client language: " .. hf_language);

		end

	end


	-- now we can do all other setting checks

	
	-- Check if the player has any ranged damage skills
	local rangedSkills = false;
	for i,v in pairs(settings.profile.skills) do
		if( v.Range > 100  and
			( v.Type == STYPE_DAMAGE or
			  v.Type == STYPE_DOT ) ) then
			rangedSkills = true;
			printf(language[176], v.Name);		-- Ranged skill found
			break;
		end
	end

	if( rangedSkills == false and settings.profile.options.COMBAT_RANGED_PULL ) then
		cprintf(cli.yellow, language[200]);
		settings.profile.options.COMBAT_RANGED_PULL = false;
	end


--	function checkProfileHotkeys(name)
--		if( not settings.profile.hotkeys[name] ) then
--			error("ERROR: Hotkey not set for this profile: " ..name, 0);
--		end
--	end


	-- default combat type if not in profile defined
	if( settings.profile.options.COMBAT_TYPE ~= "ranged" and 
	    settings.profile.options.COMBAT_TYPE ~= "melee" ) then
		if( player.Class1 == CLASS_WARRIOR or
		    player.Class1 == CLASS_ROGUE   or
		    player.Class1 == CLASS_WARDEN  or
		    player.Class1 == CLASS_KNIGHT  ) then
			settings.profile.options.COMBAT_TYPE  = "melee";
		elseif(
		    player.Class1 == CLASS_PRIEST  or
		    player.Class1 == CLASS_SCOUT   or
		    player.Class1 == CLASS_DRUID   or
		    player.Class1 == CLASS_MAGE    ) then
			settings.profile.options.COMBAT_TYPE  = "ranged";
		else
			error("undefined player.Class1 in settings.lua", 0);
		end;
	end


	-- check if range attack range and combat distance fit together
	local best_range = 0;
	for i,v in pairs(settings.profile.skills) do
		if( v.Range > best_range and
			( v.Type == STYPE_DAMAGE or
			  v.Type == STYPE_DOT ) ) then
			best_range = v.Range;
		end
	end

	-- check is combat distance is greater then maximum ranged attack
	if( best_range < settings.profile.options.COMBAT_DISTANCE  and
		(settings.profile.options.COMBAT_TYPE == "ranged" or
		settings.profile.options.COMBAT_RANGED_PULL == true) ) then
		local msg = sprintf(language[179], settings.profile.options.COMBAT_DISTANCE);	-- Maximum range of range attack skills is lesser
		error(msg, 0);
	end


	-- warning if not all inventory slots are updated
	if( settings.profile.options.INV_AUTOSELL_TOSLOT > settings.profile.options.INV_MAX_SLOTS ) then
		cprintf(cli.yellow, language[1003], settings.profile.options.INV_MAX_SLOTS, settings.profile.options.INV_AUTOSELL_TOSLOT);
	end


	-- check if igf addon is active
	if ( RoMScript("IGF_INSTALLED") == true ) then
		bot.IgfAddon = true; 
	else
		bot.IgfAddon = false;
	end

	-- error if igf (ingamefunctions) addon isn't installed and options are set
	if( bot.IgfAddon == false	and
		( settings.profile.options.INV_AUTOSELL_NOSELL_DURA > 0	or
		  settings.profile.options.INV_AUTOSELL_STATS_NOSELL ~= nil ) ) then
		error(language[1004], 0)	-- Ingamefunctions addon (igf) is not installed
	end

	-- check if automatic targeting is active
	if( settings.profile.options.AUTO_TARGET == false ) then
		cprintf(cli.yellow, "Caution: Automatic targeting is deactivated with option AUTO_TARGET=\"false\"\n");
	end


end
micromacro\lib\lib.lua

Code: Select all

--[[ lib.lua
	This is a pseudo library designed for MicroMaco.
	Functions, variables, etc. declared here will
	be accessable in all scripts made for MicroMacro.

	Note: You should not modify this script unless
	you are fixing something. Please report fixes
	to the author (admin@solarstrike.net) or post
	on the forums at www.solarstrike.net

	Any changes you make may be overwritten if
	you chose to update. Consider making a module
	instead.
--]]

cocoAvailable = (coroutine.coco == true);


------------------------------------------------------
-- Import configurations and libraries, load modules
------------------------------------------------------
-- Set module path
package.path = ".\\?.lua;" .. getPath() .. "/lib/mods/?.lua" ;
package.cpath = ".\\?.dll;" .. getPath() .. "/plugins/?.dll;" .. getPath() .. "/lib/mods/?.dll";


local plugintab = getDirectory(getPath() .. "/plugins");
if( plugintab ) then
	for i,v in pairs(plugintab) do
		local extpos = string.find(v, ".dll");
		if( extpos ) then
			local fname = string.sub(v, 0, extpos - 1);

			-- Make sure it's not already loaded for some reason
			if( not package.loaded[fname] ) then
				local success = package.loadlib(getPath() .. "/plugins/" .. v, "luaopen_" .. fname);
				if( type(success) == "function" ) then
					package.loaded[fname] = success();
				else
					package.loaded[fname] = success;
				end

				if( success ) then
					logMessage("Loaded plugin \'" .. fname .. "\'");
				else
					logMessage("Failed to load plugin \'" .. fname .. "\'");
				end
			end
		end
	end
end


-- Autoload modules/plugins
local autoloadFile = io.open(getPath() .. "/lib/autoload.lua");
if( autoloadFile ) then
	autoloadFile:close();
	local autoload = dofile(getPath() .. "/lib/autoload.lua");

	for i,v in pairs(autoload) do
		require(v);
	end
end



------------------------------------------------------
-- Keyboard & Language setup
------------------------------------------------------
key = nil;
if( keyboard ~= nil and type(keyboard) == "string" ) then
	key = require("keyboard/" .. keyboard);
end

if( key == true or key == nil ) then
	setTextColor(cli.yellow);
	error("Error loading keyboard module.");
	key = { };
end


------------------------------------------------------
-- VARIABLE DECLARATION
------------------------------------------------------

-- Our start/stop keys.
-- Only useful when using startMacro()
local startKeyDefault = key.VK_F5;
local stopKeyDefault = key.VK_F6;

local startKey = startKeyDefault;
local stopKey = stopKeyDefault;


-- Timed function list.
-- These are automatically "timed" when registered
local timerList = {}


-- Priority Defines -- DEPRECATED! Use priority.high, priority.low, or priority.normal instead
PRIORITY_HIGH = 1;
PRIORITY_NORMAL = 0;
PRIORITY_LOW = -1;

-- Protected environment vars
local __PErunning = false;
local __PEco;


------------------------------------------------------
-- FUNCTION DECLARATION
------------------------------------------------------

function setStartKey(val)
    startKey = val
end

function getStartKey()
    return startKey
end

function setStopKey(val)
    stopKey = val
end

function getStopKey()
    return stopKey
end


-- Runs a coroutine in a protected state, if available
function safeYield()
	-- make sure we're not trying to yield in the main thread
	-- do nothing.
	local co = coroutine.running();
	if( co == nil ) then
		return;
	end

	if( cocoAvailable ) then
		local status, err = pcall(coroutine.yield);

		if( status ~= true ) then
			setTextColor(cli.yellow);
			error(err, 3);
		end
	else
		coroutine.yield();
	end
end


-- unpacks varargs and returns them as a table.
-- also returns 'n', the true size of the table.
function unpack2(...)
	local n = select('#', ...);
	local t = {};
	for i = 1,n do
		local v = select(i, ...);
		t[i] = v;
	end

	return t, n;
end


-- Formatted output
-- C printf-like function
function printf(format, ...)
	local t, n = unpack2(...);

	for i = 1,n do
		local v = t[i];
		if( type(v) == "nil" ) then
			local err = sprintf("bad argument #%d to 'printf' (got %s)", i, type(v));
			error(err, 2);
		end

		if( type(v) == "table" or type(v) == "boolean" or type(v) == "function"
		or type(v) == "thread" or type(v) == "userdata" ) then
			t[i] = tostring(t[i]);
		end

	end

	local status, err = pcall(string.format, format, unpack(t));

	if( status == false ) then
		error(err, 2);
	end

	io.write(err);
end


-- Formatted output
-- C sprintf-like function
--sprintf = string.format;
function sprintf(format, ...)
	local t, n = unpack2(...);

	for i = 1,n do
		local v = t[i];
		if( type(v) == "nil" ) then
			local err = sprintf("bad argument #%d to 'sprintf' (got %s)", i, type(v));
			error(err, 2);
		end

		if( type(v) == "table" or type(v) == "boolean" or type(v) == "function"
		or type(v) == "thread" or type(v) == "userdata" ) then
			t[i] = tostring(t[i]);
		end

	end

	local status, err = pcall(string.format, format, unpack(t));

	if( status == false ) then
		error(err, 2);
	end

	return err;
end



-- Include another file
-- Directly calling dofile() may lead to issues with
-- relative paths. It is recommended to use include().
function include(file)
	if( file == nil or string.len(file) < 1 ) then
		error("Cannot include \'nil\'.", 2);
	end

	local startExecutionPath = getExecutionPath();
	local test = string.find(file, "%a:[/\\]");
	local isRelative = ( test == nil );

	local status, err;

	if( isRelative ) then
		local fullpath = startExecutionPath .. "/" .. file;
		setExecutionPath(getFilePath(fullpath));

		status, err = pcall(dofile, fullpath);
	else
		setExecutionPath(getFilePath(file));
		status, err = pcall(dofile, file);
	end

	if( not status ) then
		error(err, 2);
	end

	setExecutionPath(startExecutionPath);
end


-- Time conversion for timers

-- Convert hours to timer value
function hoursToTimer(hours)
	return math.floor( hours * 3600000 );
end

-- Convert minutes to timer value
function minutesToTimer(minutes)
	return math.floor( minutes * 60000 );
end

-- Converts seconds to timer value
function secondsToTimer(seconds)
	return math.floor( seconds * 1000 );
end


-- Prepares an at-exit callback function that is
-- called when the script terminates
local __EXIT_CALLBACK = nil;
function atExit(func)
	if( type(func) ~= "function" and type(func) ~= "nil" ) then
		local err = "Error: Non-function type passed to atExit() where a function is expected.";
		setTextColor(cli.yellow);
		error(err, 2);
		return;
	end

	__EXIT_CALLBACK = func;
end

-- Prepare an at-pause callback function
-- called when the script is paused.
local function defaultPauseCallback()
	printf("Paused.\n");
end

local __PAUSE_CALLBACK = defaultPauseCallback;
function atPause(func)
	if( type(func) ~= "function" and type(func) ~= "nil" ) then
		local err = "Error: Non-function type passed to atPause() where a function is expected.";
		setTextColor(cli.yellow);
		error(err, 2);
		return;
	end

	__PAUSE_CALLBACK = func;

	if( func == nil ) then
		__PAUSE_CALLBACK = defaultPauseCallback;
	end
end


-- Prepare an at-resume callback function
-- called when the script is resumed.
local function defaultResumeCallback()
	printf("Started.\n");
end

local __RESUME_CALLBACK = defaultResumeCallback;
function atResume(func)
	if( type(func) ~= "function" and type(func) ~= "nil" ) then
		local err = "Error: Non-function type passed to atResume() where a function is expected.";
		setTextColor(cli.yellow);
		error(err, 2);
		return;
	end

	__RESUME_CALLBACK = func;

	if( func == nil ) then
		__RESUME_CALLBACK = defaultResumeCallback;
	end
end


-- Register a function to be called automatically.
-- Should be used in combination with startMacro
-- as opposed to manually.
function registerTimer(name, time, func, ...)
	if( type(func) ~= "function" ) then
		local err = "Error: Non-function type passed to registerTimer() where a function is expected.";
		setTextColor(cli.yellow);
		error(err, 2);
		return; 
	end

	if( type(time) ~= "number" ) then
		local err = "Error: Non-numerical type passed to registerTimer() where a time value is expected.";
		setTextColor(cli.yellow);
		error(err, 2);
		return;
	end

	local tmp = {};
	tmp.time = time;
	tmp.func = func;
	tmp.args = unpack2(...);

	newTimer(name);
	startTimer(name, time);
	timerList[name] = tmp;
end

-- Unregisters a function from being called automatically.
-- Only works if the function has been registered
function unregisterTimer(name)
	if( timerList[name] ) then
  		timerList[name] = nil;
  		removeTimer(name);
	end;
end


-- Toggles __PErunning to 0 in order to stop
-- the protected environment from continuing.
function stopPE()
	__PErunning = false;
	safeYield();
end

-- Start/resume the script
local function __start()
	for i,v in pairs(timerList) do
		if( isTriggered(i) ) then
			-- restart timers
			startTimer(i, v.time);
		end
	end

	if( __RESUME_CALLBACK ~= nil ) then
		__RESUME_CALLBACK();
	end

	__PErunning = true;
end

-- Stop/pause the script
local function __stop()
	if( __PAUSE_CALLBACK ~= nil ) then
		__PAUSE_CALLBACK();
	end

	__PErunning = false;
	if( coroutine.running() ) then
		-- Do not yield from main thread...
		coroutine.yield();
	end
end

-- Get debug information from any running script
local script_line = 0;
local script_name = "";
local function get_script_info(event, line)
	script_line = line;
	script_name = debug.getinfo(2).short_src;
end
debug.sethook(get_script_info, "l");


local function checkGlobalHotkeys()
	local kp;
	if( getAttachedHwnd() ~= 0 ) then
		kp = keyPressedLocal(startKey);
	else
		kp = keyPressed(startKey);
	end;

	if( kp ) then
		lastStartKey = true;
	else
		if( lastStartKey and not __PErunning ) then
			__start();
		end

		lastStartKey = false;
	end


	if( getAttachedHwnd() ~= 0 ) then
		kp = keyPressedLocal(stopKey);
	else
		kp = keyPressed(stopKey);
	end;

	if( kp ) then
		lastStopKey = true;
	else
		if( lastStopKey and __PErunning ) then
			__stop();
		end

		lastStopKey = false;
	end

	if( keyPressedLocal(key.VK_CONTROL) and keyPressedLocal(key.VK_L) ) then
		return true;
	else
		return false;
	end;
end

local function global_hotkey_hook(event, line)
	if( checkGlobalHotkeys() ) then
		stopPE();
	end;
end

-- Protected environment for startMacro to run.
-- Runs the function as a coroutine.
-- It allows us to easily run certain tasks
-- regularly without having to program them
-- directly into the macro.
function __ProtectedEnvironment(foo, defaultstate)
	if( defaultstate == false ) then
		__PErunning = false;
		printf("The macro is currently not running. Press the start key (%s) to begin.\n", getKeyName(startKey));
		printf("You may use (%s) key to stop/pause the script.\n", getKeyName(stopKey));
	else
		__PErunning = true;
		printf("Press the (%s) key to stop/pause the script.\nYou can resume with the (%s) key.\n",
		getKeyName(stopKey), getKeyName(startKey));
	end

	local lastStartKey, lastStopKey = false, false;

  	__PEco = coroutine.create(function ()
			math.randomseed(getTime().low);
			foo();
		end
	);

	-- Check global hotkeys every 10 lines.
	-- This is to ensure that a thread doesn't get out of control
	-- and become unrecoverable.
	debug.sethook(__PEco, global_hotkey_hook, "l", 10);

	local timerCo = coroutine.create(function()
			math.randomseed(getTime().low);
			
			while(true) do
				-- automatic timer functions
				if( __PErunning ) then
					for i,v in pairs(timerList) do
						if( isTriggered(i) ) then
							startTimer(i, v.time); -- restart timer.

							if( type(v.func) ~= "function" ) then
								-- throw an error
								local err = sprintf("Timer \'%s\' error: invalid function", i);
								setTextColor(cli.yellow);
								error(err, 2);
							else
								v.func(unpack(v.args));
							end
						end
					end
				end

				coroutine.yield();
			end
		end
	);


	while( true ) do
		if( checkGlobalHotkeys() ) then
			break;
		end;

		if( coroutine.status(__PEco) ~= 'dead' ) then
			-- continue macro
      
			if( __PErunning ) then
				-- Run main thread
				local runstatus,message = coroutine.resume(__PEco);
				if( runstatus == false ) then
					local msg = debug.traceback(__PEco, "In main thread:", 1) ..
					"\n\n----------TRACEBACK END----------\n\n";
					logRaw(msg);

					setTextColor(cli.yellow);
					error(message, 2);
				end

				-- Run timer thread
				runstatus,message = coroutine.resume(timerCo);
				if( runstatus == false ) then
					local msg = debug.traceback(timerCo, "In timer thread:", 1) ..
					"\n\n----------TRACEBACK END----------\n\n";
					logRaw(msg);

					setTextColor(cli.yellow);
					error(message, 2);
				end
			else
				rest(10); -- minimize CPU usage
			end
		else
			-- macro is "dead"
			break;
		end
	end

	-- cleanup timers
	for i,v in pairs(timerList) do
		timerList[i] = nil;
	end

	print("Stopping execution.");

	--[[if( __PAUSE_CALLBACK ~= defaultPauseCallback and __PAUSE_CALLBACK ~= nil ) then
		__PAUSE_CALLBACK();
	end]]

	if( __EXIT_CALLBACK ~= nil ) then
		__EXIT_CALLBACK();
	end

	-- restore defaults
	startKey = startKeyDefault;
	stopKey = stopKeyDefault;
	atResume(nil);
	atPause(nil);
	atExit(nil);
end


-- startMacro passes the call off to
-- __ProtectedEnvironment, and handles
-- any errors.
function startMacro(foo, defaultstate)
	if( defaultstate ~= true ) then defaultstate = false; end;

	if( type(foo) ~= "function" ) then
		local err = "Error: Non-function type passed to startMacro(). Value is of type " .. type(foo) .. ".";
		setTextColor(cli.yellow);
		error(err, 2);
		return;
	end

	local status, err = pcall(__ProtectedEnvironment, foo, defaultstate);
	if( status ) then
		-- no errors
	else
		-- errors occured...log them
		setTextColor(cli.yellow);
		error(err, 3);
	end
end


-- A pretty standard rest/sleep command.
-- It automatically will yeild, though.
function yrest(msec)
	if( msec == nil ) then error("yrest() cannot rest for \'nil\'.\n", 2); end;
	safeYield();

	-- if Coco is available, use 10ms sections. This is the highest
	-- resolution available on Windows.
	-- if Coco is not available, fall back on 100ms sections to
	-- avoid yielding across C-boundaries

	local resttime;
	local sections;
	local ext;

	if( cocoAvailable ) then
		resttime = 10;
	else
		resttime = 100;
	end


	if( msec < resttime ) then
		rest(msec);
		return;
	else
		local startTime = getTime();
		while( deltaTime(getTime(), startTime) < msec ) do
			rest(resttime);
			safeYield();
		end
	end

end

-- Checks if a color is within 'accuracy' of another color.
-- Each channel is checked individually.
-- 'accuracy' should be between 0 and 255.
function colorMatch(color1, color2, accuracy)
	local r1, g1, b1, r2, g2, b2;

	if( accuracy == nil ) then accuracy = 0; end;
	if( accuracy < 0 ) then accuracy = 0; end;
	if( accuracy > 255 ) then accuracy = 255; end;

	r1 = getR(color1); g1 = getG(color1); b1 = getB(color1);
	r2 = getR(color2); g2 = getG(color2); b2 = getB(color2);

	if( math.abs(r2 - r1) <= accuracy and
		math.abs(g2 - g1) <= accuracy and
		math.abs(b2 - b1) <= accuracy ) then

		return true; -- they match
	end;

	return false; -- they don't match
end


-- Checks and returns true if a file exists.
function fileExists(fullpath)
	local handle = io.open(fullpath, "r");
	local success = handle ~= nil;

	if( success ) then
		handle:close();
	end

	return success;
end


-- "explode" a string into a table, splitting at 'token'
-- i.e. "Hello World, how are you?" explodes using the space
-- character would return {"Hello", "World,", "how", "are", "you?"}
-- if 'token' is not given, space is assumed.
function explode(instr, token)
	local findpos;
	local holder = {};

	if( token == nil ) then token = " "; end

	findpos = string.find(instr, token);

	if( findpos == nil ) then return {instr}; end

	while( findpos ) do
		table.insert(holder, string.sub(instr, 0, findpos -1));
		instr = string.sub(instr, findpos + string.len(token));
		findpos = string.find(instr, token);
	end

	if( string.len(instr) ) then
		table.insert(holder, instr);
	end

	return holder;
end


-- Throw a warning and log it
function warning(msg, showline)
	if( type(msg) ~= "string" ) then
		if( type(msg) == "number" ) then
			msg = tostring(msg);
		else
			error("Non-string passed to function warning", 2);
		end;
	end;

	if( type(showline) ~= "boolean" ) then
		showline = true;
	end;

	if( showline ) then
		msg = script_name .. ":" .. script_line .. "\n" .. msg;
	end

	setTextColor(cli.yellow);
	print("[WARN]: " .. msg);
	setTextColor(cli.lightgray);
	logMessage("[WARN]: " .. msg);
end
Last edited by ginokid on Wed Dec 09, 2009 4:47 pm, edited 2 times in total.

ginokid
Posts: 35
Joined: Tue Jul 28, 2009 10:30 pm

Re: Bot stopped working.. help plz :)

#2 Post by ginokid » Wed Dec 09, 2009 4:43 pm

Here's my characters profile
My character's profile

Code: Select all

<profile>
	<options>
		<!-- Try the bot with a new char mage                   -->
		<!-- At the pioneer village. Use demo.xml waypoint file -->
		<option name="HP_LOW"			value="65" />
		<option name="MP_LOW_POTION"	value="50" />
		<option name="HP_LOW_POTION"	value="70" />
		<option name="USE_HP_POTION"	value="best" />	<!-- potion select strategy: best|minstack -->
		<option name="USE_MANA_POTION"	value="best" />	<!-- potion select strategy: best|minstack -->

		<!-- Rest if HP or Mana is below that level -->
		<option name="HP_REST" value="15" />
		<option name="MP_REST" value="15" />

		<!-- Shopping options, how many of what do you want to keep in your inventory -->
		<option name="HEALING_POTION" value="99" />
		<option name="MANA_POTION" value="99" />
		<option name="ARROW_QUIVER" value="2" />
		<option name="THROWN_BAG" value="2" />
		<option name="POISON" value="30" />

		<!-- either false or arrow or thrown -->
		<option name="RELOAD_AMMUNITION" value="false" />	<!-- false|arrow|thrown -->

		<!-- Combat options -->
		<option name="COMBAT_TYPE"        value="" />	<!-- leave empty or choose ranged/melee if not using class default -->
		<option name="COMBAT_RANGED_PULL" value="true" /> <!-- only important for melees -->
		<option name="COMBAT_DISTANCE"    value="200" />
		<option name="MAX_FIGHT_TIME"     value="15" />	<!-- Max time without damage before break -->
		<option name="DOT_PERCENT"        value="90" />
		<option name="ANTI_KS"            value="true" />

		<!-- Attack monsters 3 levels above or 10 below your level -->
		<option name="TARGET_LEVELDIF_ABOVE" value="6" />
		<option name="TARGET_LEVELDIF_BELOW" value="10" />

		<!-- Waypoint and movement settings -->
		<option name="WAYPOINTS"		value="" />  <!-- leave empty to show a list -->
		<option name="RETURNPATH"		value="" />
		<option name="PATH_TYPE"		value="waypoints" />	<!-- waypoints | wander -->
		<option name="WANDER_RADIUS"		value="500" />
		<option name="WAYPOINT_DEVIATION"	value="0" />
		<option name="QUICK_TURN" 		value="true" />

		<!-- Loot settings -->
		<option name="LOOT"               value="true" />
		<option name="LOOT_IN_COMBAT"     value="true" />
		<option name="LOOT_DISTANCE"      value="250" />
		<option name="LOOT_PAUSE_AFTER"   value="0" />		<!-- probability in % for a short rest -->

		<!-- Log out and resurrect settings -->
		<option name="LOGOUT_TIME" 			value="0" />	<!-- in minutes, 0 = timer disabled -->
		<option name="LOGOUT_SHUTDOWN"		value="false" />
		<option name="LOGOUT_WHEN_STUCK"	value="true" />
		<option name="RES_AUTOMATIC_AFTER_DEATH" value="true" />

		<!-- For more options and documentation see the RoM Bot Wiki:  -->
		<!-- http://www.solarstrike.net/wiki/index.php5?title=RoM_Bot  -->

	</options>

	<friends>
		<!-- names of friends we help fighting or enemys we don't want to attack -->
		<!-- for umlauts use \129 (ue),\132 (ae),\148 (oe) e.g. K\132fer         -->
		<friend name="MyOtherCharacter1" />
		<friend name="MyOtherCharacter2" />
		<friend name="Elite_Mob_Name1" />
		<friend name="Elite_Mob_Name2" />
	</friends>

	<mobs>
		<!-- names of mobs we want to attack 				-->
		<!-- if no names defined we will attack all mobs	-->
		<mob name="" />
		<mob name="" />
		<mob name="" />
	</mobs>

	<hotkeys>
    	<!-- to communicate with the RoM API / define ingame dummy macro at place 1 -->
		<hotkey name="MACRO"        key="VK_0" />
	</hotkeys>

	<!-- define your skills depending from your actual primary class -->
	<!-- see the example for a priest/mage                           -->
	<!-- delete skills you don't have or don't want to use.          -->
	<!-- For more skills to use see /database/skills.xml             -->
	<!-- demo skills for LvL 1 character for all classes             -->
<skillst>
		<skill name="SCOUT_VAMPIRE_ARROWS"        hotkey="VK_2" priority="90" />
		<skill name="ROGUE_BLIND_STAB"    hotkey="VK_3" priority="80" />
		<skill name="ROGUE_SHADOWSTAB" hotkey="VK_4" priority="70" />
		<skill name="ROGUE_LOW_BLOW"  hotkey="VK_5" priority="90" />
		<skill name="ROGUE_WOUND_ATTACK"    hotkey="VK_6" priority="80" />
	</skills>

</profile>

ginokid
Posts: 35
Joined: Tue Jul 28, 2009 10:30 pm

Re: Bot stopped working.. help plz :)

#3 Post by ginokid » Wed Dec 09, 2009 4:46 pm

My bot.lua

Code: Select all

BOT_VERSION = 3.10;

include("addresses.lua");
include("database.lua");
include("classes/player.lua");
include("classes/inventory.lua");
include("classes/camera.lua");
include("classes/waypoint.lua");
include("classes/waypointlist.lua");
include("classes/waypointlist_wander.lua");
include("classes/node.lua");
include("settings.lua");
include("functions.lua");


settings.load();
setStartKey(settings.hotkeys.START_BOT.key);
setStopKey(settings.hotkeys.STOP_BOT.key);



__WPL = nil;	-- Way Point List
__RPL = nil;	-- Return Point List

-- start message
text = sprintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" ..
	"Welcome to rom bot! press END to quit\n" ..
	"RoM Bot Version %0.2f\n", BOT_VERSION);

printPicture("logo", text, 4);

function main()
	local forcedProfile = nil;
	local forcedPath = nil;
	local forcedRetPath = nil;

	for i = 2,#args do
		if( args[i] == "update" ) then
			include("update.lua");
		end

		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 == "profile" ) then
				forcedProfile = val;
			elseif( var == "path" ) then
				forcedPath = val;
			elseif( var == "retpath" ) then
				forcedRetPath = val;
			else
				-- invalid option
				local msg = sprintf(language[61], args[i]);
				error(msg, 0 ); 
			end
		end

		-- check the options
		if(not foundpos  and  args[i] ~= "update" ) then
			local msg = sprintf(language[61], args[i]);
			error(msg, 0 ); 
		end;

	end



	database.load();
	attach(getWin());

	if( not checkExecutableCompatible() ) then
		cprintf(cli.yellow, "!! Notice: !!\n");
		printf(language[43]);	-- is recommended that you run rom/update.lua

		logMessage("Game exectuable may have changed. You should run rom/update.lua");
	end

	local playerAddress = memoryReadIntPtr(getProc(), addresses.staticbase_char, addresses.charPtr_offset);
	if( settings.options.DEBUGGING ) then
		printf(language[44]);	-- Attempt to read playerAddress
	end

	if( playerAddress == nil ) then 
		local msg = sprintf(language[48], "playerAddress");	-- pls update to current version
		error(msg, 0);
	end;
	logMessage(sprintf("Using static char address 0x%X, player address 0x%X",
		tonumber(addresses.staticbase_char), tonumber(playerAddress)));

	player = CPlayer(playerAddress);
	player:initialize();
	player:update();
	if( settings.options.DEBUGGING ) then
		-- Player debugging info
		printf("[DEBUG] playerAddr: 0x%X\n", player.Address);
		printf("[DEBUG] player pet: 0x%X\n", player.PetPtr);
		printf("[DEBUG] Player target: 0x%X\n", player.TargetPtr);

		if( player.TargetPtr ~= 0 ) then
			local target = CPawn(player.TargetPtr);
			printf("[DEBUG] Player target type: 0x%X\n", target.Type);
			printf("[DEBUG] Player target attackable: %s\n", target.Attackable);
		end
	end

	mousePawn = CPawn( memoryReadIntPtr(getProc(), addresses.staticbase_char, addresses.mousePtr_offset) );

	if( settings.options.DEBUGGING ) then
		-- Mouse pawn debugging info
		printf("[DEBUG] mousePawn: 0x%X\n", mousePawn.Address);
		printf("[DEBUG] mousePawn id: %d\n", mousePawn.Id);
	end

	local cameraAddress = memoryReadIntPtr(getProc(), addresses.staticbase_char, addresses.camPtr_offset);
	if( cameraAddress == nil ) then cameraAddress = 0; end;

	camera = CCamera(cameraAddress);
	if( settings.options.DEBUGGING ) then
		-- Camera debugging info
		printf("[DEBUG] Cam X: %0.2f, Y: %0.2f, Z: %0.2f\n", camera.X, camera.Y, camera.Z);
		printf("[DEBUG] Cam XU: %0.2f, YU: %0.2f, ZU: %0.2f\n", camera.XUVec, camera.YUVec, camera.ZUVec);
	end

	local hf_x, hf_y, hf_wide, hf_high = windowRect( getWin());
	cprintf(cli.turquoise, language[42], hf_wide, hf_high, hf_x, hf_y );	-- RoM windows size

	-- convert player name to profile name and check if profile exist
	local load_profile_name;	-- name of profile to load
	if( forcedProfile ) then
		load_profile_name = convertProfileName(forcedProfile);
	else
		load_profile_name = convertProfileName(player.Name);
	end

	-- Set window name, install timer to automatically do it once a second
	local displayname = string.sub(load_profile_name, 1, 4) .. "****";
	setWindowName(getHwnd(), sprintf("RoM Bot %s [%s]", BOT_VERSION, displayname));
	settings.loadProfile(load_profile_name);
	settingsPrintKeys();		-- print keyboard settings to MM and log
	registerTimer("timedSetWindowName", secondsToTimer(1), timedSetWindowName, load_profile_name);
	player.BotStartTime_nr = os.time();	-- remember bot start time no reset
	player.level_detect_levelup = player.Level;	-- remember actual player level
	
	if( getTimerFrequency ) then
		-- Grab the real frequency instead of calculating it, if available
		bot.GetTimeFrequency = getTimerFrequency().low / 1000;
	else
		-- calculate the CPU Frequency / used for manipulation the GetTime() values
		local calc_start = getTime();
		yrest(1000);
		local calc_end = getTime();
		bot.GetTimeFrequency = (calc_end.low - calc_start.low) / 1000;
	end

	printf("[DEBUG] CPU Frequency %s\n", bot.GetTimeFrequency);
	
	inventory = CInventory();		-- register inventory (needs profile loaded because of maxslot)

	-- onLoad event
	-- possibility for users to overwrite profile settings
	if( type(settings.profile.events.onLoad) == "function" ) then
		local status,err = pcall(settings.profile.events.onLoad);
		if( status == false ) then
			local msg = sprintf("onLoad error: %s", err);
			error(msg);
		end
	end


	-- list waypoint files and files in folders
	-- only files with filetype '.xml' are listed
	-- only folders without '.' are listed
	-- only 1 level of subfolders will be listed
	local function list_waypoint_files()

		local hf_counter = 0;
		local pathlist = { }
		
		local function read_subdirectory(_folder)
			local subdir = getDirectory(getExecutionPath() .. "/waypoints/".._folder);
			if( not subdir) then return; end
			
			for i,v in pairs(subdir) do
				if( string.find (v,".xml",1,true) ) then
					hf_counter = hf_counter + 1;
						pathlist[hf_counter] = { };
						pathlist[hf_counter].folder = _folder;
						pathlist[hf_counter].filename = v;
				end
			end
			
		end		-- end of: local function read_subdirectory(_folder)


		local function concat_filename(_i, _folder, _filename)
			
			local hf_newname;
			local hf_folder = "";
			local hf_dots = "";
			local hf_slash = "";
			
			if( _folder  and  string.len(_folder) > 8 )  then 
				hf_folder = string.sub(_folder, 1, 6); 
				hf_dots = "..";
				hf_slash = "/";
			elseif( _folder  and  string.len(_folder) > 0 )  then 
				hf_folder = _folder;
				hf_slash = "/";
			end
			
			hf_newname = sprintf("%s%s%s%s",
			  hf_folder,
			  hf_dots,
			  hf_slash,
			  _filename);
			
			hf_nr = sprintf("%3d:", _i);
			
			return hf_nr, hf_newname;

		end

		-- choose a path from the waypoints folder
		local dir = getDirectory(getExecutionPath() .. "/waypoints/")

		cprintf(cli.green, language[144], getExecutionPath());	-- Waypoint files in %s


		-- copy table dir to table pathlist
		-- select only xml files
		pathlist[0] = { };
		pathlist[0].filename = "wander";
		for i,v in pairs(dir) do
		
			-- no . means perhaps folder
			if( not string.find (v,".",1,true) ) then
				read_subdirectory(v);
				
			-- only list files with extension .xml
			elseif( string.find (v,".xml",1,true) ) then
				hf_counter = hf_counter + 1;
				pathlist[hf_counter] = { };
				pathlist[hf_counter].filename = v;
			end
		end

		local inc = math.ceil(#pathlist/3);
		
		for i = 0, inc do
			
			local column1 = ""; local column2 = ""; local column3 = "";
			local col1nr = ""; local col2nr = ""; local col3nr = "";
			
			col1nr, column1 = concat_filename(i, pathlist[i].folder, pathlist[i].filename)
			
			if ( (i + inc) <= #pathlist ) then
				col2nr, column2 = concat_filename(i+inc, pathlist[i+inc].folder, pathlist[i+inc].filename);
			end
			if ( (i+inc*2) <= #pathlist ) then
				col3nr, column3 = concat_filename(i+inc*2, pathlist[i+inc*2].folder, pathlist[i+inc*2].filename);
			end

			cprintf(cli.green,"%s %s %s %s %s %s\n", 
				col1nr,
				string.sub(column1.."                    ", 1, 21),
				col2nr,
				string.sub(column2.."                    ", 1, 21),
				col3nr,
				string.sub(column3.."                    ", 1, 20) );

		end

		-- ask for pathname to choose
		keyboardBufferClear();
		io.stdin:flush();
		cprintf(cli.green, language[145], getKeyName(_G.key.VK_ENTER) );	-- Enter the number of the path 
		local hf_choose_path_nr = tonumber(io.stdin:read() );
		if( hf_choose_path_nr and
			hf_choose_path_nr >= 0 and
			hf_choose_path_nr <= #pathlist ) then 
			printf(language[146], hf_choose_path_nr );	-- You choose %s\n
			if( pathlist[hf_choose_path_nr].folder ) then
				wp_to_load = pathlist[hf_choose_path_nr].folder.."/"..pathlist[hf_choose_path_nr].filename;
			else
				wp_to_load = pathlist[hf_choose_path_nr].filename;
			end
			
			return wp_to_load;
		else
			cprintf(cli.yellow, language[147]);	-- Wrong selection
			yrest(3000);
			return false;
		end

	end	
	-- end of local function list_waypoint_files()
	

	-- This logic prevents files from being loaded if wandering was forced
	local wp_to_load, rp_to_load;
	-- get wp filename to load
	if( forcedPath ) then			-- waypointfile or 'wander'
		wp_to_load = forcedPath;
	else
		if( settings.profile.options.WAYPOINTS ) then
			wp_to_load = settings.profile.options.WAYPOINTS;
		end
	end

	-- get rp filename to load
	if( forcedRetPath ) then
		rp_to_load = forcedRetPath;
	else
		if( settings.profile.options.RETURNPATH ) then
			rp_to_load = settings.profile.options.RETURNPATH;
		end
	end

	-- set wander if defined in profile
	if( settings.profile.options.PATH_TYPE == "wander") then
	    wp_to_load = "wander";
	end
	
	-- list the path list?
	-- if we don't have a wp file to load, list them
	if( __WPL == nil ) then		-- not allready loaded (in onLoad event)

		while( wp_to_load == nil or wp_to_load == "" or wp_to_load == false	or wp_to_load == " " ) do	
			wp_to_load = list_waypoint_files();
		end;

		if( wp_to_load == "wander" ) then
			--__WPL = CWaypointListWander();
			loadPaths("wander", rp_to_load);
			__WPL:setRadius(settings.profile.options.WANDER_RADIUS);
			__WPL:setMode("wander");
			cprintf(cli.green, language[168], settings.profile.options.WANDER_RADIUS );	-- we wander around
		else
			loadPaths(wp_to_load, rp_to_load);	-- load the waypoint path / return path
		end;
	end;

	-- special option for use waypoint file from profile in a reverse order / not if forced path
	if( settings.profile.options.WAYPOINTS_REVERSE == true  and
	    not forcedPath  ) then 
		__WPL:reverse();
	end;
	
	-- look for the closest waypoint / return path point to start
	if( __RPL and __WPL.Mode ~= "wander" ) then	-- return path points available ?
		-- compare closest waypoint with closest returnpath point
		__WPL:setWaypointIndex( __WPL:getNearestWaypoint(player.X, player.Z ) );
		local hf_wp = __WPL:getNextWaypoint();
		local dist_to_wp = distance(player.X, player.Z, hf_wp.X, hf_wp.Z)
		
		__RPL:setWaypointIndex( __RPL:getNearestWaypoint(player.X, player.Z ) );
		local hf_wp = __RPL:getNextWaypoint();
		local dist_to_rp = distance(player.X, player.Z, hf_wp.X, hf_wp.Z)
		
		if( dist_to_rp < dist_to_wp ) then	-- returnpoint is closer then next normal wayoiint
			player.Returning = true;	-- then use return path first
			cprintf(cli.yellow, language[12]);	-- Starting with return path
		else
			player.Returning = false;	-- use normale waypoint path
		end;
	end;

	-- Update inventory
	inventory:update();

	local distBreakCount = 0; -- If exceedes 3 in a row, unstick.
	while(true) do
		player:update();
		player:logoutCheck();
		player.Fighting = false;		-- we are now not in the fight routines

		if( not player.Alive ) then
			player:resetSkillLastCastTime();	-- set last use back, so we can rebuff
			resurrect();
		end

		if( player.TargetPtr ~= 0 and not player:haveTarget() ) then
			player:clearTarget();
		end


		-- reloading ammunition
		if ( settings.profile.options.RELOAD_AMMUNITION ) then
			local ammo = string.lower(settings.profile.options.RELOAD_AMMUNITION);
			if ammo == "arrow" or ammo == "thrown" then
				if inventory:getAmmunitionCount() == 0 then
					inventory:reloadAmmunition(ammo);
				end
			else
			    print("RELOAD_AMMUNITION can only be false, arrow or thrown!");
			end
		end


		-- go back to sleep, if in sleep mode
		if( player.Sleeping == true ) then
			yrest(800);	-- wait a little for the aggro flag
			player:update();
			if( player.Battling == false ) then 
				player:sleep(); 
			end;
		end;	-- go sleeping if sleeping flag is set


		-- trigger timed inventory update
		--if( os.difftime(os.time(), player.InventoryLastUpdate) > 
			--settings.profile.options.INV_UPDATE_INTERVAL ) then
			--player.InventoryDoUpdate = true;
		--end

		-- update inventory if update flag is set
		-- TODO: rolling update while resting?
		if(player.InventoryDoUpdate == true and
		   not player.Battling ) then
			player.InventoryDoUpdate = false;
			player.InventoryLastUpdate = os.time();		-- remember update time
			inventory:update();
		end;


		-- check if levelup happens / execute after aggro is gone
		-- we do it here , to be sure, aggro flag is gone
		--  aggro flag would needs a wait (if no loot), so we don't check it
		if(player.Level > player.level_detect_levelup   and
		   not player.Battling )  then
		
			player.level_detect_levelup = player.Level;

			-- check if onLevelup event is used in profile
			if( type(settings.profile.events.onLevelup) == "function" ) then
				local status,err = pcall(settings.profile.events.onLevelup);
				if( status == false ) then
					local msg = sprintf(language[85], err);
					error(msg);
				end
			end
		end


		-- rest after getting new target and before starting fight
		-- rest between 50 until 99 sec, at most until full, after that additional rnd(10)
		if( player:haveTarget()  and
		    player.Current_waypoint_type ~= WPT_RUN ) then	-- no resting if running waypoin type
			player:rest( 50, 99, "full", 10 );		-- rest befor next fight
		end;


		-- if aggro then wait for target from client
		-- we come back to that coding place if we stop moving because of aggro
		local aggroWaitStart = os.time();
		local msg_print = false;
		while(player.Battling) do

			if( player.Current_waypoint_type == WPT_RUN or
				player.Current_waypoint_type == WPT_TRAVEL ) then	-- runing mode, don't wait for target
				cprintf(cli.green, language[113]);	-- we don't stop and don't fight back
				break;
			end;
			
			-- wait a second with the aggro message to avoid wrong msg 
			-- ecause of slow battle flag from the client
			if( msg_print == false  and  os.difftime(os.time(), aggroWaitStart) > 1 ) then
				cprintf(cli.green, language[35]);	-- Waiting on aggressive enemies.
				msg_print = true;
			end;
			if( player:haveTarget() ) then
				if( msg_print == false ) then
					cprintf(cli.green, language[35]);	-- Waiting on aggressive enemies.
					msg_print = true;
				end;

				break;
			end;

			if( os.difftime(os.time(), aggroWaitStart) > 4 ) then
				cprintf(cli.red, language[34]);		-- Aggro wait time out
				player.LastAggroTimout = os.time();	-- remember aggro timeout
				break;
			end;

			yrest(10);
			player:update();
		end


		if( player:haveTarget()  and
		    player.Current_waypoint_type ~= WPT_RUN and
			player.Current_waypoint_type ~= WPT_TRAVEL ) then	-- only fight back if it's not a running waypoint
		-- fight the mob / target

			-- remember players position at fight start
			local FightStartX = player.X;
			local FightStartZ = player.Z;
		
			local target = player:getTarget();
			if( settings.profile.options.ANTI_KS ) then
				if( target:haveTarget() and 
				  target:getTarget().Address ~= player.Address and 
				  (not player:isFriend(CPawn(target.TargetPtr))) ) then
					cprintf(cli.red, language[5], target.Name);
				else
					player:fight();
				end
			else
				player:fight();
			end

			
			-- check if we (as melee) can skip a waypoint because we touched it while moving to the fight place
			-- we do the check for all classes, even mostly only melees are touched by that, because only
			-- they move within the fightstart/-end
			local WPLorRPL;	-- current WP we want to reach next
			if( player.Returning ) then
				WPLorRPL = __RPL;	-- we are on a return path waypoint file
			else
				WPLorRPL = __WPL;	-- we are using a normal waypoint file
			end;
			if( WPLorRPL:getMode() ~= "wander" ) then
				local currentWp = WPLorRPL:getNextWaypoint();	-- get current wp we try to reach

				-- calculate direction in rad for: fight start postition -> current waypoint
				local dir_fightstart_to_currentwp = math.atan2(currentWp.Z - FightStartZ, currentWp.X - FightStartX);
				local dist_fightstart_to_currentwp = distance(FightStartX, FightStartZ, currentWp.X, currentWp.Z);

				-- calculate direction in rad for: fight start postition -> fight end postition
				local dir_fightstart_to_fightend = math.atan2(player.Z - FightStartZ, player.X - FightStartX);
				local dist_fightstart_to_fightend = distance(player.X, player.Z, FightStartX, FightStartZ);

				-- calculate how much  fighstart, wp and fightend are on a line, 0 = one line, 
				local angleDif = angleDifference(dir_fightstart_to_currentwp, dir_fightstart_to_fightend);
				if (settings.profile.options.DEBUG_WAYPOINT) then
					printf("[DEBUG] FightStartX %s FightStartZ %s\n", FightStartX, FightStartZ );
					printf("[DEBUG] dir_FS->WP rad %.3f dir_FS->FE rad %.3f\n", dir_fightstart_to_currentwp, dir_fightstart_to_fightend );
					cprintf(cli.yellow, "[DEBUG] Line FS->WP / FS->FE: angleDif rad %.3f grad %d\n", angleDif, math.deg(angleDif) );
				end

				-- c = Wurzel (a2 + b2 - 2 a b cos (ga))
				local a = dist_fightstart_to_currentwp;
				local b = dist_fightstart_to_currentwp;
				local ga = angleDif;
				local dist_to_passed_wp = math.sqrt( math.pow(a,2) + math.pow(b,2) - 2 * a * b * math.cos(ga) );
				if (settings.profile.options.DEBUG_WAYPOINT) then
					cprintf(cli.yellow, "[DEBUG] We (would) pass(ed) wp #%s (dist %.1f) in a dist of %d (skip at %d)\n", currentWp.wpnum, dist_fightstart_to_currentwp,  dist_to_passed_wp, settings.profile.options.WAYPOINT_PASS );
				end

				if( dist_to_passed_wp < settings.profile.options.WAYPOINT_PASS  and		-- default is 100
					dist_fightstart_to_fightend >= dist_fightstart_to_currentwp ) then

					-- check position of the waypoint after the current waypoint we want to reach
					-- we don't check the closest wp, thats to much effort, we assume the distance between wp is
					-- as far, that the next one is always the closest
					local nextWp = WPLorRPL:getNextWaypoint(1);	-- get current wp we try to reach +1
					local dir_fightend_to_nextwp = math.atan2(nextWp.Z - player.Z, nextWp.X - player.X);
					local dir_fightend_to_currentwp = math.atan2(currentWp.Z - player.Z, currentWp.X - player.X );
					angleDif = angleDifference(dir_fightend_to_currentwp, dir_fightend_to_nextwp);
					if (settings.profile.options.DEBUG_WAYPOINT) then
						printf( "[DEBUG] currentWp #%s %s %s, FE->WP rad %.3f\n", currentWp.wpnum,currentWp.X,currentWp.Z,dir_fightend_to_currentwp);
						printf( "[DEBUG] nextWp #%s %s %s, FE->WP rad %.3f\n", nextWp.wpnum,nextWp.X,nextWp.Z,dir_fightend_to_nextwp);
						cprintf(cli.yellow, "[DEBUG] FE->wp#%s to FE->wp#%s is in a angle of %d grad (skip at %d)\n", nextWp.wpnum,  currentWp.wpnum, math.deg(angleDif), settings.profile.options.WAYPOINT_PASS_DEGR );
					end

					-- if next waypoint is 'in front' of current waypoint
					if( math.deg(angleDif) > settings.profile.options.WAYPOINT_PASS_DEGR ) then	-- default 90
						if (settings.profile.options.DEBUG_WAYPOINT) then
							cprintf(cli.yellow, "[DEBUG] We overrun waypoint #%d, skip it and move on to #%d\n",currentWp.wpnum, nextWp.wpnum);
						end
						cprintf(cli.green, "We overrun waypoint #%d, skip it and move on to #%d\n",currentWp.wpnum, nextWp.wpnum);
						WPLorRPL:advance();	-- set next waypoint

						-- execute the action from the skiped wp
						if( currentWp.Action and type(currentWp.Action) == "string" ) then
							local actionchunk = loadstring(currentWp.Action);
							assert( actionchunk,  sprintf(language[150], WPLorRPL.CurrentWaypoint) );
							actionchunk();
						end

					end

				end 	-- end of: check to skip a waypoint
			end

			
		else
		-- don't fight, move to wp
			local wp = nil; local wpnum = nil;

			if( player.Returning ) then
				wp = __RPL:getNextWaypoint();
				wpnum = __RPL.CurrentWaypoint;
				cprintf(cli.green, language[13], wpnum, wp.X, wp.Z);	-- Moving to returnpath waypoint
			else
				wp = __WPL:getNextWaypoint();
				wpnum = __WPL.CurrentWaypoint;
				cprintf(cli.green, language[6], wpnum, wp.X, wp.Z);	-- Moving to waypoint
			end;

			player.Current_waypoint_type = wp.Type;		-- remember current waypoint type

			local success, reason = player:moveTo(wp);

			if( player.TargetPtr ~= 0 and (not player:haveTarget()) ) then
				player:clearTarget();
			end

			player:checkPotions();
			player:checkSkills( ONLY_FRIENDLY );	-- only cast hot spells to ourselfe

			if( success ) then
				-- if we stick directly at a wp the counter would reseted even if we are sticked
				-- hence we reset the counter only after 3 successfull waypoints
				player.Success_waypoints = player.Success_waypoints + 1;
				if( player.Success_waypoints > 3 ) then
					player.Unstick_counter = 0;	-- reset unstick counter
				end;

				if( player.Returning ) then
					-- Completed. Return to normal waypoints.
					if( __RPL.CurrentWaypoint >= #__RPL.Waypoints ) then
						__WPL:setWaypointIndex(__WPL:getNearestWaypoint(player.X, player.Z));
						if( __WPL.Mode == "wander" ) then
							__WPL.OrigX = player.X;
							__WPL.OrigZ = player.Z;
						end
						player.Returning = false;
						cprintf(cli.yellow, language[7]);
					else
						__RPL:advance();
					end
				else
					__WPL:advance();
				end
			else
				if( not reason == WF_TARGET ) then
					cprintf(cli.red, language[8]);		-- Waypoint movement failed
				end

				if( reason == WF_COMBAT ) then	
					cprintf(cli.turquoise, language[14]);	-- We get aggro. Stop moving to waypoint 
				end;

				if( reason == WF_DIST ) then
					distBreakCount = distBreakCount + 1;
				else
					if( distBreakCount > 0 ) then
						distBreakCount = 0;
					end
				end

				if( reason == WF_STUCK or distBreakCount > 3 ) then
					-- Get ourselves unstuck, then!
					distBreakCount = 0;
					player:clearTarget();
					player.Success_waypoints = 0;	-- counter for successfull waypoints in row
					player.Unstick_counter = player.Unstick_counter + 1;	-- count our unstick tries

					-- Too many tries, logout
					if( settings.profile.options.MAX_UNSTICK_TRIALS > 0 and
						player.Unstick_counter > settings.profile.options.MAX_UNSTICK_TRIALS ) then 
						cprintf(cli.yellow, language[55], 
						  player.Unstick_counter, 
						  settings.profile.options.MAX_UNSTICK_TRIALS );	-- max unstick reached
						if( settings.profile.options.LOGOUT_WHEN_STUCK ) then
							player:logout();
						else
						-- pause or stop ?
							player.Sleeping = true;		-- go to sleep
							--stopPE();	-- pause the bot
							-- we should play a sound !
							player.Unstick_counter = 0;
						end
					end;
					
					if( player.Sleeping ~= true) then	-- not when to much trial and we go to sleep
						-- unstick player und unstick message
						cprintf(cli.red, language[9], player.X, player.Z, 	-- unsticking player... at position
						   player.Unstick_counter, settings.profile.options.MAX_UNSTICK_TRIALS);
						player:unstick();
					end
				end
			end

			coroutine.yield();

		end
	end
	
end

function resurrect()
	-- Make sure they aren't still trying to run off
	keyboardRelease(settings.hotkeys.MOVE_FORWARD.key);
	keyboardRelease(settings.hotkeys.MOVE_BACKWARD.key);
	keyboardRelease(settings.hotkeys.ROTATE_LEFT.key);
	keyboardRelease(settings.hotkeys.ROTATE_RIGHT.key);
	keyboardRelease(settings.hotkeys.STRAFF_LEFT.key);
	keyboardRelease(settings.hotkeys.STRAFF_RIGHT.key);
	player.Death_counter = player.Death_counter + 1;

	-- Take a screenshot. Only works on MicroMacro 1.0 or newer
	showWindow(getWin(), sw.show);
	yrest(500);
	local sfn = getExecutionPath() .. "/profiles/" .. player.Name .. ".bmp";
	saveScreenshot(getWin(), sfn);
	printf(language[2], sfn);

	if( type(settings.profile.events.onDeath) == "function" ) then
		local status,err = pcall(settings.profile.events.onDeath);
		if( status == false ) then
			local msg = sprintf("onDeath error: %s", err);
			error(msg);
		end
	end

	-- msg how to activate automatic resurrection
	if( settings.profile.options.RES_AUTOMATIC_AFTER_DEATH == false ) then
		cprintf(cli.yellow, language[103]); -- If you want to use automatic resurrection
	end

	if( settings.profile.options.RES_AUTOMATIC_AFTER_DEATH == true ) then
		cprintf(cli.red, language[3]);			-- Died. Resurrecting player...
				
		-- try mouseclick to reanimate
		cprintf(cli.green, language[104]);  -- try to resurrect in 10 seconds
		yrest(5000);

		-- if still dead, try macro if one defined
		if( not player.Alive ) then
			cprintf(cli.green, language[107]);  -- use the ingame resurrect macro
			RoMScript("UseSelfRevive();");	-- first try self revive 
			yrest(500);
			RoMScript("BrithRevive();");
			yrest(settings.profile.options.WAIT_TIME_AFTER_RES);	
			player:update();
		end

		-- death counter message
		cprintf(cli.green, language[109],	-- You have died %s times 
		   player.Death_counter, settings.profile.options.MAX_DEATHS);
				
		-- check maximal death if automatic mode
		if( player.Death_counter > settings.profile.options.MAX_DEATHS ) then
			cprintf(cli.yellow, language[54], player.Death_counter, 
			  settings.profile.options.MAX_DEATHS );	-- to much deaths
			player:logout();
		end

		if( player.Level > 9  and 
		    player.Alive      ) then	-- no wait if resurrect at the place of death / priest / buff
			cprintf(cli.red, language[4]);		-- Returning to waypoints after 1 minute.
			
			-- check the first debuff that player has. (it has to be the weakness!)
			local debuff = RoMScript("GetPlayerBuffLeftTime(GetPlayerBuff(1,'HARMFUL'))");
			if(debuff == nil) then debuff = 0; end;
			debuff = tonumber(debuff);
			
			if (debuff == 0 and not settings.profile.options.PK_COUNTS_AS_DEATH) then
				print("This was a PK or no xp debt death.");
				player.Death_counter = player.Death_counter - 1;
			end
			
			player:rest(debuff,debuff+15); -- wait off the debuff before going about your path.
		end

	end

	player:update();
	-- pause if still death
	if( not player.Alive ) then
		pauseOnDeath();
	end

	-- use/compare return path if defined, if not use normal one and give a warning
	-- wen need to search the closest, hence we also accept resurrection at the death place
	player:rest(10); -- give some time to be really sure that loadscreen is gone
	-- if not it could result in loading NOT the returnpath, becaus we dont hat the new position
	player.Returning = nil;
	if( __RPL and __WPL.Mode ~= "wander" ) then
		-- compare closest waypoint with closest returnpath point
		__WPL:setWaypointIndex( __WPL:getNearestWaypoint(player.X, player.Z ) );
		local hf_wp = __WPL:getNextWaypoint();
		local dist_to_wp = distance(player.X, player.Z, hf_wp.X, hf_wp.Z)

		__RPL:setWaypointIndex( __RPL:getNearestWaypoint(player.X, player.Z ) );
		local hf_wp = __RPL:getNextWaypoint();
		local dist_to_rp = distance(player.X, player.Z, hf_wp.X, hf_wp.Z)

		if( dist_to_rp < dist_to_wp ) then	-- returnpoint is closer then next normal wayoiint
			player.Returning = true;	-- then use return path first
			cprintf(cli.yellow, language[12]);	-- Starting with return path
		end
	else
		cprintf(cli.yellow, language[111], __WPL:getFileName() ); -- don't have a defined return path
	end

	if( __RPL and __WPL.Mode == "wander" ) then
		__RPL:setWaypointIndex(1);
		player.Returning = true;
		cprintf(cli.yellow, language[12]);
	end
			
	-- not using returnpath, so we use the normal waypoint path
	if( player.Returning == nil) then
		player.Returning = false;
		__WPL:setWaypointIndex( __WPL:getNearestWaypoint(player.X, player.Z ) );
		cprintf(cli.green, language[112], 	-- using normal waypoint file
		__WPL:getFileName() );
	end
end
startMacro(main);

User avatar
Administrator
Site Admin
Posts: 5329
Joined: Sat Jan 05, 2008 4:21 pm

Re: Bot stopped working.. help plz :)

#4 Post by Administrator » Wed Dec 09, 2009 5:36 pm

The problem is in your profile, near line 95.

Code: Select all

<skillst>
      <skill name="SCOUT_VAMPIRE_ARROWS"        hotkey="VK_2" priority="90" />
      <skill name="ROGUE_BLIND_STAB"    hotkey="VK_3" priority="80" />
      <skill name="ROGUE_SHADOWSTAB" hotkey="VK_4" priority="70" />
      <skill name="ROGUE_LOW_BLOW"  hotkey="VK_5" priority="90" />
      <skill name="ROGUE_WOUND_ATTACK"    hotkey="VK_6" priority="80" />
   </skills>
You opened the tag 'skillst' and closed 'skills'. Obviously, the change needed here is to change 'skillst' to 'skills'.

ginokid
Posts: 35
Joined: Tue Jul 28, 2009 10:30 pm

Re: Bot stopped working.. help plz :)

#5 Post by ginokid » Wed Dec 09, 2009 8:12 pm

Oh jeeezz LOL...
I totally missed that! :roll:
I'll fix it when I get home and test it again.

Question, how can I tell where the problem might be on my own when it says "line 98" ect...
What program do you use to tell what number all the lines are?

Thank you very much!
Gino :D

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 2 guests