-- Version 2.3 -- Written by Bill D Cat -- Edited by Rock5 --==[ Function to locate an object, move to it, and gather it ]==-- -- _itemNameOrId = Name or ID of item to gather -- _questNameOrId = Name or ID of quest to check for completion -- _doneTag = Optional waypoint tag to move to when quest is complete function moveAndGather(_itemNameOrId, _questNameOrId, _doneTag) if getQuestStatus(_questNameOrId) ~= "complete" then -- Sometimes have to gather an item that gives a border quest, therefore checking for "incomplete" will fail. _item = player:findNearestNameOrId(_itemNameOrId) if _item and 180 > distance(_item, player) then player:moveInRange(CWaypoint(_item.X, _item.Z), 39, true) repeat yrest(50) player:updateActualSpeed() until not player.Moving printf("Gathering %s (%s).\n",_item.Name, _item.Id) player:target_NPC(_item.Id) Attack() repeat yrest(100) player:updateCasting() until player.Casting == false end end if getQuestStatus(_questNameOrId) == "complete" and _doneTag ~= nil then __WPL:setWaypointIndex(__WPL:findWaypointTag(_doneTag)) end end --==[ Function to locate an object, move to it, and use a specified item on it ]==-- -- _targetNameOrId = Name or ID of Mob/Item/NPC to target -- _itemNameOrId = Name or ID of item to use on the target -- _questNameOrId = Name or ID of quest to check for completion -- _doneTag = Optional waypoint tag to move to when quest is complete local ignorelast = 0 function targetAndUse(_targetNameOrId, _itemNameOrId, _questNameOrId, _doneTag) if getQuestStatus(_questNameOrId) == "incomplete" then _target = player:findNearestNameOrId(_targetNameOrId, ignorelast) if _target and 180 > distance(_target, player) then repeat player:moveTo(CWaypoint(_target.X, _target.Z,_target.Y), true) repeat yrest(50) player:updateActualSpeed() until not player.Moving until 50 > distance(_target, player) player:target(_target) inventory:useItem(_itemNameOrId) yrest(5000) ignorelast = _target.Address end end if getQuestStatus(_questNameOrId) == "complete" and _doneTag ~= nil then __WPL:setWaypointIndex(__WPL:findWaypointTag(_doneTag)) end end --==[ Functions to hunt and kill required number of mobs until the specified quests are complete. ]==-- -- _mountAfter = true/false to mount after quest is complete -- _targetNameOrId = Name or ID of mob to kill -- _questNameOrId = ID of quest so we can check if it is complete -- _doneTag = Optional waypoint tag to move to when quest is complete -- Three concurrent mobs/quests can be specified at once if needed. function killForQuest(_mountAfter, _targetNameOrId1, _questNameOrId1, _targetNameOrId2, _questNameOrId2, _targetNameOrId3, _questNameOrId3, _doneTag) numquests = 3 if _questNameOrId2 == nil then _doneTag = _targetNameOrId2 numquests = 1 elseif _questNameOrId3 == nil then _doneTag = _targetNameOrId3 numquests = 2 end repeat status = huntMob(_targetNameOrId1, _questNameOrId1) if numquests == 2 or numquests == 3 then status = status + huntMob(_targetNameOrId2, _questNameOrId2) end if numquests == 3 then status = status + huntMob(_targetNameOrId3, _questNameOrId3) end until math.fmod(status, 5) == 0 if status == 5 * numquests then player:update() if _mountAfter == true and player.Mounted == false then print("Quest complete, mounting.") player:mount() yrest(3000) end if _doneTag then __WPL:setWaypointIndex(__WPL:findWaypointTag(_doneTag)) end end end function huntMob(_targetNameOrId, _questNameOrId) -- Clear aggro enemies first local _mob = player:findEnemy(true, nil, evalTargetDefault) if _mob then repeat player:target(_mob) player:fight() yrest(500) _mob = player:findEnemy(true, nil, evalTargetDefault) until _mob == nil end if getQuestStatus(_questNameOrId) == "complete" then return 5 end _mob = player:findEnemy(false, _targetNameOrId, evalTargetDefault) if _mob and 200 > distance(_mob, player) then player:target(_mob) player:fight() yrest(500) if getQuestStatus(_questNameOrId) == "complete" then return 5 -- Quest completed. else return 1 -- Quest not completed, but more mobs were found. end else return 0 -- Quest not completed and no additional mobs were found. end end --==[ Sets up onPreSkillCast and onSkillCast to check the targets HP and use an item if the HP is lower than the given percentage. ]==-- -- mobNameOrId = Name or ID of mob to catch -- percentHP = HP level at which to attempt to catch the mob -- itemNameOrId = Name or ID of quest item used to catch the mob -- questNameOrId = ID of quest requiring capture so we can check if it is complete function CatchMobSetup(mobNameOrId, percentHP, itemNameOrId, questNameOrId) if mobNameOrId == 0 then enable_skills() return end if type(tonumber(mobNameOrId)) == "number" then targetName = GetIdName(tonumber(mobNameOrId)) else targetName = mobNameOrId end if type(tonumber(itemNameOrId)) == "number" then toolName = GetIdName(tonumber(itemNameOrId)) else toolName = itemNameOrId end print("We will attempt to capture " .. targetName .. " using " .. toolName .. " at " .. percentHP .."% HP.") skill_state = true disable_skills() local oldOnPreSkillCast if type(settings.profile.events.onPreSkillCast) == "function" then oldOnPreSkillCast = settings.profile.events.onPreSkillCast end local oldOnSkillCast if type(settings.profile.events.onSkillCast) == "function" then oldOnSkillCast = settings.profile.events.onSkillCast end function settings.profile.events.onPreSkillCast(arg1) local mob = player:getTarget() if mob and (mob.Name == mobNameOrId or mob.Id == mobNameOrId) and (getQuestStatus(questNameOrId) == "incomplete") then if percentHP > math.ceil((mob.HP/mob.MaxHP)*100) then local wp_type = player.Current_waypoint_type __WPL:setForcedWaypointType("TRAVEL") print("Target weakened, attempting capture.") player:breakFight() player:target(mob) if distance(mob, player) > 90 then player:moveTo(CWaypoint(mob.X, mob.Z), true) yrest(500) end inventory:useItem(itemNameOrId) repeat yrest(500) until player.Casting == false __WPL:setForcedWaypointType(wp_type) return elseif math.ceil((mob.HP/mob.MaxHP)*100) > percentHP + 15 then return true else return false end elseif getQuestStatus(questNameOrId) == "complete" and skill_state == false then enable_skills() elseif oldOnPreSkillCast then oldOnPreSkillCast(arg1) -- Run original function from profile end end function settings.profile.events.onSkillCast(arg1) local mob = player:getTarget() if mob and (mob.Name == mobNameOrId or mob.Id == mobNameOrId) and (getQuestStatus(questNameOrId) == "incomplete") then if percentHP > math.ceil((mob.HP/mob.MaxHP)*100) then local wp_type = player.Current_waypoint_type __WPL:setForcedWaypointType("TRAVEL") print("Target weakened, attempting capture.") player:breakFight() player:target(mob) if distance(mob, player) > 90 then player:moveTo(CWaypoint(mob.X, mob.Z), true) yrest(500) end inventory:useItem(itemNameOrId) repeat yrest(500) until player.Casting == false __WPL:setForcedWaypointType(wp_type) return end elseif getQuestStatus(questNameOrId) == "complete" and skill_state == false then enable_skills() elseif oldOnPreSkillCast then oldOnPreSkillCast(arg1) -- Run original function from profile end end end function enable_skills() -- Re-enable skills after capture quest complete. print("Clearing the mob capture settings.") if player.Class1 == CLASS_WARLOCK then changeProfileSkill("WARLOCK_PERCEPTION_EXTRACTION", "AutoUse", true) changeProfileSkill("WARLOCK_SOUL_PAIN", "AutoUse", true) end if player.Class1 == CLASS_MAGE then changeProfileSkill("MAGE_FLAME", "AutoUse", true) end if player.Class1 == CLASS_SCOUT then changeProfileSkill("SCOUT_VAMPIRE_ARROWS", "AutoUse", true) end if player.Class1 == CLASS_PRIEST then changeProfileSkill("PRIEST_BONE_CHILL", "AutoUse", true) changeProfileSkill("PRIEST_CHAIN_OF_LIGHT", "AutoUse", true) end if player.Class1 == CLASS_ROGUE then changeProfileSkill("ROGUE_SHADOWSTAB", "AutoUse", true) end skill_state = true end function disable_skills() -- Disable certain DOT skills and other high damage skills that kill mobs way too fast to be able to catch them. if player.Class1 == CLASS_WARLOCK then changeProfileSkill("WARLOCK_PERCEPTION_EXTRACTION", "AutoUse", false) changeProfileSkill("WARLOCK_SOUL_PAIN", "AutoUse", false) end if player.Class1 == CLASS_MAGE then changeProfileSkill("MAGE_FLAME", "AutoUse", false) end if player.Class1 == CLASS_SCOUT then changeProfileSkill("SCOUT_VAMPIRE_ARROWS", "AutoUse", false) end if player.Class1 == CLASS_PRIEST then changeProfileSkill("PRIEST_BONE_CHILL", "AutoUse", false) changeProfileSkill("PRIEST_CHAIN_OF_LIGHT", "AutoUse", false) end if player.Class1 == CLASS_ROGUE then changeProfileSkill("ROGUE_SHADOWSTAB", "AutoUse", false) end skill_state = false end --==[ Functions to try and Accept and Complete quests during a structured waypoint file. ]==-- -- Failure to successfully accept or complete a quest will pause the bot to allow you to fix the problem. function SureAcceptQuest(quest) if RoMScript("CheckQuest("..quest..")") == 0 then -- 0 = Not done yet and not accepted AcceptQuestByName(quest) yrest(500) if RoMScript("CheckQuest("..quest..")") == 0 then -- Try a second time to be sure AcceptQuestByName(quest) yrest(500) if RoMScript("CheckQuest("..quest..")") == 0 then print("\aFailed to accept quest: \""..GetIdName(quest).."\". Please fix, then resume.") player:sleep() end end end end function SureCompleteQuest(quest, reward) if RoMScript("CheckQuest("..quest..")") ~= 2 then -- 2 = Already done CompleteQuestByName(quest, reward) yrest(500) if RoMScript("CheckQuest("..quest..")") ~= 2 then -- Try a second time to be sure CompleteQuestByName(quest, reward) while ItemQueueCount() > 0 and inventory:itemTotalCount(0) > 0 do yrest(500) end yrest(500) if RoMScript("CheckQuest("..quest..")") ~= 2 then print("\aFailed to complete quest: \""..GetIdName(quest).."\". Please fix, then resume.") player:sleep() end end end end --==[ Simple function to swap classes at any housekeeper ]==-- -- Target any housemaid and open the dialog before running this function. -- mainClass = CLASS_WARRIOR, CLASS_SCOUT, etc. to become your primary class. No quotes around the class name. -- secClass = CLASS_WARRIOR, CLASS_SCOUT, etc. to become your secondary class. No quotes around the class name. -- If no arguments are given, then the player's current classes will be swapped. function swapClass(mainClass, secClass) if not ChoiceOptionByName(getTEXT("HOUSE_MAID_HOUSE_CHANGEJOB")) then -- 'Change class' ChoiceOptionByName(getTEXT("SO_110581_1")) -- 'I want to switch my primary and secondary class.' end yrest(3000) player:update() local pri, sec if mainClass == nil then pri = player.Class2 + 1 sec = player.Class1 + 1 else pri = mainClass + 1 sec = secClass + 1 end RoMScript("ExchangeClass("..pri..","..sec..")") end