diff --git a/.gitignore b/.gitignore index 6fd0a37..09c9366 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ luac.out *.x86_64 *.hex +/test_pclib_retrieveFirstById.lua +/.idea/ diff --git a/Classes/Pokemon.lua b/Classes/Pokemon.lua index 67c0165..38c1a66 100644 --- a/Classes/Pokemon.lua +++ b/Classes/Pokemon.lua @@ -33,6 +33,7 @@ function Pokemon:newFromPC(boxIndex, boxPokemonIndex) o.totalXp = getPokemonTotalExperienceFromPC (boxIndex, boxPokemonIndex) o.remainingXP = getPokemonRemainingExperienceFromPC(boxIndex, boxPokemonIndex) o.uniqueId = getPokemonUniqueIdFromPC (boxIndex, boxPokemonIndex) + o.id = getPokemonIdFromPC (boxIndex, boxPokemonIndex) o.isShiny = isPokemonFromPCShiny (boxIndex, boxPokemonIndex) o.item = getPokemonHeldItemFromPC (boxIndex, boxPokemonIndex) o.level = getPokemonLevelFromPC (boxIndex, boxPokemonIndex) diff --git a/Classes/Set.lua b/Classes/Set.lua new file mode 100644 index 0000000..d7d752e --- /dev/null +++ b/Classes/Set.lua @@ -0,0 +1,68 @@ +--@author m1l4 +--inspired from: https://www.lua.org/pil/13.1.html + +local gen = require "libs.genlib" + +Set = {} + +--object methods +function Set:new(t) + local set = {} + setmetatable(set, self) + + self.__index = self + self.__len = gen.size + self.__class = "Set" + + for _, e in pairs(t) do set[e] = true end + return set +end + +function Set:contains(a) + return self[a] +end + +function Set:tostring() + local s = "{" + local sep = "" + for e in pairs(self) do + s = s .. sep .. tostring(e) + sep = ", " + end + return s .. "}" +end + +function Set:print() + print(self:tostring()) +end + +function Set.union (a,b) + local res = Set:new{} + for k in pairs(a) do res[k] = true end + for k in pairs(b) do res[k] = true end + return res +end + +function Set.intersection (a,b) + if not a.__class or not a.__class == "Set" then a = Set:new(a) end + if not b.__class or not b.__class == "Set" then b = Set:new(b) end + + local res = Set:new{} + for k in pairs(a) do + res[k] = b[k] + end + + if #res == 0 then return nil end + return res +end + +--Tests +--a = Set:new{1,3,5,7,8,9 } +--b = Set:new{8,2,4,10} +--s = Set.intersection(a,b) +--s:print() +--print(a[10]) +--print(#s) +--print(s:contains()) + +return Set \ No newline at end of file diff --git a/Data/cutTargets.lua b/Data/cutTargets.lua new file mode 100644 index 0000000..663675a --- /dev/null +++ b/Data/cutTargets.lua @@ -0,0 +1,272 @@ +---@author: m1l4 +---@summary: A dictionary, containing all pokemon that are able to cut (HM01) +---@attention: Autogenerated using following as source: https://bulbapedia.bulbagarden.net/wiki/Cut_(move) +---so there might be variations to PRO's implementation. Those have to be adressed on the flow. +---@comment: copied from my own project and reduced +---@param dictKey: the pkm index of the pkm to be tested for cut ability +---@type dictKey: integer +---@return: true, if pkm has the ability to learn cut | false, otherwise +---@type: boolean +local CutTargets = { + [1] = true, + [2] = true, + [3] = true, + [4] = true, + [5] = true, + [6] = true, + [15] = true, + [19] = true, + [20] = true, + [27] = true, + [28] = true, + [29] = true, + [30] = true, + [31] = true, + [32] = true, + [33] = true, + [34] = true, + [43] = true, + [44] = true, + [45] = true, + [46] = true, + [47] = true, + [50] = true, + [51] = true, + [52] = true, + [53] = true, + [69] = true, + [70] = true, + [71] = true, + [72] = true, + [73] = true, + [83] = true, + [98] = true, + [99] = true, + [108] = true, + [112] = true, + [114] = true, + [115] = true, + [123] = true, + [127] = true, + [141] = true, + [149] = true, + [151] = true, + [152] = true, + [153] = true, + [154] = true, + [155] = true, + [156] = true, + [157] = true, + [158] = true, + [159] = true, + [160] = true, + [161] = true, + [162] = true, + [182] = true, + [190] = true, + [191] = true, + [192] = true, + [196] = true, + [197] = true, + [207] = true, + [208] = true, + [212] = true, + [214] = true, + [215] = true, + [216] = true, + [217] = true, + [227] = true, + [243] = true, + [244] = true, + [245] = true, + [248] = true, + [251] = true, + [252] = true, + [253] = true, + [254] = true, + [255] = true, + [256] = true, + [257] = true, + [263] = true, + [264] = true, + [274] = true, + [275] = true, + [286] = true, + [287] = true, + [288] = true, + [289] = true, + [290] = true, + [291] = true, + [292] = true, + [302] = true, + [304] = true, + [305] = true, + [306] = true, + [315] = true, + [331] = true, + [332] = true, + [341] = true, + [342] = true, + [347] = true, + [348] = true, + [352] = true, + [357] = true, + [359] = true, + [371] = true, + [372] = true, + [373] = true, + [375] = true, + [376] = true, + [380] = true, + [381] = true, + [383] = true, + [386] = true, + [387] = true, + [388] = true, + [389] = true, + [390] = true, + [391] = true, + [392] = true, + [393] = true, + [394] = true, + [395] = true, + [399] = true, + [400] = true, + [402] = true, + [406] = true, + [407] = true, + [409] = true, + [416] = true, + [417] = true, + [424] = true, + [425] = true, + [426] = true, + [427] = true, + [428] = true, + [431] = true, + [432] = true, + [434] = true, + [435] = true, + [443] = true, + [444] = true, + [445] = true, + [451] = true, + [452] = true, + [454] = true, + [455] = true, + [461] = true, + [463] = true, + [464] = true, + [465] = true, + [472] = true, + [475] = true, + [483] = true, + [484] = true, + [487] = true, + [491] = true, + [493] = true, + [495] = true, + [496] = true, + [497] = true, + [501] = true, + [502] = true, + [503] = true, + [504] = true, + [505] = true, + [509] = true, + [510] = true, + [511] = true, + [512] = true, + [513] = true, + [514] = true, + [515] = true, + [516] = true, + [529] = true, + [530] = true, + [540] = true, + [541] = true, + [542] = true, + [545] = true, + [548] = true, + [549] = true, + [550] = true, + [551] = true, + [552] = true, + [553] = true, + [557] = true, + [558] = true, + [566] = true, + [567] = true, + [570] = true, + [571] = true, + [586] = true, + [587] = true, + [588] = true, + [589] = true, + [595] = true, + [596] = true, + [598] = true, + [604] = true, + [610] = true, + [611] = true, + [612] = true, + [613] = true, + [614] = true, + [621] = true, + [624] = true, + [625] = true, + [626] = true, + [627] = true, + [628] = true, + [629] = true, + [630] = true, + [631] = true, + [632] = true, + [638] = true, + [639] = true, + [640] = true, + [643] = true, + [644] = true, + [646] = true, + [647] = true, + [650] = true, + [651] = true, + [652] = true, + [653] = true, + [654] = true, + [655] = true, + [656] = true, + [657] = true, + [658] = true, + [659] = true, + [660] = true, + [674] = true, + [675] = true, + [677] = true, + [678] = true, + [679] = true, + [680] = true, + [681] = true, + [686] = true, + [687] = true, + [688] = true, + [689] = true, + [692] = true, + [693] = true, + [694] = true, + [695] = true, + [700] = true, + [701] = true, + [702] = true, + [707] = true, + [708] = true, + [709] = true, + [714] = true, + [715] = true, + [716] = true, + [717] = true, + [721] = true, + [798] = true, +} + +return CutTargets \ No newline at end of file diff --git a/Data/surfTargets.lua b/Data/surfTargets.lua new file mode 100644 index 0000000..1e790f7 --- /dev/null +++ b/Data/surfTargets.lua @@ -0,0 +1,241 @@ +---@author: m1l4 +---@summary: A dictionary, containing all pokemon that are able to surf (HM03) +---@attention: Autogenerated using following as source: https://bulbapedia.bulbagarden.net/wiki/Surf_(move) +---so there might be variations to PRO's implementation. Those have to be adressed on the flow. +---@comment: copied from my own project and reduced +---@param dictKey: the pkm index of the pkm to be tested for surf ability +---@type dictKey: integer +---@return: true, if pkm has the ability to learn surf | false, otherwise +---@type: boolean +local SurfTarget = { + [7] = true, + [8] = true, + [9] = true, +-- [25] = true, --pikachu - removed since it has to be taught by victor and is only available when pikachu was picked as starter + [31] = true, + [34] = true, + [54] = true, + [55] = true, + [60] = true, + [61] = true, + [62] = true, + [72] = true, + [73] = true, + [79] = true, + [80] = true, + [86] = true, + [87] = true, + [90] = true, + [91] = true, + [98] = true, + [99] = true, + [108] = true, + [112] = true, + [115] = true, + [116] = true, + [117] = true, + [118] = true, + [119] = true, + [120] = true, + [121] = true, + [128] = true, + [130] = true, + [131] = true, + [134] = true, + [138] = true, + [139] = true, + [140] = true, + [141] = true, + [143] = true, + [147] = true, + [148] = true, + [149] = true, + [151] = true, + [158] = true, + [159] = true, + [160] = true, + [161] = true, + [162] = true, + [170] = true, + [171] = true, + [183] = true, + [184] = true, + [186] = true, + [194] = true, + [195] = true, + [199] = true, + [211] = true, + [215] = true, + [222] = true, + [223] = true, + [224] = true, + [226] = true, + [230] = true, + [241] = true, + [245] = true, + [248] = true, + [249] = true, + [258] = true, + [259] = true, + [260] = true, + [263] = true, + [264] = true, + [270] = true, + [271] = true, + [272] = true, + [279] = true, + [295] = true, + [296] = true, + [297] = true, + [298] = true, + [306] = true, + [318] = true, + [319] = true, + [320] = true, + [321] = true, + [339] = true, + [340] = true, + [341] = true, + [342] = true, + [349] = true, + [350] = true, + [363] = true, + [364] = true, + [365] = true, + [366] = true, + [367] = true, + [368] = true, + [369] = true, + [370] = true, + [380] = true, + [381] = true, + [382] = true, + [384] = true, + [393] = true, + [394] = true, + [395] = true, + [400] = true, + [409] = true, + [418] = true, + [419] = true, + [422] = true, + [423] = true, + [445] = true, + [446] = true, + [456] = true, + [457] = true, + [458] = true, + [461] = true, + [463] = true, + [464] = true, + [484] = true, + [489] = true, + [490] = true, + [493] = true, + [501] = true, + [502] = true, + [503] = true, + [507] = true, + [508] = true, + [515] = true, + [516] = true, + [531] = true, + [535] = true, + [536] = true, + [537] = true, + [550] = true, + [564] = true, + [565] = true, + [580] = true, + [581] = true, + [592] = true, + [593] = true, + [594] = true, + [612] = true, + [613] = true, + [614] = true, + [618] = true, + [621] = true, + [626] = true, + [635] = true, + [647] = true, + [656] = true, + [657] = true, + [658] = true, + [659] = true, + [660] = true, + [672] = true, + [673] = true, + [674] = true, + [675] = true, + [676] = true, + [684] = true, + [685] = true, + [688] = true, + [689] = true, + [690] = true, + [691] = true, + [692] = true, + [693] = true, + [694] = true, + [695] = true, + [712] = true, + [713] = true, + [728] = true, + [729] = true, + [730] = true, + [746] = true, + [747] = true, + [748] = true, + [751] = true, + [752] = true, + [767] = true, + [768] = true, + [773] = true, + [779] = true, + [780] = true, + [781] = true, + [788] = true, +} + +--redundant, but keeps a clean interface with other methods +function SurfTarget.canSurf(pkmId) + return SurfTarget[pkmId] +end + +function SurfTarget.first() + --init pkmId + return SurfTarget.next(0) +end + +--TODO: add to genlib +function SurfTarget.next(pkmId) + if not pkmId then return fatal("SurfTarget.next(pkmId) expects an integer as input.") end + for i = pkmId + 1, #SurfTarget do + if SurfTarget[i] then + log("SurfTarget next: "..i.." | input: "..pkmId) + return i + end + end +end + +function SurfTarget.getIds() + local values = {} + for pkmId, isSurfer in pairs(SurfTarget) do + if isSurfer then table.insert(values, pkmId) end + end + return values +end + +--set dict size as highest value +local function size(table) return 788 end +setmetatable(SurfTarget, {__len = size}) + +-- +--log(SurfTarget[781]) +--log(SurfTarget[782]) +--log(SurfTarget.first()) + + + +return SurfTarget \ No newline at end of file diff --git a/Libs/gamelib.lua b/Libs/gamelib.lua index 1d1ec4d..c1c1d66 100644 --- a/Libs/gamelib.lua +++ b/Libs/gamelib.lua @@ -10,17 +10,16 @@ local sys = require("Libs/syslib") function game.isTeamFullyHealed() for pokemonId=1, getTeamSize(), 1 do if getPokemonHealthPercent(pokemonId) < 100 - or not game.isFullPP(pokemonId) then + or not game.isPokemonFullPP(pokemonId) then return false end end return true end -function game.isFullPP(pokemonId) +function game.isPokemonFullPP(pokemonId) for moveId = 1, 4 do local move = getPokemonMoveName(pokemonId, moveId) - sys.debug("move: "..tostring(move)) if move and --has a move on index and getRemainingPowerPoints(pokemonId, move) ~= getPokemonMaxPowerPoints(pokemonId, moveId) --move is not full recovered then return false end @@ -28,20 +27,19 @@ function game.isFullPP(pokemonId) return true end -function game.isPokemonFullPP(pokemonId) - sys.todo("add getPokemonMoves() to PROShine") - error("waiting for proshine update") - return true -end - function game.useAnyMove() + sys.debug("game.useAnyMove()", "start", true) local pokemonId = getActivePokemonNumber() - for i=1,4 do - local moveName = getPokemonMoveName(pokemonId, i) - if not moveName and getPokemonMoveRemainingPowerPoints() > 0 then + sys.debug("activeId", pokemonId) + for moveId=1,4 do + local moveName = getPokemonMoveName(pokemonId, moveId) + if moveName and getPokemonMaxPowerPoints(pokemonId, moveId) > 0 then + sys.debug("Using any move", moveName) + sys.debug("game.useAnyMove()", "end", true) return useMove(moveName) end end + sys.debug("game.useAnyMove()", "end", true) return false end @@ -81,17 +79,6 @@ function game.inRectangle(x1, y1, x2, y2) return false end -function game.minTeamLevel() - local current - for pokemonId=1, getTeamSize(), 1 do - local pokemonLevel = getPokemonLevel(pokemonId) - if current == nil or pokemonLevel < current then - current = pokemonLevel - end - end - return current -end - function game.maxTeamLevel() local current for pokemonId=1, getTeamSize(), 1 do diff --git a/Libs/genlib.lua b/Libs/genlib.lua new file mode 100644 index 0000000..bb787ef --- /dev/null +++ b/Libs/genlib.lua @@ -0,0 +1,38 @@ +gen = {} + +--TODO: make a separate lib project and remove the redundances in pathfinder and own workspace +--since many things are copied from there +--filter +--TODO: write globa library, from my project's, pathfinder's and questing's library - all those are doing the same... + +--comparers - normally it makes no difference if >= is used or not, +-- but when using it in methods it becomes mandator to prevent +-- + +--TODO: remvoe the level part and make it a clean max, min +function gen.maxLvl(a, b) return getPokemonLevel(b) >= getPokemonLevel(a) end --greater **equal** is necesarry to avoid swaping same lvled pkm +function gen.minLvl(a, b) return getPokemonLevel(b) < getPokemonLevel(a) end --lesser is necesarry to avoid swaping same lvled pkm + +--compare functions +function gen.smaller(a, b) return a < b end +function gen.higher(a, b) return a > b end + +--filter +function gen.first(t) t = t or {} if #t > 0 then return t[1] end end +function gen.last(t) t = t or {} if #t > 0 then return t[#t] end end + +--generic - at least all pkm properties or even more could be reduced +function gen.equal(i, fn, value) return fn(i)==value end + + + +function gen.size(table) + local count = 0 + for k in pairs(table) do + count = count + 1 + end + return count +end + + +return gen \ No newline at end of file diff --git a/Libs/pclib.lua b/Libs/pclib.lua index c00ad20..e2f763b 100644 --- a/Libs/pclib.lua +++ b/Libs/pclib.lua @@ -3,109 +3,378 @@ -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. -local pc = {} - +local gen = require("Libs/genlib") local sys = require("Libs/syslib") +local team = require("Libs/teamlib") +local Pokemon = require("Classes/Pokemon") +local Set = require("Classes/Set") + +local pc = {} function pc.isValidIndex(boxIndex, pokemonIndex) - if getCurrentBoxId() == boxIndex and pokemonIndex <= getCurrentBoxSize() then - return true - end - return false + if getCurrentPCBoxId() == boxIndex and pokemonIndex <= getCurrentBoxSize() then + return true + end + return false end function pc.isReady() - if isPCOpen() and isCurrentPCBoxRefreshed() then - return true - end - return false + if isPCOpen() and isCurrentPCBoxRefreshed() then + return true + end + return false end function pc.use() - if isPCOpen() then - if isCurrentPCBoxRefreshed() then - return - else - -- we wait - return - end - else - if not usePC() then - sys.error("libpc.use", "Tried to use the PC in a zone without PC") - end - end + if isPCOpen() then + if isCurrentPCBoxRefreshed() then + return + else + -- we wait + return + end + else + if not usePC() then + sys.error("libpc.use", "Tried to use the PC in a zone without PC") + end + end end -- this function needs to be called multiple time -- returns true once the swap is done function pc.swap(boxIndex, boxPokemonIndex, teamIndex) - if not pc.isReady() then - pc.use() - return false - else - if not swapPokemonFromPC(boxIndex, boxPokemonIndex, teamIndex) then - return sys.error("libpc.swap", "Failed to swap") - else - return true - end - end - return false + if not pc.isReady() then + pc.use() + return false + else + if not swapPokemonFromPC(boxIndex, boxPokemonIndex, teamIndex) then + return sys.error("libpc.swap", "Failed to swap") + else + return true + end + end + return false end -- this function needs to be called multiple time -- returns true once deposit is done function pc.deposit(teamIndex) - if not pc.isReady() then - pc.use() - return false - else - if not depositPokemonToPC(__teamIndex) then - return sys.error("libpc.deposit", "Failed to deposit") - end - return true - end - return false + if not pc.isReady() then + pc.use() + return false + else + if not depositPokemonToPC(__teamIndex) then + return sys.error("libpc.deposit", "Failed to deposit") + end + return true + end + return false end -- this function needs to be called multiple time -- returns true once withdraw is done function pc.withdraw(boxIndex, boxPokemonIndex) - if not pc.isReady() then - pc.use() - return false - else - if getTeamSize() == 6 then - return sys.error("libpc.withdraw", "Team full. Could not withdraw the pokemon " - .. getPokemonNameFromPC(boxIndex, boxPokemonIndex)) - end - if not withdrawPokemonFromPC(boxIndex, boxPokemonIndex, teamIndex) then - return sys.error("libpc.deposit", "Failed to deposit") - end - return true - end - return false + if not pc.isReady() then + pc.use() + return false + else + if getTeamSize() == 6 then + return sys.error("libpc.withdraw", "Team full. Could not withdraw the pokemon " + .. getPokemonNameFromPC(boxIndex, boxPokemonIndex)) + end + if not withdrawPokemonFromPC(boxIndex, boxPokemonIndex, teamIndex) then + return sys.error("libpc.deposit", "Failed to deposit") + end + return true + end + return false +end + + +--some first interface methods | collected by the current questing needs + some obvious ones +function pc.retrieveFirstWithMovesFromRegions(moves, regions, swapId) + return pc._retrieveFirst{swapId = swapId, moves=moves, region = regions} +end + +function pc.retrieveFirstFromNamesBelowLvl(pkmNames, level, swapId) + return pc._retrieveFirst{swapId = swapId, name = pkmNames, level = level, lvlComparer = gen.smaller} +end + +function pc.retrieveFirstFromNamesAboveLvl(pkmNames, level, swapId) + return pc._retrieveFirst{swapId = swapId, name = pkmNames, level = level, lvlComparer = gen.higher} +end + +function pc.retrieveFirstFromNames(pkmNames, swapId) + return pc._retrieveFirst{swapId = swapId, name = pkmNames} +end + +function pc.retrieveFirstFromIds(ids, swapId) + return pc._retrieveFirst{swapId = swapId, id = ids} +end + + + +--- @summary : Retrieves all pkm from the PC. Starts with latest page to potentially add higher level pkm prior +--- to lower leveled ones +function pc._collect() + --start pc + if not isPCOpen() then return usePC() end + + --refresing + if not isCurrentPCBoxRefreshed() then return sys.debug("refreshed") end + + --start with last box | to get potentially highest level matching pkm + --init values + pc.boxId = pc.boxId or getPCBoxCount() --appended to pc, to avoid namespace interference + pc.pkmListCol = pc.pkmListCol or {} -- ... same ... + + --read table if desired is open + if pc.boxId == getCurrentPCBoxId() then + + --check each box item + for slotId = 1, getCurrentPCBoxSize() do + + --read data from slot and add it + local pkm = Pokemon:newFromPC(pc.boxId, slotId) + table.insert(pc.pkmListCol, { pkm, pc.boxId, slotId }) + end + + --indicate next page to be loaded + pc.boxId = pc.boxId - 1 + end + + --if we are on last page clean up + if pc.boxId < 1 then + --temp variable + local returnList = pc.pkmListCol + + --reset values + pc.boxId = getPCBoxCount() + pc.pkmListCol = nil + + --return collection + return returnList + end + + --open pcbox if current is not open | or end of current is reached + return openPCBox(pc.boxId) +end + + + +--TODO: update luadoc to fit the new "named arguments" implementation +--- @summary : Retrieves a pkm from the box, that matches given parameters. Handles held items as well. +--- params: +--- @param swapId: 1-6 | pkm team ids: which indicates the swap target for a match | default: lowest leveled pkm +--- @type : integer | nil +--- @param ids: 1-775 | pkm ids: searches for all or first pkm with given ids | nil, not checking +--- @type : integer list | nil +--- @param pkmNames: pkm name: searches for all or the first pkm with given name | nil, not checking +--- @type : string list | nil +--- @param moves: moves name: searches for all or the first pkm with given moves | nil, not checking +--- @type : string list | nil +--- @param regions: 1-4 | regions ids: searches for all or the first pkm from that regions | nil, not checking +--- @type : string list | nil +--- following can only be used together: +--- @param level: 1-100 | searches for the first pkm with a level lvlComparer accepts | nil, if not checking +--- @type : integer | nil +--- @param lvlComparer: compares given level and pokemons level, returns: true for a match, false otherwise | nil, if not checking +--- @type : function | nil +--- return slotId, boxId, swapId +--- @return : +--- @type : list {dict} integer, integer, integer +function pc._retrieveFirst(args) + --preparing swap target + --assert(args.swapId, "pc._retrieveFirst needs a swapId parameter") + local swapId = args.swapId or team.getLowestLvlPkm() + args.swapId = nil + + -- start search if we didn't do it before | this occurs when switching pcBox as you have to terminate, + -- since you couldn't perform a swap in the same cycle or it would create a "two actions in one frame + -- exception" + if not pc.firstMatch then + + --leftovers had to be disabled, so they wouldn't interfere with taking them away + leftovers_disabled = true + + -- taking held item, if it has one + local heldItem = getPokemonHeldItem(swapId) + if heldItem then + takeItemFromPokemon(swapId) + return pc.result.WORKING + end + + pc.pkmList = pc._collect() + end + + --has solution + if pc.firstMatch or type(pc.pkmList) == "table" then + --append pc search result + args.pkmList = pc.pkmList + pc.firstMatch = pc.firstMatch or pc._getFirstMatch(args) --appended to pc context, to prevent naming duplicates in user scripts + + --no result, if no pkm matches + if not pc.firstMatch then return pc.result.NO_RESULT end + + --else initate transfer process + local pkm, boxId, slotId = pc._split(pc.firstMatch) + + -- open correct box for transfer + if boxId ~= getCurrentPCBoxId() then + openPCBox(boxId) + return pc.result.WORKING + end + + + --retrieve match + local isSwap = getTeamSize() >= 6 + if isSwap then swapPokemonFromPC(boxId, slotId, swapId) + else withdrawPokemonFromPC(boxId, slotId) end + + --cleanup + leftovers_disabled = false --active leftovers again + pc.firstMatch = nil --clear match result, for next query + + return pkm, boxId, slotId, swapId + + --no solution + elseif not pc.pkmList then + return pc.result.NO_RESULT + + --result is a function: state working + elseif pc.pkmList == true then + return pc.result.WORKING + + else sys.debug("pc._retrieveFirst: unsupported state. pc._collect ".. + "has neither true, false or table as return value.") + end +end + +function pc._split(item) + local pkm, boxId, slotId = item[1], item[2], item[3] + return pkm, boxId, slotId +end + +--- @param : itemList +-- usage example: rename{old="temp.lua", new="temp1.lua"} +function pc._getFirstMatch(args) + return gen.first(pc._getMatches(args)) +end + +function pc._getMatches(args) + --retrieve itemList and remove, for the iteration of arg + assert(args.pkmList, "pc._getMatches needs a pkmList from pc._collect()") + local pkmList = args.pkmList + args.pkmList = nil + + --make sure that if level given, lvlComparer exists + assert(not args.level or args.level and args.lvlComparer, "pc._getMatches" .. + "don't accepts argument level unless lvlComparer is given as well") + local lvlComparer = args.lvlComparer + args.lvlComparer = nil + + + --pokemon class vars + local posArgs = Set:new { + "ev", "iv", "moves", "name", "nature", "ability", + "happiness", "region", "trainer", "gender", "totalXp", + "remainingXP", "uniqueId", "id", "isShiny", "item", + "level", "totalHP", "percentHP", "currentHP" + } + + --iterating all pokemon + local matches = {} + for _, item in pairs(pkmList) do + local pkm = item[1] + + --iterate arguments + local match = true + for testParam, testValue in pairs(args) do + assert(posArgs:contains(testParam), "pc._getMatches: unsupported compare attribute: "..tostring(testParam)) + + local testValueSet = Set:new(testValue) + local pkmValue = pkm[testParam] + local checkResult = false + + --moves | exception handling + if testParam == "moves" then + local moveList = pc._transform(pkm.moves, pc._getProperty, "name") + + --meaining: size of intersection of moves and pkmMoves has to at least 1 + -- -- = one item is contained in both lists + checkResult = Set.intersection(testValueSet, moveList) + + --level | exception handling + elseif testParam == "level" and lvlComparer then + assert(testValue ~= integer, "pc._getMatches expects an integer as level if no comparison function \"lvlComparer\" is given.") + checkResult = lvlComparer(testValue, pkmValue) + + --basic items | table testValue, meaning: testValue is in that table + elseif type(testValue) == "table" then + checkResult = testValueSet:contains(pkmValue) + + --basic items | check same value + else checkResult = testValue == pkmValue end + + --binary and, all arguments have to match + match = match and checkResult + end + + + if match then table.insert(matches, item) end + end + + return matches +end + +--transform +function pc._transform(t, fn, ...) + local transTbl = {} + for key, value in pairs(t) do + --key param: unnecessary, if key is integer | necessary, for every other tpye + --sys.debug(key .." | "..value .." |" .. fn(value)) --not possible with reltive pathing + table.insert(transTbl, value, fn(value, ...)) + end + return transTbl end + +function pc._wrap(obj) + if not obj then return + elseif type(obj) ~= table then return { obj } + end + return obj +end + + +function pc._getProperty(o, prop) if o[prop] then return o[prop] end end + +pc.result = { + EXCEPTION = 0, --needed? just call fatal + WORKING = 1, + NO_RESULT = 2, + FINISHED = 3 +} + + function pc.gatherDatas(sortingFunction) - end -- sortingFunction must take 2 pokemons as parameters (id + box) and return a bool --- i.e.: +-- i.e.: --[[ - function sortByUniqueId(boxIndexA, boxPokemonIndexA, boxIndexB, boxPokemonIndexB) - if (getPokemonUniqueIdFromPC(boxIndexA, boxPokemonIndexA) > - getPokemonUniqueIdFromPC(boxIndexB, boxPokemonIndexB) - then - return true - end - return false - end - - pc.sort(sortByUniqueId) + function sortByUniqueId(boxIndexA, boxPokemonIndexA, boxIndexB, boxPokemonIndexB) + if (getPokemonUniqueIdFromPC(boxIndexA, boxPokemonIndexA) > + getPokemonUniqueIdFromPC(boxIndexB, boxPokemonIndexB) + then + return true + end + return false + end + + pc.sort(sortByUniqueId) --]] function pc.sort(sortingFunction) - end -return pc \ No newline at end of file +return pc diff --git a/Libs/syslib.lua b/Libs/syslib.lua index ea3e0f5..f429e2c 100644 --- a/Libs/syslib.lua +++ b/Libs/syslib.lua @@ -1,19 +1,35 @@ local sys = {} -function sys.debug(message) - if debug then - log("DEBUG | " .. message) + + +function sys.debug(valDescription, value, isTitle) + if DEBUG then + value = value or "nil" + value = tostring(value) + local message = valDescription ..": "..value + --indent + sys._printIndent("DEBUG | ", message, isTitle) end end +function sys._printIndent(prefix, message, isTitle) + local indent = "\t" + if isTitle then indent = "" end + log("DEBUG | " ..indent.. message) +end + function sys.todo(message) - if todo then + if TODO then + message = message or "" log("TODO | " .. message) end end +function sys.info(message) return log("INFO | "..message) end +function sys.log(message) return log("LOG | "..message) end + function sys.error(functionName, message) - return fatal("ERROR | " .. functionName .. ": " .. message) + return fatal("ERROR | " .. tostring(functionName) .. ": " .. tostring(message)) end function sys.assert(test, functionName, message) @@ -38,12 +54,12 @@ function sys.removeCharacter(str, character) end function sys.tableHasValue(tab, val) - for index, value in ipairs(tab) do - if value == val then - return true - end - end - return false + for index, value in ipairs(tab) do + if value == val then + return true + end + end + return false end -return sys +return sys \ No newline at end of file diff --git a/Libs/teamlib.lua b/Libs/teamlib.lua new file mode 100644 index 0000000..5c1d7fc --- /dev/null +++ b/Libs/teamlib.lua @@ -0,0 +1,267 @@ +---@author: m1l4 +---@comment: copied and reduced code from TeamManager class which wasn't finished at the I copyPasted it here, +---so there might be redundancies. Additionally: simplifications of the current code through usage of this module +---are only done sparsly - those will be coming with future updates a litte at a time +---@attention: functions, variables and comments are reffering another project's context. So keep that in mind +---when reading comments :) +-- ------------------------- + +local gen = require("Libs/genlib") + +--|x, y| x + y is shorthand for function(x,y) return x+y end. +team = {} +--pkm conditions +function team.isPkmAlive(i) return getPokemonHealth(i) > 0 end +function team.isPkmToLvl(i, lvl_cap) return getPokemonLevel(i) < lvl_cap end +function team.isPkmToLvlAlive(i, lvl_cap) return team.isPkmAlive(i) and team.isPkmToLvl(i, lvl_cap) end +function team.isPkmToLvlUsable(i, lvl_cap) return isPokemonUsable(i) and team.isPkmToLvl(i, lvl_cap) end +--pkm properties +function team.hasPkmItem(i, item) return getPokemonHeldItem(i) == item end +function team.hasPkmAbility(i, abilty) return getPokemonAbility(i) == abilty end +function team.hasPkmNature(i, nature) return getPokemonNature(i) == nature end +function team.hasPkmMove(i, move) return hasMove(i, move) end + + + +--- @summary : fetches all pkm under given level cap +--- @param level_cap: upper level treshold, 100 by default +--- @type level_cap: integer +--- @return : list of team indexes of all pkm that can be leveled up +--- @type : table (list of integers) +function team.getPkmToLvl(level_cap) + return team._filter(team.getPkm(), team.isPkmToLvl, level_cap) +end + +--- @summary : Searches the lowest leveled pkm under given level_cap +--- @param level_cap: upper level treshold, 100 by default +--- @type level_cap: integer +--- @return : team index, of lowest leveled pkm under level_cap | nil, if none exists +--- @type : integer | nil +function team.getLowestPkmToLvl(level_cap) + return team._compare(team.getPkmToLvl(level_cap), gen.minLvl) +end + +function team.getAlivePkmToLvl(level_cap) + return team._filter(team.getPkm(), team.isPkmToLvlAlive, level_cap) +end + +function team.getLowestAlivePkmToLvl(level_cap) + return team._compare(team.getAlivePkmToLvl(level_cap), gen.minLvl) +end + +--- @summary : Searches the lowest leveled pkm under given level_cap +--- @param level_cap: upper level treshold, 100 by default +--- @type level_cap: integer +--- @return : team index, of lowest leveled pkm under level_cap | nil, if none exists +--- @type : integer | nil +function team.getLowestUsablePkmToLvl(level_cap) + return team._compare(team.getUsablePkmToLvl(), gen.minLvl) +end + +--- @summary : fetches all pkm under given level cap, that are able to battle +--- @param level_cap: upper level treshold, 100 by default +--- @type level_cap: integer +--- @return : list of team indexes of all battle-ready pkm that can be leveled up +--- @type : table (list of integers) +function team.getUsablePkmToLvl(level_cap) + return team._filter(team.getUsablePkm(), team.isPkmToLvl, level_cap) +end + +--- @summary : Searches the lowest leveled pkm under given level_cap +--- @param level_cap: upper level treshold, 100 by default +--- @type level_cap: integer +--- @return : team index, of lowest leveled pkm under level_cap | nil, if none exists +--- @type : integer | nil +function team.getRndPkmToLvl(level_cap) + local pkmToLvl = team.getPkmToLvl(level_cap) + if not pkmToLvl then return end + + return pkmToLvl[math.random(#pkmToLvl)] +end + + + + + +function team.getAlivePkm() + return team._filter(team.getPkm(), team.isPkmAlive) +end + +function team.getFirstPkmAlive() + return gen.first(team.getAlivePkm()) +end + +---duplicate, but easy to understand +function team.getStarter() + return team.getFirstPkmAlive() +end + +function team.getLastPkmAlive() + return gen.last(team.getAlivePkm()) +end + +function team.getHighestPkmAlive() + return team._compare(team.getAlivePkm(), gen.maxLvl) +end + +function team.getLowestLvlPkm() + return team._compare(team.getPkm(), gen.minLvl) +end + +function team.getLowestPkmAlive() + return team._compare(team.getAlivePkm(), gen.minLvl) +end + +function team.getLowestLvl() + return getPokemonLevel(team.getLowestLvlPkm()) +end + +function team.getPkm() + local pkm = {} + for index = 1, getTeamSize() do + table.insert(pkm, index) + end + return pkm +end + +--- @summary : +--- @return : +--- @type : +function team.getPkmWithAbility(abilityName) + return team._filter(team.getPkm(), team.hasPkmAbility, abilityName) +end + +--- @summary : +--- @return : +--- @type : +function team.getPkmWithMove(moveName) + return team._filter(team.getPkm(), team.hasPkmMove, moveName) +end + +--- @summary : +--- @return : +--- @type : integer | nil +function team.getFirstPkmWithMove(moveName) + return gen.first(team.getPkmWithMove(moveName)) +end + +function team.getUsablePkmWithMove(moveName) + return team._filter(team.getUsablePkm(), team.hasPkmMove, moveName) +end + +function team.getFirstUsablePkmWithMove(moveName) + return gen.first(team.getUsablePkmWithMove(moveName)) +end + +--- @summary : +--- @return : 1-6, index of first pkm holding matching item | nil, if no team member matches +--- @type : integer | nil +function team.getPkmWithItem(itemName) + return team._filter(team.getPkm(), team.hasPkmItem, itemName) +end + + +function team.getFirstPkmWithItem(itemName) + return gen.first(team.getPkmWithItem(itemName)) +end + +function team.getLastPkmWithItem(itemName) + return gen.last(team.getPkmWithItem(itemName)) +end + +--- @summary : provides couverage for proShine's unused attacks +function team.getUsablePkm() + return team._filter(team.getPkm(), isPokemonUsable, itemName) +end + +function team.getFirstUsablePkm() + return gen.first(team.getUsablePkm()) +end + + +function team.giveLeftoversTo(leftoversTarget) + local leftovers = "Leftovers" + --correct pkm already has leftovers + log("DEBUG | hasPkmItem: "..tostring(team.hasPkmItem(leftoversTarget, leftovers))) + if team.hasPkmItem(leftoversTarget, leftovers) then return end + + --leftoversTarget not in team range + if leftoversTarget < 1 or leftoversTarget > getTeamSize() then + log("Error | wrong leftoversTarget: "..tostring(leftoversTarget)) + return + end + + --remove item, if pkm is already holding one + if getPokemonHeldItem(leftoversTarget) then takeItemFromPokemon(leftoversTarget) end + + --give leftovers if available + if hasItem(leftovers) then return giveItemToPokemon(leftovers, leftoversTarget) end + + --take leftovers if necessary | last because it allows starter to hold leftovers as well + local pkmWithLeftovers = team.getLastPkmWithItem(leftovers) + log("DEBUG | pkmWithLeftovers: "..tostring(pkmWithLeftovers)) + if pkmWithLeftovers then return takeItemFromPokemon(pkmWithLeftovers) end +end + +--actual calculations +function team._compare(t, fn) + if not t then return nil end + if #t == 0 then return nil end --, nil end + local key, value = 1, t[1] + for i = 2, #t do + if fn(value, t[i]) then + key, value = i, t[i] + end + end + return value +end + +function team._filter(t, fn, ...) + local newtbl = {} + for key, value in pairs(t) do + if fn(key, ...) then + table.insert(newtbl, value) + end + end + if #newtbl > 0 then return newtbl end +end + +function team.getPkmWithId(pkmId) + return team._filter(team.getPkm(), gen.equal, getPokemonId, pkmId) +end + +function team.getFirstPkmWithId(pkmId) + log("-------------------------") + log("gen: " .. tostring(gen)) + log("gen.first: " .. tostring(gen.first)) + local res = gen.first(team.getPkmWithId(pkmId)) + log("-------------------------") + return res +end + +--function team.getPkmWithName(pkmName) +-- return team._filter(team.getPkm(), getPokemonName) +--end +-- +--function team.getFirstPkmWithName(pkmName) +-- return gen.first(team.getPkmWithName(pkmName)) +--end + +---@summary +---@comment: added for questing +function team.getPkmIds() + return team._transform(team.getPkm(), getPokemonId) +end + +function team._transform(t, fn) + local transTbl = {} + for key, value in pairs(t) do + --key param: unnecessary, if key is integer | necessary, for every other tpye + --sys.debug(key .." | "..value .." |" .. fn(value)) --not possible with reltive pathing + table.insert(transTbl, value, fn(value)) + end + return transTbl +end + + +return team \ No newline at end of file diff --git a/Questing.lua b/Questing.lua index 513becf..03ca732 100644 --- a/Questing.lua +++ b/Questing.lua @@ -5,10 +5,9 @@ name = "Questing" author = "g0ld, wiwi33, m1l4" -description = [[Mainquesting up to sinnoh region.]] +description = [[MainQuesting until end of Hoenn region.]] dofile "config.lua" -debug = false local QuestManager local questManager = nil @@ -16,7 +15,17 @@ local questManager = nil function onStart() math.randomseed(os.time()) QuestManager = require "Quests/QuestManager" + log("all fine") questManager = QuestManager:new() + + --for longer botting runs + if DISABLE_PM and isPrivateMessageEnabled() then + log("Private messages disabled.") + return disablePrivateMessage() + end + + --disable AutoEvolve for reduced exp needed to lvl up + disableAutoEvolve() end function onPause() diff --git a/Quests/Johto/Elite4Johto.lua b/Quests/Johto/Elite4Johto.lua index 7b5491f..5dbfab7 100644 --- a/Quests/Johto/Elite4Johto.lua +++ b/Quests/Johto/Elite4Johto.lua @@ -74,7 +74,7 @@ function Elite4Johto:BlackthornCityGym() end function Elite4Johto:BlackthornCity() - if game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Blackthorn City" then + if game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Blackthorn City" then return moveToMap("Pokecenter Blackthorn") else return moveToMap("Route 45") @@ -194,7 +194,7 @@ function Elite4Johto:CinnabarIsland() return moveToMap("Route 21") elseif hasPokemonInTeam("Rattata") then return moveToMap("Route 20") - elseif self:needPokecenter() or not self.registeredPokecenter == "Pokecenter Cinnabar Island" + elseif self:needPokecenter() or self.registeredPokecenter ~= "Pokecenter Cinnabar Island" or (self.forceCaught and not hasPokemonInTeam("Rattata")) then return moveToMap("Pokecenter Cinnabar") elseif self:needPokemart() and not (getItemQuantity("Great Ball") > 9)then diff --git a/Quests/Johto/FogBadgeQuest.lua b/Quests/Johto/FogBadgeQuest.lua index ffd9340..cfd7ee8 100644 --- a/Quests/Johto/FogBadgeQuest.lua +++ b/Quests/Johto/FogBadgeQuest.lua @@ -49,7 +49,7 @@ function FogBadgeQuest:GoldenrodCityGym() end function FogBadgeQuest:GoldenrodCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Goldenrod" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Goldenrod" then return moveToMap("Pokecenter Goldenrod") elseif not hasItem("SquirtBottle") then moveToMap("Goldenrod City Flower Shop") @@ -117,7 +117,7 @@ function FogBadgeQuest:Route36() end function FogBadgeQuest:Route37() - if self:needPokecenter() or not self.registeredPokecenter == "Pokecenter Ecruteak" then + if self:needPokecenter() or self.registeredPokecenter ~= "Pokecenter Ecruteak" then moveToMap("Ecruteak City") elseif not self:isTrainingOver() then moveToGrass() @@ -125,7 +125,7 @@ function FogBadgeQuest:Route37() end function FogBadgeQuest:EcruteakCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Ecruteak" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Ecruteak" then return moveToMap("Pokecenter Ecruteak") elseif not self:isTrainingOver() then log("dd") diff --git a/Quests/Johto/GlacierBadgeQuest.lua b/Quests/Johto/GlacierBadgeQuest.lua index 724e047..889490e 100644 --- a/Quests/Johto/GlacierBadgeQuest.lua +++ b/Quests/Johto/GlacierBadgeQuest.lua @@ -60,7 +60,7 @@ function GlacierBadgeQuest:OlivineCityGym() end function GlacierBadgeQuest:OlivineCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Olivine City" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Olivine City" then moveToMap("Olivine Pokecenter") else moveToMap("Route 39") end @@ -113,7 +113,7 @@ function GlacierBadgeQuest:MtMortarLowerCave() end function GlacierBadgeQuest:MahoganyTown() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Mahogany Town" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Mahogany Town" then moveToMap("Pokecenter Mahogany") elseif not isNpcOnCell(11,24) then moveToMap("Mahogany Town Gym") diff --git a/Quests/Johto/GoldenrodCityQuest.lua b/Quests/Johto/GoldenrodCityQuest.lua index d4b0661..9d1e2c5 100644 --- a/Quests/Johto/GoldenrodCityQuest.lua +++ b/Quests/Johto/GoldenrodCityQuest.lua @@ -16,34 +16,34 @@ local description = " Complete Guard's Quest" local level = 22 local dialogs = { - martElevatorFloorB1F = Dialog:new({ + martElevatorFloorB1F = Dialog:new({ "on the underground" }), - martElevatorFloor1 = Dialog:new({ + martElevatorFloor1 = Dialog:new({ "the first floor" }), - martElevatorFloor2 = Dialog:new({ + martElevatorFloor2 = Dialog:new({ "the second floor" }), - martElevatorFloor3 = Dialog:new({ + martElevatorFloor3 = Dialog:new({ "the third floor" }), - martElevatorFloor4 = Dialog:new({ + martElevatorFloor4 = Dialog:new({ "the fourth floor" }), - martElevatorFloor5 = Dialog:new({ + martElevatorFloor5 = Dialog:new({ "the fifth floor" }), - martElevatorFloor6 = Dialog:new({ + martElevatorFloor6 = Dialog:new({ "the sixth floor" }), - directorQuestPart1 = Dialog:new({ + directorQuestPart1 = Dialog:new({ "there is nothing to see here" }), - guardQuestPart1 = Dialog:new({ + guardQuestPart1 = Dialog:new({ "any information on his whereabouts" }), - guardQuestPart2 = Dialog:new({ + guardQuestPart2 = Dialog:new({ "where did you find him", "he might be able to help" }) @@ -67,7 +67,7 @@ end function GoldenrodCityQuest:isDoable() if self:hasMap() then - if getMapName() == "Goldenrod City" then + if getMapName() == "Goldenrod City" then return isNpcOnCell(48,34) else return true @@ -81,7 +81,7 @@ function GoldenrodCityQuest:isDone() return true end return false - + end function GoldenrodCityQuest:pokemart_() @@ -96,7 +96,7 @@ function GoldenrodCityQuest:pokemart_() if maximumBuyablePokeballs < pokeballToBuy then pokeballToBuy = maximumBuyablePokeballs end - return buyItem("Pokeball", pokeballToBuy) + return buyItem("Pokeball", pokeballToBuy) end else return moveToMap("Goldenrod Mart 1") @@ -107,15 +107,15 @@ function GoldenrodCityQuest:PokecenterGoldenrod() if self.need_oddish and (not hasPokemonInTeam("Oddish") and not hasPokemonInTeam("Gloom")) then log("Oddish with Johto Region NOT FOUND, Next quest: llexForestQuest.lua") return moveToMap("Goldenrod City") - --Get Oddish From PC + --Get Oddish From PC elseif hasItem("Basement Key") and not hasItem("SquirtBottle") and dialogs.guardQuestPart2.state then if not hasPokemonInTeam("Oddish") and not hasPokemonInTeam("Gloom")then if isPCOpen() then if isCurrentPCBoxRefreshed() then if getCurrentPCBoxSize() ~= 0 then for pokemon=1, getCurrentPCBoxSize() do - if getPokemonNameFromPC(getCurrentPCBoxId(),pokemon) == "Oddish" and getPokemonRegionFromPC(getCurrentPCBoxId(),pokemon) == "Johto" then - if not game.hasPokemonWithName("Gastly") == false then + if getPokemonNameFromPC(getCurrentPCBoxId(),pokemon) == "Oddish" and getPokemonRegionFromPC(getCurrentPCBoxId(),pokemon) == "Johto" then + if not game.hasPokemonWithName("Gastly") == false then log("LOG: Oddish Found on BOX: " .. getCurrentPCBoxId() .." Slot: ".. pokemon .. " Swapping with Gastly on Slot: " .. game.hasPokemonWithName("Gastly")) return swapPokemonFromPC(getCurrentPCBoxId(),pokemon,game.hasPokemonWithName("Gastly")) --swap with gastly useless against Gavin Director else @@ -135,18 +135,18 @@ function GoldenrodCityQuest:PokecenterGoldenrod() else return usePC() end - --END get Oddish or Bellsprout + --END get Oddish or Bellsprout else -- have Oddish self:pokecenter("Goldenrod City") end else self:pokecenter("Goldenrod City") - end + end end function GoldenrodCityQuest:GoldenrodCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Goldenrod" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Goldenrod" then return moveToMap("Pokecenter Goldenrod") elseif self:needPokemart() then return moveToMap("Goldenrod Mart 1") @@ -160,7 +160,7 @@ function GoldenrodCityQuest:GoldenrodCity() return talkToNpcOnCell(50,34) elseif hasItem("Basement Key") and not hasItem("SquirtBottle") and dialogs.guardQuestPart2.state then --get Oddish on PC and start leveling if not game.hasPokemonWithMove("Sleep Powder") then - if hasPokemonInTeam("Oddish") then + if hasPokemonInTeam("Oddish") then return moveToMap("Route 34") else return moveToMap("Pokecenter Goldenrod") @@ -171,7 +171,7 @@ function GoldenrodCityQuest:GoldenrodCity() elseif isNpcOnCell(48,34) then if dialogs.guardQuestPart2.state then if hasItem("Basement Key") then - + else return moveToMap("Goldenrod City House 2") end @@ -200,7 +200,7 @@ function GoldenrodCityQuest:GoldenrodUndergroundEntranceTop() else return moveToMap("Goldenrod Underground Path") end - + end function GoldenrodCityQuest:GoldenrodUndergroundPath() @@ -228,7 +228,7 @@ function GoldenrodCityQuest:GoldenrodCityHouse2() end function GoldenrodCityQuest:Route34() - if self:needPokecenter() or not self.registeredPokecenter == "Pokecenter Goldenrod" then + if self:needPokecenter() or self.registeredPokecenter ~= "Pokecenter Goldenrod" then return moveToMap("Goldenrod City") elseif self.need_oddish and (not hasPokemonInTeam("Oddish") and not hasPokemonInTeam("Gloom"))then return moveToMap("Route 34 Stop House") @@ -254,7 +254,7 @@ function GoldenrodCityQuest:Route34() end function GoldenrodCityQuest:Route34StopHouse() - if self:needPokecenter() or not self.registeredPokecenter == "Pokecenter Goldenrod" then + if self:needPokecenter() or self.registeredPokecenter ~= "Pokecenter Goldenrod" then return moveToMap("Route 34") elseif self.need_oddish and (not hasPokemonInTeam("Oddish") and not hasPokemonInTeam("Gloom"))then self.need_oddish = false @@ -266,7 +266,7 @@ end function GoldenrodCityQuest:GoldenrodMartElevator() if not hasItem("Fresh Water") then - if not dialogs.martElevatorFloor6.state then + if not dialogs.martElevatorFloor6.state then pushDialogAnswer(5) pushDialogAnswer(3) return talkToNpcOnCell(1,6) @@ -275,7 +275,7 @@ function GoldenrodCityQuest:GoldenrodMartElevator() return moveToCell(3,6) end elseif hasItem("Basement Key") and not hasItem("SquirtBottle") and game.hasPokemonWithMove("Sleep Powder") and dialogs.guardQuestPart2.state then - if not dialogs.martElevatorFloorB1F.state then + if not dialogs.martElevatorFloorB1F.state then pushDialogAnswer(1) return talkToNpcOnCell(1,6) else @@ -334,11 +334,11 @@ function GoldenrodCityQuest:GoldenrodMartB1F() if isNpcOnCell(13,8) then pushDialogAnswer(2) if game.hasPokemonWithName("Oddish") then - pushDialogAnswer(game.hasPokemonWithName("Oddish")) + pushDialogAnswer(game.hasPokemonWithName("Oddish")) elseif game.hasPokemonWithName("Gloom") then - pushDialogAnswer(game.hasPokemonWithName("Gloom")) + pushDialogAnswer(game.hasPokemonWithName("Gloom")) else - fatal("Error . - No Oddish or Gloom in this team") + fatal("Error . - No Oddish or Gloom in this team") end return talkToNpcOnCell(13,8) else @@ -347,7 +347,7 @@ function GoldenrodCityQuest:GoldenrodMartB1F() else return moveToMap("Goldenrod Mart Elevator") end - + end function GoldenrodCityQuest:UndergroundWarehouse() @@ -393,7 +393,7 @@ function GoldenrodCityQuest:UndergroundWarehouse() else return moveToCell(24,22) end - elseif not self.checkCrate6 then --Snubbull Crate + elseif not self.checkCrate6 then --Snubbull Crate if getPlayerX() == 13 and getPlayerY() == 24 then talkToNpcOnCell(12,24) self.checkCrate6 = true @@ -410,7 +410,7 @@ function GoldenrodCityQuest:UndergroundWarehouse() return moveToCell(5,8) end elseif isNpcOnCell(3,16) then --Item: Antidote - return talkToNpcOnCell(3,16) + return talkToNpcOnCell(3,16) else self.checkCrate1 = false self.checkCrate2 = false @@ -434,7 +434,7 @@ function GoldenrodCityQuest:GoldenrodUndergroundBasement() return talkToNpcOnCell(17,13) else return moveToMap("Goldenrod Underground Path") - end + end elseif isNpcOnCell(18,12) and isNpcOnCell(22,16) and isNpcOnCell(18,18) and isNpcOnCell(13,16) and isNpcOnCell(9,12) and isNpcOnCell(9,18) and isNpcOnCell(4,16) and isNpcOnCell(4,10) then --Lever A return talkToNpcOnCell(26,13) elseif not isNpcOnCell(18,12) and isNpcOnCell(22,16) and isNpcOnCell(18,18) and isNpcOnCell(13,16) and isNpcOnCell(9,12) and not isNpcOnCell(9,18) and isNpcOnCell(4,16) and isNpcOnCell(4,10) then --Lever C @@ -462,26 +462,26 @@ function GoldenrodCityQuest:GoldenrodUndergroundBasement() end end elseif not isNpcOnCell(18,12) and not isNpcOnCell(22,16) and isNpcOnCell(18,18) and not isNpcOnCell(13,16) and isNpcOnCell(9,12) and not isNpcOnCell(9,18) and not isNpcOnCell(4,16) and not isNpcOnCell(4,10) then --Lever C - if isNpcOnCell(5,4) then --Galvin Director - return talkToNpcOnCell(5,4) - else - fatal("Error GoldenrodCityQuest:GoldenrodUndergroundBasement()") - end + if isNpcOnCell(5,4) then --Galvin Director + return talkToNpcOnCell(5,4) + else + fatal("Error GoldenrodCityQuest:GoldenrodUndergroundBasement()") + end else - fatal("Error ON PUZZLE RESOLUTION GoldenrodCityQuest:GoldenrodUndergroundBasement()") + fatal("Error ON PUZZLE RESOLUTION GoldenrodCityQuest:GoldenrodUndergroundBasement()") end end function GoldenrodCityQuest:MapName() - + end function GoldenrodCityQuest:MapName() - + end function GoldenrodCityQuest:MapName() - + end return GoldenrodCityQuest diff --git a/Quests/Johto/HiveBadgeQuest.lua b/Quests/Johto/HiveBadgeQuest.lua index 743ea14..80d673c 100644 --- a/Quests/Johto/HiveBadgeQuest.lua +++ b/Quests/Johto/HiveBadgeQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -40,7 +40,7 @@ function HiveBadgeQuest:AzaleaPokemart() end function HiveBadgeQuest:AzaleaTown() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Azalea" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Azalea" then return moveToMap("Pokecenter Azalea") elseif self:needPokemart() then return moveToMap("Azalea Pokemart") @@ -58,7 +58,7 @@ function HiveBadgeQuest:AzaleaTown() end function HiveBadgeQuest:Route33() - if self:needPokecenter() or self:needPokemart() or not self.registeredPokecenter == "Pokecenter Azalea" then + if self:needPokecenter() or self:needPokemart() or self.registeredPokecenter ~= "Pokecenter Azalea" then return moveToMap("Azalea Town") elseif not self:isTrainingOver() then return moveToGrass() diff --git a/Quests/Johto/MineralBadgeQuest.lua b/Quests/Johto/MineralBadgeQuest.lua index a4a3d92..a368882 100644 --- a/Quests/Johto/MineralBadgeQuest.lua +++ b/Quests/Johto/MineralBadgeQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -45,7 +45,7 @@ function MineralBadgeQuest:isDone() end function MineralBadgeQuest:CianwoodCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Cianwood" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Cianwood" then moveToMap("Pokecenter Cianwood") elseif not dialogs.potion.state then moveToMap("Cianwood Shop") @@ -69,7 +69,10 @@ function MineralBadgeQuest:Route40() end function MineralBadgeQuest:OlivineCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Olivine City" then + if BUY_RODS and hasItem("Good Rod") and not hasItem("Super Rod") and getMoney() >= 75000 then + --go to fising guru's map, if you have enough money and want to buy the super rod + return moveToMap("Olivine House 1") + elseif self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Olivine City" then moveToMap("Olivine Pokecenter") elseif not dialogs.phare.state then moveToMap("Glitter Lighthouse 1F") @@ -79,6 +82,13 @@ function MineralBadgeQuest:OlivineCity() end end +function MineralBadgeQuest:OlivineHouse1() + --talk to the even better fishing guru + if hasItem("Good Rod") and not hasItem("Super Rod") then return talkToNpcOnCell(0, 10) + --leave when rod obtained + else return moveToMap("Olivine City") end +end + function MineralBadgeQuest:GlitterLighthouse1F() if dialogs.phare.state then moveToCell(8,14) diff --git a/Quests/Johto/PlainBadgeQuest.lua b/Quests/Johto/PlainBadgeQuest.lua index 24b365f..090a084 100644 --- a/Quests/Johto/PlainBadgeQuest.lua +++ b/Quests/Johto/PlainBadgeQuest.lua @@ -40,7 +40,7 @@ function PlainBadgeQuest:PokecenterGoldenrod() end function PlainBadgeQuest:GoldenrodCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Goldenrod" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Goldenrod" then return moveToMap("Pokecenter Goldenrod") elseif not self:isTrainingOver() then return moveToMap("Route 34") diff --git a/Quests/Johto/RisingBadgeQuest.lua b/Quests/Johto/RisingBadgeQuest.lua index 725fa80..f037bca 100644 --- a/Quests/Johto/RisingBadgeQuest.lua +++ b/Quests/Johto/RisingBadgeQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -60,7 +60,7 @@ end function RisingBadgeQuest:MahoganyTown() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Mahogany Town" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Mahogany Town" then moveToMap("Pokecenter Mahogany") else moveToMap("Route 44") end @@ -98,7 +98,7 @@ function RisingBadgeQuest:IcePathB3F() end function RisingBadgeQuest:BlackthornCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Blackthorn City" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Blackthorn City" then moveToMap("Pokecenter Blackthorn" ) elseif not self:isTrainingOver() then moveToMap("Dragons Den Entrance") diff --git a/Quests/Johto/StartJohtoQuest.lua b/Quests/Johto/StartJohtoQuest.lua index 241f379..af47fd0 100644 --- a/Quests/Johto/StartJohtoQuest.lua +++ b/Quests/Johto/StartJohtoQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -18,7 +18,6 @@ local StartJohtoQuest = Quest:new() function StartJohtoQuest:new() local o = Quest.new(StartJohtoQuest, name, description, level) - o.BUY_BIKE = true return o end @@ -68,7 +67,7 @@ end function StartJohtoQuest:CherrygroveCity() if isNpcOnCell(52,7) then return talkToNpcOnCell(52,7) --Get 5 Pokeballs + 5 Potions + 10000 Money - elseif self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Cherrygrove City" then + elseif self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Cherrygrove City" then return moveToMap("Pokecenter Cherrygrove City") elseif self:needPokemart() then return moveToMap("Mart Cherrygrove City") @@ -105,7 +104,7 @@ function StartJohtoQuest:pokemart_() end function StartJohtoQuest:Route30() - if self:needPokecenter() or not self.registeredPokecenter == "Pokecenter Cherrygrove City" or (getTeamSize() > 1 and getUsablePokemonCount() == 1) or getUsablePokemonCount() == 0 then + if self:needPokecenter() or self.registeredPokecenter ~= "Pokecenter Cherrygrove City" or (getTeamSize() > 1 and getUsablePokemonCount() == 1) or getUsablePokemonCount() == 0 then return moveToCell(8,96) --Cherrygrove City elseif getTeamSize() <= 2 or not self:isTrainingOver() then --Get some pokemons for fill the team return moveToGrass() @@ -113,21 +112,11 @@ function StartJohtoQuest:Route30() return talkToNpcOnCell(15,67) elseif isNpcOnCell(20,3) then --Item: Pecha Berry return talkToNpcOnCell(20,3) - elseif self.BUY_BIKE and getMoney() > 75000 and not hasItem("Bicycle") and not hasItem("Bike Voucher") then - return moveToMap("Route 30 House 2") elseif game.tryTeachMove("Cut","HM01 - Cut") == true then return moveToMap("Route 31") end end -function StartJohtoQuest:Route30House2() - if self.BUY_BIKE and getMoney() > 75000 and not hasItem("Bicycle") and not hasItem("Bike Voucher") then - return talkToNpcOnCell(2,6) - else - return moveToMap("Route 30") - end -end - function StartJohtoQuest:Route31() if isNpcOnCell(25,15) then --Item: Persim Berry return talkToNpcOnCell(25,15) diff --git a/Quests/Johto/StormBadgeQuest.lua b/Quests/Johto/StormBadgeQuest.lua index e44d2ce..b7ffca8 100644 --- a/Quests/Johto/StormBadgeQuest.lua +++ b/Quests/Johto/StormBadgeQuest.lua @@ -50,7 +50,7 @@ function StormBadgeQuest:EcruteakGym() end function StormBadgeQuest:EcruteakCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Ecruteak" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Ecruteak" then moveToMap("Pokecenter Ecruteak") else moveToMap("Ecruteak Stop House 1") end @@ -83,7 +83,7 @@ function StormBadgeQuest:Route39() end function StormBadgeQuest:OlivineCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Olivine" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Olivine" then moveToMap("Olivine Pokecenter") elseif not dialogs.phare.state then moveToMap("Glitter Lighthouse 1F") diff --git a/Quests/Johto/ZephyrBadgeQuest.lua b/Quests/Johto/ZephyrBadgeQuest.lua index a13773d..2c8fe1b 100644 --- a/Quests/Johto/ZephyrBadgeQuest.lua +++ b/Quests/Johto/ZephyrBadgeQuest.lua @@ -52,49 +52,53 @@ function ZephyrBadgeQuest:VioletCityPokemart() end function ZephyrBadgeQuest:VioletCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Violet City" then + if self:needPokecenter() + or not game.isTeamFullyHealed() + or self.registeredPokecenter ~= "Pokecenter Violet City" + then return moveToMap("Pokecenter Violet City") elseif self:needPokemart() then return moveToMap("Violet City Pokemart") - elseif not self:isTrainingOver() or getTeamSize() <= minTeamSize then + elseif not self:isTeamReady() then return moveToMap("Route 32") elseif isNpcOnCell(27,44) then return moveToMap("Sprout Tower F1") elseif not hasItem("Zephyr Badge") then return moveToMap("Violet City Gym Entrance") - else - return moveToMap("Route 32") end + + return moveToMap("Route 32") +end + +function ZephyrBadgeQuest:isTeamReady() + return self:isTrainingOver() + and getTeamSize() >= minTeamSize end function ZephyrBadgeQuest:Route32() - if self:needPokecenter() or self:needPokemart() or not self.registeredPokecenter == "Pokecenter Violet City" then - return moveToMap("Violet City") - elseif not self:isTrainingOver() or getTeamSize() < minTeamSize then - return moveToGrass() + if not hasItem("Zephyr Badge") then + if self:needPokecenter() + or self:needPokemart() + or self.registeredPokecenter ~= "Pokecenter Violet City" + or self:isTeamReady() + then return moveToMap("Violet City") end + elseif hasItem("Zephyr Badge") then - if isNpcOnCell(26,23) then - return talkToNpcOnCell(26,23) - else - if isNpcOnCell(25,8) then - return talkToNpcOnCell(25,8) --Item: Chesto Berry - elseif isNpcOnCell(26,8) then - return talkToNpcOnCell(26,8) --Item: Oran Berry - elseif isNpcOnCell(20,119) then - return talkToNpcOnCell(20,119) --Item: Oran Berry - elseif isNpcOnCell(20,120) then - return talkToNpcOnCell(20,120) --Item: Lummy Berry - elseif isNpcOnCell(20,121) then - return talkToNpcOnCell(20,121) --Item: Leppa Berry - elseif self:needPokecenter() or not self.registeredPokecenter == "Pokecenter Route 32" then - return moveToMap("Pokecenter Route 32") - else - return moveToMap("Union Cave 1F") - end - end - else - return moveToMap("Violet City") + if isNpcOnCell(26,23) then return talkToNpcOnCell(26,23) + elseif isNpcOnCell(25,8) then return talkToNpcOnCell(25,8) --Item: Chesto Berry + elseif isNpcOnCell(26,8) then return talkToNpcOnCell(26,8) --Item: Oran Berry + elseif isNpcOnCell(20,119) then return talkToNpcOnCell(20,119) --Item: Oran Berry + elseif isNpcOnCell(20,120) then return talkToNpcOnCell(20,120) --Item: Lummy Berry + elseif isNpcOnCell(20,121) then return talkToNpcOnCell(20,121) --Item: Leppa Berry + elseif self:needPokecenter() + or self.registeredPokecenter ~= "Pokecenter Route 32" + then + return moveToMap("Pokecenter Route 32") + + else return moveToMap("Union Cave 1F") end end + + return moveToGrass() end function ZephyrBadgeQuest:VioletCityGymEntrance() diff --git a/Quests/Kanto/BoulderBadgeQuest.lua b/Quests/Kanto/BoulderBadgeQuest.lua index 27a1d88..a728d35 100644 --- a/Quests/Kanto/BoulderBadgeQuest.lua +++ b/Quests/Kanto/BoulderBadgeQuest.lua @@ -76,7 +76,8 @@ function BoulderBadgeQuest:PewterCity() elseif self:needPokemart() then return moveToMap("Pewter Pokemart") elseif hasItem("Boulder Badge") then - return moveToMap("Route 3") + --so they even changed the Jail map to "Link" as well, those bastards xDs + return moveToCell(65,34) elseif self.registeredPokecenter ~= "Pokecenter Pewter" or not game.isTeamFullyHealed() then diff --git a/Quests/Kanto/CascadeBadgeQuest.lua b/Quests/Kanto/CascadeBadgeQuest.lua index 7ba2113..af1fd5c 100644 --- a/Quests/Kanto/CascadeBadgeQuest.lua +++ b/Quests/Kanto/CascadeBadgeQuest.lua @@ -55,17 +55,23 @@ function CascadeBadgeQuest:CeruleanCity() elseif not self:isTrainingOver() or not dialogs.billTicketDone.state then - return moveToCell(39,0)-- Route 24 Bridge - else - if not hasItem("Cascade Badge") then + -- Route 24 Bridge + return moveToCell(39,0) + + elseif not hasItem("Cascade Badge") then return moveToMap("Cerulean Gym") - else -- Gym complete --> Get Ticket Bill - if isNpcOnCell(47, 27) then -- RocketGuy --> 2ND - return talkToNpcOnCell(47, 27) - else -- all done Ticket + Badge (Go to Route 5) - return moveToCell(23,50) -- Route 5 - end - end + + elseif isNpcOnCell(43,23) then + --talk to the newly added police officer + return talkToNpcOnCell(43,23) + + elseif isNpcOnCell(47, 27) then + -- RocketGuy --> 2ND + return talkToNpcOnCell(47, 27) + + else + -- all done Ticket + Badge (Go to Route 5) + return moveToCell(23,50) -- Route 5 end end @@ -160,4 +166,4 @@ function CascadeBadgeQuest:CeruleanGym() -- get Cascade Badge end end -return CascadeBadgeQuest +return CascadeBadgeQuest \ No newline at end of file diff --git a/Quests/Kanto/EarthBadgeQuest.lua b/Quests/Kanto/EarthBadgeQuest.lua index a3344d9..3379205 100644 --- a/Quests/Kanto/EarthBadgeQuest.lua +++ b/Quests/Kanto/EarthBadgeQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -79,7 +79,7 @@ function EarthBadgeQuest:ViridianPokemart() end function EarthBadgeQuest:ViridianCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Viridian" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Viridian" then return moveToMap("Pokecenter Viridian") elseif self:needPokemart() then return moveToMap("Viridian Pokemart") diff --git a/Quests/Kanto/ExpForSaffronQuest.lua b/Quests/Kanto/ExpForSaffronQuest.lua index 6747fb7..46aad9d 100644 --- a/Quests/Kanto/ExpForSaffronQuest.lua +++ b/Quests/Kanto/ExpForSaffronQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -12,7 +12,7 @@ local Dialog = require "Quests/Dialog" local name = 'Training for Saffron' local description = 'Exp in Seafoam' -local level = 60 +local level = 65 local ExpForSaffronQuest = Quest:new() @@ -34,12 +34,8 @@ function ExpForSaffronQuest:isDone() return false end -function ExpForSaffronQuest:canUseNurse() - return getMoney() > 1500 -end - function ExpForSaffronQuest:Route20() - if not self:isTrainingOver() then + if not self:isFinishedFarming() then return moveToCell(60,32) --Seafoam 1F else return moveToMap("Route 19") @@ -47,7 +43,7 @@ function ExpForSaffronQuest:Route20() end function ExpForSaffronQuest:Seafoam1F() - if not self:isTrainingOver() then + if not self:isFinishedFarming() then return moveToCell(20,8) --Seafom B1F else return moveToMap("Route 20") @@ -55,7 +51,7 @@ function ExpForSaffronQuest:Seafoam1F() end function ExpForSaffronQuest:SeafoamB1F() - if not self:isTrainingOver() then + if not self:isFinishedFarming() then return moveToCell(64,25) --Seafom B2F else return moveToCell(15,12) @@ -66,7 +62,7 @@ function ExpForSaffronQuest:SeafoamB2F() if isNpcOnCell(67,31) then --Item: TM13 - Ice Beam return talkToNpcOnCell(67,31) end - if not self:isTrainingOver() then + if not self:isFinishedFarming() then return moveToCell(63,19) --Seafom B3F else return moveToCell(51,27) @@ -74,34 +70,38 @@ function ExpForSaffronQuest:SeafoamB2F() end function ExpForSaffronQuest:SeafoamB3F() - if not self:isTrainingOver() then - return moveToCell(57,26) --Seafom B4F - else - return moveToCell(64,16) - end + --Still farming then: Seafom B4F + if not self:isFinishedFarming() then return moveToCell(57,26) + + --else go home + else return moveToCell(64,16) end +end + +function ExpForSaffronQuest:isFinishedFarming() + return self:isTrainingOver() --as before: training + and (not BUY_BIKE or getMoney() > 60000) --additional: money farming, when buying bike is set end function ExpForSaffronQuest:SeafoamB4F() - if isNpcOnCell(57,20) then --Item: Nugget (15000 Money) - return talkToNpcOnCell(57,20) - end - if not self:isTrainingOver() then - if self:needPokecenter() then - if self:canUseNurse() then -- if have 1500 money - return talkToNpcOnCell(59,13) - else - if not game.getTotalUsablePokemonCount() > 1 then - fatal("don't have enough Pokemons for farm 1500 money and heal the team") - else - return moveToRectangle(50,10,62,32) - end - end - else - return moveToRectangle(50,10,62,32) + --Item: Nugget (15000 Money) + if isNpcOnCell(57,20) then return talkToNpcOnCell(57,20) end + --moving to ladder, to leave level + if self:isFinishedFarming() then + return moveToCell(53,28) end + + if self:needPokecenter() then + -- use on road nurse only if you have the money + if getMoney() > 1500 then + return talkToNpcOnCell(59,13) + + --not enough money and Escape Rope (550) cheaper than feinting (5% of current money) + elseif hasItem("Escape Rope") and getMoney()*0.05 > 550 then + return useItem("Escape Rope") end - else - return moveToCell(53,28) end + + --else farm / provoke feinting + return moveToRectangle(50,10,62,32) end return ExpForSaffronQuest \ No newline at end of file diff --git a/Quests/Kanto/HmFlashQuest.lua b/Quests/Kanto/HmFlashQuest.lua index 379c991..2d5c75d 100644 --- a/Quests/Kanto/HmFlashQuest.lua +++ b/Quests/Kanto/HmFlashQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -104,7 +104,8 @@ function HmFlashQuest:CeruleanCity() if not hasItem("HM05 - Flash") then return moveToMap("Route 5") else - return moveToMap("Route 9") + --PRO did again update a bad link Name to source code :/ + return moveToMap("Link") end end diff --git a/Quests/Kanto/MarshBadgeQuest.lua b/Quests/Kanto/MarshBadgeQuest.lua index 63cd945..5343c1f 100644 --- a/Quests/Kanto/MarshBadgeQuest.lua +++ b/Quests/Kanto/MarshBadgeQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -23,6 +23,8 @@ local dialogs = { local MarshBadgeQuest = Quest:new() function MarshBadgeQuest:new() + --setting starter, if no none defined + if not KANTO_DOJO_POKEMON_ID then KANTO_DOJO_POKEMON_ID = math.random(1,2) end local o = Quest.new(MarshBadgeQuest, name, description, level, dialogs) o.dojoState = false return o @@ -36,7 +38,9 @@ function MarshBadgeQuest:isDoable() end function MarshBadgeQuest:isDone() - if (hasItem("Marsh Badge") and getMapName() == "Route 8") or getMapName() == "Silph Co 1F" or getMapName() == "Route 5" then + if hasItem("Marsh Badge") and getMapName() == "Lavender Town" + or getMapName() == "Silph Co 1F" + or getMapName() == "Route 5" then return true else return false @@ -45,34 +49,45 @@ end function MarshBadgeQuest:Route8() - if not self:needPokecenter() and not self:isTrainingOver() then - return moveToGrass() - else - return moveToMap("Route 8 Stop House") - end + if self:needPokecenter() or self:isTrainingOver() then + --if we won gym fight, self:isTrainingOver() should be true. So another test against badge has + --to be made, to fix looping between Rout8StopHouse and Route8 itself + if hasItem("Marsh Badge")then return moveToMap("Lavender Town") + + else return moveToMap("Route 8 Stop House") end + + else return moveToGrass() end end function MarshBadgeQuest:Route8StopHouse() - if hasItem("Marsh Badge") or not self:isTrainingOver() then - return moveToMap("Route 8") - else - return moveToMap("Saffron City") - end + if not hasItem("Marsh Badge") + and (self:needPokecenter() or self:isTrainingOver()) + + --updated link name + then return moveToMap("Link") end + + return moveToMap("Route 8") +end + +function MarshBadgeQuest:isBuyingBike() + sys.debug("BUY_BIKE: ", BUY_BIKE) + sys.debug("Voucer: ", hasItem("Bike Voucher")) + sys.debug("money: ", getMoney() >=60000) + return BUY_BIKE and hasItem("Bike Voucher") and getMoney() >=60000 end function MarshBadgeQuest:Route5StopHouse() - if hasItem("Bike Voucher") then - return moveToMap("Route 5") - else - return moveToMap("Saffron City") - end + --when bying a bike move towards Cerulean City + if self:isBuyingBike() then return moveToMap("Route 5") end + --coming back + return moveToMap("Link") end function MarshBadgeQuest:SaffronCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Saffron" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Saffron" then return moveToMap("Pokecenter Saffron") - elseif hasItem("Bike Voucher") then + elseif self:isBuyingBike() then return moveToMap("Route 5 Stop House") elseif not self:isTrainingOver() then return moveToMap("Route 8 Stop House") @@ -95,7 +110,7 @@ function MarshBadgeQuest:SaffronDojo() if isNpcOnCell(7,5) then if dialogs.dojoSaffronDone.state then if isNpcOnCell(3,4) and isNpcOnCell(10,4) then - if DOJO_POKEMON_ID == 1 then -- Hitmonchan + if KANTO_DOJO_POKEMON_ID == 1 then -- Hitmonchan return talkToNpcOnCell(3, 4) else -- Hitmonlee return talkToNpcOnCell(10,4) diff --git a/Quests/Kanto/MoonFossilQuest.lua b/Quests/Kanto/MoonFossilQuest.lua index 8faf957..1775914 100644 --- a/Quests/Kanto/MoonFossilQuest.lua +++ b/Quests/Kanto/MoonFossilQuest.lua @@ -21,6 +21,8 @@ local dialogs = { local MoonFossilQuest = Quest:new() function MoonFossilQuest:new() + --setting moon fossil, if no none defined + if not KANTO_FOSSIL_ID then KANTO_FOSSIL_ID = math.random(1,2) end return Quest.new(MoonFossilQuest, name, description, level, dialogs) end diff --git a/Quests/Kanto/PalletStartQuest.lua b/Quests/Kanto/PalletStartQuest.lua index 01de1ef..d0a8932 100644 --- a/Quests/Kanto/PalletStartQuest.lua +++ b/Quests/Kanto/PalletStartQuest.lua @@ -32,6 +32,8 @@ local dialogs = { local PalletStartQuest = Quest:new() function PalletStartQuest:new() + --setting moon fossil, if no none defined + if not KANTO_STARTER_ID then KANTO_STARTER_ID = math.random(1,4) end return Quest.new(PalletStartQuest, name, description, _, dialogs) end diff --git a/Quests/Kanto/PokeFluteQuest.lua b/Quests/Kanto/PokeFluteQuest.lua index ef4f100..86df527 100644 --- a/Quests/Kanto/PokeFluteQuest.lua +++ b/Quests/Kanto/PokeFluteQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -50,7 +50,7 @@ function PokeFluteQuest:PokecenterLavender() end function PokeFluteQuest:LavenderTown() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Lavender" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Lavender" then return moveToMap("Pokecenter Lavender") elseif dialogs.checkFujiHouse.state and not dialogs.checkFujiNote.state then return moveToMap("Lavender Town Volunteer House") diff --git a/Quests/Kanto/RainbowBadgeQuest.lua b/Quests/Kanto/RainbowBadgeQuest.lua index 150bdec..ba831db 100644 --- a/Quests/Kanto/RainbowBadgeQuest.lua +++ b/Quests/Kanto/RainbowBadgeQuest.lua @@ -28,6 +28,10 @@ local RainbowBadgeQuest = Quest:new() function RainbowBadgeQuest:new() local o = Quest.new(RainbowBadgeQuest, name, description, level, dialogs) o.pokemonId = 1 + + --stay on map until ditto catched, if a bike is wanted from user + o.pokemon = "Ditto" + o.forceCaught = not BUY_BIKE return o end @@ -49,7 +53,7 @@ end function RainbowBadgeQuest:CeladonCity() if isNpcOnCell(21,51) and getPlayerX() == 21 and getPlayerY() == 50 and hasItem("Rainbow Badge") then --NPC: Trainer OP return talkToNpcOnCell(21,51) - elseif self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Celadon" then + elseif self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Celadon" then return moveToMap("Pokecenter Celadon") elseif not self:isTrainingOver() and not hasItem("Rainbow Badge") then return moveToMap("Route 7") @@ -85,7 +89,7 @@ function RainbowBadgeQuest:PokecenterCeladon() end function RainbowBadgeQuest:Route7() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Celadon" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Celadon" then return moveToMap("Celadon City") elseif hasItem("Rainbow Badge") and hasItem("Lemonade") then return moveToMap("Underground House 3") @@ -101,7 +105,7 @@ function RainbowBadgeQuest:Route7() end function RainbowBadgeQuest:CeladonGym() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Celadon" or not self:isTrainingOver() then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Celadon" or not self:isTrainingOver() then return moveToMap("Celadon City") elseif not hasItem("Rainbow Badge") then talkToNpcOnCell(8,4) -- Erika diff --git a/Quests/Kanto/RockTunnelQuest.lua b/Quests/Kanto/RockTunnelQuest.lua index 39dcfa1..382f5c3 100644 --- a/Quests/Kanto/RockTunnelQuest.lua +++ b/Quests/Kanto/RockTunnelQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -41,10 +41,10 @@ end function RockTunnelQuest:Route10() if game.inRectangle(9,0,24,11) then - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Route 10" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Route 10" then return moveToMap("Pokecenter Route 10") else - return moveToMap("Rock Tunnel 1") + return moveToMap("Link") end else return moveToMap("Lavender Town") @@ -79,7 +79,7 @@ function RockTunnelQuest:RockTunnel2() end function RockTunnelQuest:LavenderTown() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Lavender" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Lavender" then return moveToMap("Pokecenter Lavender") else return moveToMap("Route 8") diff --git a/Quests/Kanto/RocketCeladonQuest.lua b/Quests/Kanto/RocketCeladonQuest.lua index 658bcb7..270b837 100644 --- a/Quests/Kanto/RocketCeladonQuest.lua +++ b/Quests/Kanto/RocketCeladonQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -80,7 +80,7 @@ function RocketCeladonQuest:isDone() end function RocketCeladonQuest:Route7() - if not self.registeredPokecenter == "Pokecenter Celadon" then + if self.registeredPokecenter ~= "Pokecenter Celadon" then return moveToMap("Celadon City") elseif not self:needPokecenter() and not self:isTrainingOver() then return moveToGrass() @@ -90,7 +90,7 @@ function RocketCeladonQuest:Route7() end function RocketCeladonQuest:CeladonCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Celadon" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Celadon" then return moveToMap("Pokecenter Celadon") elseif not self:isTrainingOver() then return moveToMap("Route 7") diff --git a/Quests/Kanto/SaffronGuardQuest.lua b/Quests/Kanto/SaffronGuardQuest.lua index 4c9e305..ce6e251 100644 --- a/Quests/Kanto/SaffronGuardQuest.lua +++ b/Quests/Kanto/SaffronGuardQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -6,6 +6,7 @@ local sys = require "Libs/syslib" +local pc = require "Libs/pclib" local game = require "Libs/gamelib" local Quest = require "Quests/Quest" local Dialog = require "Quests/Dialog" @@ -17,9 +18,7 @@ local level = 55 local SaffronGuardQuest = Quest:new() function SaffronGuardQuest:new() - local o = Quest.new(SaffronGuardQuest, name, description, level) - o.BUY_BIKE = BUY_BIKE - return o + return Quest.new(SaffronGuardQuest, name, description, level) end function SaffronGuardQuest:isDoable() @@ -87,31 +86,101 @@ function SaffronGuardQuest:VermilionPokemart() end function SaffronGuardQuest:VermilionCity() - if self.BUY_BIKE and getMoney() > 75000 and not hasItem("Bike Voucher") and not hasItem("Bicycle") then - return moveToCell(32,21) - elseif self:needPokemart() and getMoney() > 200 then + + if self:needPokemart() and getMoney() > 200 then return moveToMap("Vermilion Pokemart") - elseif not hasItem("Old Rod") then - return moveToMap("Fisherman House - Vermilion") - else - return moveToMap("Route 6") + + elseif self:isDittoSwapNeeded() or self:isReSwapNeeded() then + return moveToMap("Pokecenter Vermilion") + + --has ditto, get Bike Voucher + elseif self:isVoucherNeeded() then + return moveToCell(32,21) end + + --all done - move to next quest location + return moveToMap("Route 6") end -function SaffronGuardQuest:VermilionHouse2Bottom() - if self.BUY_BIKE and getMoney() > 75000 and not hasItem("Bike Voucher") and not hasItem("Bicycle")then - return talkToNpcOnCell(8,6) - else - return moveToMap("Vermilion City") - end +function SaffronGuardQuest:isVoucherNeeded() + return not hasItem("Bike Voucher") + and hasPokemonInTeam("Ditto") + and not hasItem("Bicycle") + and BUY_BIKE end -function SaffronGuardQuest:FishermanHouseVermilion() - if not hasItem("Old Rod") then - return talkToNpcOnCell(0,6) - else - return moveToMap("Vermilion City") - end + +function SaffronGuardQuest:isDittoSwapNeeded() + return not hasItem("Bike Voucher") + and not hasPokemonInTeam("Ditto") + and not hasItem("Bicycle") + and BUY_BIKE +end + +function SaffronGuardQuest:isReSwapNeeded() + return swapBoxId and swapSlotId -- parameters for swap are set + and hasItem("Bike Voucher") -- and preQuest "Voucher" is done +end + +function SaffronGuardQuest:PokecenterVermilion() + if self:isDittoSwapNeeded() then + sys.debug("entered regardless", "yes") + + local isDittoSwaped = getTeamSize() >= 6 + + local dittoId = {132 } + local result, pkmBoxId, slotId, swapTeamId = pc.retrieveFirstFromIds(dittoId) + + --working | then return because of open proShine functions to be resolved + -- | if not returned, a "can only execute one function per frame" might occur + if result == pc.result.WORKING then return sys.info("Searching PC") + + --no solution, terminate bot + elseif result == pc.result.NO_RESULT then + -- quick fix until pathfinder is added, then moving to route 8 wouldn't + -- such a hassle to implement + BUY_BIKE = false + return sys.log("No ditto caught, you skipped a quest. You missed out on a fancy new bike :(") + end + + --solution found and already added to team + + --if team was full set values, needed to return swap target + if isDittoSwaped then + swapBoxId = pkmBoxId + swapSlotId = slotId + end + + local pkm = result + local msg = "Found "..pkm.name.." on BOX: " .. pkmBoxId .. " Slot: " .. slotId + if swapTeamId then msg = msg .. " | Swapping with pokemon in team N: " .. swapTeamId + else msg = msg .. " | Added to team." end + return sys.log(msg) + + --getting the pokemon, we needed to put down because of ditto + elseif self:isReSwapNeeded() then + --start pc + if not isPCOpen() then return usePC() end + --refresing + if not isCurrentPCBoxRefreshed() then return sys.debug("refreshed") end + -- open correct box for transfer + if swapBoxId ~= getCurrentPCBoxId() then return openPCBox(swapBoxId) end + + --get the pokemon we put down to retrieve + withdrawPokemonFromPC(swapBoxId, swapSlotId) + swapBoxId, swapSlotId = nil, nil --reset after swap + return + + --do basic pokecenter related stuff... + else self:pokecenter("Vermilion City") end +end + +function SaffronGuardQuest:VermilionHouse2Bottom() + --retrieve bike voucher + if self:isVoucherNeeded() then return talkToNpcOnCell(6,6) + + --leave house otherwise when done + else return moveToMap("Vermilion City") end end function SaffronGuardQuest:Route6() @@ -129,7 +198,7 @@ function SaffronGuardQuest:Route6() end function SaffronGuardQuest:Route6StopHouse() - return moveToMap("Saffron City") + return moveToMap("Link") end return SaffronGuardQuest \ No newline at end of file diff --git a/Quests/Kanto/SoulBadgeQuest.lua b/Quests/Kanto/SoulBadgeQuest.lua index a570c94..3238ead 100644 --- a/Quests/Kanto/SoulBadgeQuest.lua +++ b/Quests/Kanto/SoulBadgeQuest.lua @@ -1,18 +1,23 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. -- Quest: @Rympex -local sys = require "Libs/syslib" -local game = require "Libs/gamelib" -local Quest = require "Quests/Quest" -local Dialog = require "Quests/Dialog" +local sys = require "Libs/syslib" +local game = require "Libs/gamelib" +local pc = require "Libs/pclib" +local team = require "Libs/teamlib" +local SurfTarget = require "Data/surfTargets" +local Quest = require "Quests/Quest" +local Dialog = require "Quests/Dialog" +local Set = require("Classes/Set") -local name = 'Sould Badge' -local description = 'Fuchsia City' -local level = 40 + +local name = 'Soul Badge' +local description = 'Fuchsia City' +local level = 40 local dialogs = { questSurfAccept = Dialog:new({ @@ -30,9 +35,12 @@ function SoulBadgeQuest:new() return o end -function SoulBadgeQuest:isDoable() - if self:hasMap() and not hasItem("Marsh Badge") then - if getMapName() == "Route 15" then +function SoulBadgeQuest:isDoable() + if not hasItem("Marsh Badge") + and self:hasMap() then + + + if getMapName() == "Route 15" then if hasItem("Soul Badge") and hasItem("HM03 - Surf") then return false else @@ -112,41 +120,107 @@ function SoulBadgeQuest:randomZoneExp() end function SoulBadgeQuest:PokecenterFuchsia() - self:pokecenter("Fuchsia City") + + local surferIds = SurfTarget.getIds() + local teamIds = team.getPkmIds() + local matches = Set.intersection(teamIds, surferIds) + + --1. check for snorlax + --2. check for surfer + if (not team.getFirstPkmWithMove("surf") and not matches) + or not snorlaxTested + then + -- --trying to add snorlax - id(38): + -- -- -1- strong pkm - high hp, high atk + -- -- -2- hopefully caught during progress: the road blocking one + -- -- -3- could be used as surfer + -- -- -4- apparently very good to beat hannah, to get access to sinnoh + if not snorlaxTested then surferIds = {38} end + + local result, pkmBoxId, slotId, swapTeamId = + pc.retrieveFirstFromIds(surferIds) + + --working | then return because of open proShine functions to be resolved + -- | if not returned, a "can only execute one function per frame" might occur + if result == pc.result.WORKING then return sys.info("Searching PC") + + --no solution, terminate bot + elseif result == pc.result.NO_RESULT then + --if we only tested for snorlax, we have still to test for surfers + if not snorlaxTested then snorlaxTested = true return end + + --no surfers + return sys.error("No pokemon in your team or on your computer has the ability to surf. Can't progress Quest") + end + + --solution found and added + local pkm = result + local msg = "Found Surfer "..pkm.name.." on BOX: " .. pkmBoxId .. " Slot: " .. slotId + if swapTeamId then msg = msg .. " | Swapping with pokemon in team N: " .. swapTeamId + else msg = msg .. " | Added to team." end + sys.log(msg) + + --do basic pokecenter related stuff... + else self:pokecenter("Fuchsia City") end end function SoulBadgeQuest:Route18() - if not self:canEnterSafari() then + if self:canEnterSafari() or self:needPokecenter() then return moveToMap("Fuchsia City") - else - return moveToGrass() - end + + else return moveToGrass() end end function SoulBadgeQuest:FuchsiaCity() - if game.minTeamLevel() >= 60 then + sys.debug("SoulBadgeQuest.fuchsiaCity() states:", true) + if team.getLowestLvl() >= 60 then + sys.debug("minTeamLevel >= 60, goingt to Route15 Stop House, its need is unknown atm") return moveToMap("Route 15 Stop House") - elseif self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Fuchsia" then + + elseif self:needPokecenter() or + not game.isTeamFullyHealed() or + self.registeredPokecenter ~= "Pokecenter Fuchsia" + then + sys.debug("heading to Pokecenter") return moveToMap("Pokecenter Fuchsia") + elseif isNpcOnCell(13,7) then --Item: PP UP + sys.debug("getting Item: PP UP") return talkToNpcOnCell(13,7) + elseif isNpcOnCell(12,10) then --Item: Ultra Ball + sys.debug("getting Item: Ultra Ball") return talkToNpcOnCell(12,10) - elseif self:needPokemart_() and not hasItem("HM03 - Surf") then --It buy balls if not have badge, at blackoutleveling no + + elseif self:needPokemart_() and not hasItem("HM03 - Surf") then + --It buy balls if not have badge, at blackoutleveling no + sys.debug("buying balls") return moveToMap("Safari Stop") - elseif not self:isTrainingOver() then + + elseif not self:isTrainingOver() + and not hasItem("HM03 - Surf") + then + sys.debug("on its way to training") return moveToMap("Route 15 Stop House") + elseif not hasItem("Soul Badge") then + sys.debug("heading to gym") return moveToMap("Fuchsia Gym") + elseif not self:canEnterSafari() then + sys.debug("farming, since safari cannot be entered") return moveToMap("Route 18") + elseif not hasItem("HM03 - Surf") then if not dialogs.questSurfAccept.state then + sys.debug("on its way to fight Viktor | to access safari zone") return moveToMap("Fuchsia City Stop House") else + sys.debug("heading to safari zone | to retrieve surf") return moveToMap("Safari Stop") end else + sys.debug("Quest done, heading to shore") return moveToMap("Fuchsia City Stop House") end end @@ -166,9 +240,9 @@ function SoulBadgeQuest:SafariStop() end function SoulBadgeQuest:Route15StopHouse() - if game.minTeamLevel() >= 60 then + if team.getLowestLvl() >= 60 then return moveToMap("Route 15") - elseif self:needPokecenter() or not self.registeredPokecenter == "Pokecenter Fuchsia" or self:isTrainingOver() then + elseif self:needPokecenter() or self.registeredPokecenter ~= "Pokecenter Fuchsia" or self:isTrainingOver() then return moveToMap("Fuchsia City") elseif hasItem("HM03 - Surf") then return moveToMap("Route 15") @@ -181,7 +255,7 @@ function SoulBadgeQuest:Route15StopHouse() end function SoulBadgeQuest:FuchsiaCityStopHouse() - if game.minTeamLevel() >= 60 then + if team.getLowestLvl() >= 60 then return moveToMap("Fuchsia City") elseif not hasItem("HM03 - Surf") then if dialogs.questSurfAccept.state then @@ -195,11 +269,11 @@ function SoulBadgeQuest:FuchsiaCityStopHouse() end function SoulBadgeQuest:Route19() - if game.minTeamLevel() >= 60 then + if team.getLowestLvl() >= 60 then return moveToMap("Fuchsia City Stop House") elseif hasItem("HM03 - Surf") then if not game.hasPokemonWithMove("Surf") then - if self.pokemonId < getTeamSize() then + if self.pokemonId <= getTeamSize() then useItemOnPokemon("HM03 - Surf", self.pokemonId) log("Pokemon: " .. self.pokemonId .. " Try Learning: HM03 - Surf") self.pokemonId = self.pokemonId + 1 @@ -220,7 +294,7 @@ function SoulBadgeQuest:Route19() end function SoulBadgeQuest:Route15() - if self:needPokecenter() or self:isTrainingOver() or not self.registeredPokecenter == "Pokecenter Fuchsia" then + if self:needPokecenter() or self:isTrainingOver() or self.registeredPokecenter ~= "Pokecenter Fuchsia" then return moveToMap("Route 15 Stop House") else return self:randomZoneExp() diff --git a/Quests/Kanto/ThunderBadgeQuest.lua b/Quests/Kanto/ThunderBadgeQuest.lua index 6c6ba51..7effe9c 100644 --- a/Quests/Kanto/ThunderBadgeQuest.lua +++ b/Quests/Kanto/ThunderBadgeQuest.lua @@ -118,7 +118,10 @@ function ThunderBadgeQuest:VermilionCity() self.dialogs.surgeVision.state = true end - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Vermilion" then + if not hasItem("Old Rod") then + --retrieve free rod + return moveToMap("Fisherman House - Vermilion") + elseif self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Vermilion" then return moveToMap("Pokecenter Vermilion") elseif not dialogs.psychicWadePart2.state then return moveToMap("Route 6") @@ -137,6 +140,13 @@ function ThunderBadgeQuest:VermilionCity() end end +function ThunderBadgeQuest:FishermanHouseVermilion() + --talk to the old fisherman + if not hasItem("Old Rod") then return talkToNpcOnCell(0,6) + --leave when rod obtained + else return moveToMap("Vermilion City") end +end + function ThunderBadgeQuest:puzzleBinPosition(binId) local xCount = 5 local yCount = 3 @@ -176,7 +186,7 @@ function ThunderBadgeQuest:solvePuzzle() end function ThunderBadgeQuest:VermilionGym() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Vermilion" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Vermilion" then return moveToMap("Vermilion City") elseif not self:isTrainingOver() and not hasItem("Thunder Badge") then return moveToMap("Vermilion City")-- Go to Route 6 and Leveling diff --git a/Quests/Kanto/ToCinnabarQuest.lua b/Quests/Kanto/ToCinnabarQuest.lua index ce85e45..2186447 100644 --- a/Quests/Kanto/ToCinnabarQuest.lua +++ b/Quests/Kanto/ToCinnabarQuest.lua @@ -1,4 +1,4 @@ --- Copyright © 2016 g0ld +-- Copyright © 2016 g0ld -- This work is free. You can redistribute it and/or modify it under the -- terms of the Do What The Fuck You Want To Public License, Version 2, -- as published by Sam Hocevar. See the COPYING file for more details. @@ -8,11 +8,13 @@ local sys = require "Libs/syslib" local game = require "Libs/gamelib" local Quest = require "Quests/Quest" -local Dialog = require "Quests/Dialog" +local pc = require "Libs/pclib" +local team = require "Libs/teamlib" +local SurfTarget = require "Data/surfTargets" local name = 'Traveling' local description = 'Route 8 To Cinnabar Island' -local level = 55 +local level = 55 local ToCinnabarQuest = Quest:new() @@ -44,7 +46,7 @@ function ToCinnabarQuest:PokecenterLavender() end function ToCinnabarQuest:LavenderTown() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Lavender" then + if self:needPokecenter() or not game.isTeamFullyHealed() or self.registeredPokecenter ~= "Pokecenter Lavender" then return moveToMap("Pokecenter Lavender") else return moveToMap("Route 12") @@ -105,26 +107,69 @@ function ToCinnabarQuest:Route15StopHouse() return moveToMap("Fuchsia City") end +function ToCinnabarQuest:hasSurfer() + local surferIds = SurfTarget.getIds() + local teamIds = team.getPkmIds() + local matches = Set.intersection(teamIds, surferIds) + + return team.getFirstPkmWithMove("surf") or matches +end + function ToCinnabarQuest:PokecenterFuchsia() - self:pokecenter("Fuchsia City") + + local surferIds = SurfTarget.getIds() + + --1. check for surfer + if not self:hasSurfer() then + local result, pkmBoxId, slotId, swapTeamId = + pc.retrieveFirstFromIds(surferIds) + + --working | then return because of open proShine functions to be resolved + -- | if not returned, a "can only execute one function per frame" might occur + if result == pc.result.WORKING then return sys.info("Searching PC") + + --no solution, terminate bot + elseif result == pc.result.NO_RESULT then + return sys.error("No pokemon in your team or on your computer has the ability to surf. Can't progress Quest") + end + + --solution found and added + local pkm = result + local msg = "Found Surfer "..pkm.name.." on BOX: " .. pkmBoxId .. " Slot: " .. slotId + if swapTeamId then msg = msg .. " | Swapping with pokemon in team N: " .. swapTeamId + else msg = msg .. " | Added to team." end + sys.log(msg) + + --do basic pokecenter related stuff... + else self:pokecenter("Fuchsia City") end + +end + +function ToCinnabarQuest:isRodObtainable() + return BUY_RODS and hasItem("Old Rod") and not hasItem("Good Rod") and getMoney() >= 15000 end function ToCinnabarQuest:FuchsiaHouse1() - if hasItem("Old Rod") and not hasItem("Good Rod") and getMoney() > 15000 then - return talkToNpcOnCell(3,6) - else - return moveToMap("Fuchsia City") - end + --talk to the fishing guru + if self:isRodObtainable() then return talkToNpcOnCell(3,6) + --leave + else return moveToMap("Fuchsia City") end end function ToCinnabarQuest:FuchsiaCity() - if self:needPokecenter() or not game.isTeamFullyHealed() or not self.registeredPokecenter == "Pokecenter Fuchsia" then + --visiting pokecenter + if self:needPokecenter() or not game.isTeamFullyHealed() --healing + or not self:hasSurfer() --getting surfer + or self.registeredPokecenter ~= "Pokecenter Fuchsia" --register pokecenter + then return moveToMap("Pokecenter Fuchsia") - elseif hasItem("Old Rod") and not hasItem("Good Rod") and getMoney() > 15000 then - return moveToMap("Fuchsia House 1") --Item: GoodRod - else - return moveToMap("Fuchsia City Stop House") - end + + --Item: GoodRod + elseif self:isRodObtainable() then + return moveToMap("Fuchsia House 1") + + --else progress story + else return moveToMap("Fuchsia City Stop House") end end function ToCinnabarQuest:FuchsiaCityStopHouse() diff --git a/Quests/Kanto/ViridianSchoolQuest.lua b/Quests/Kanto/ViridianSchoolQuest.lua index fa1d91d..fb24b03 100644 --- a/Quests/Kanto/ViridianSchoolQuest.lua +++ b/Quests/Kanto/ViridianSchoolQuest.lua @@ -5,6 +5,7 @@ local sys = require "Libs/syslib" local game = require "Libs/gamelib" +local team = require "Libs/teamlib" local Quest = require "Quests/Quest" local Dialog = require "Quests/Dialog" @@ -61,7 +62,7 @@ function ViridianSchoolQuest:Route1StopHouse() end function ViridianSchoolQuest:isTrainingOver() - if getTeamSize() >= 2 and game.minTeamLevel() >= self.level then + if getTeamSize() >= 2 and team.getLowestLvl() >= self.level then return true end return false diff --git a/Quests/Kanto/VolcanoBadgeQuest.lua b/Quests/Kanto/VolcanoBadgeQuest.lua index b5a415a..136fa2c 100644 --- a/Quests/Kanto/VolcanoBadgeQuest.lua +++ b/Quests/Kanto/VolcanoBadgeQuest.lua @@ -12,7 +12,7 @@ local Dialog = require "Quests/Dialog" local name = 'Volcano Badge' local description = 'Revive Fossil + Cinnabar Key + Exp on Seafoam B4F' -local level = 75 +local level = 85 local VolcanoBadgeQuest = Quest:new() @@ -39,7 +39,7 @@ function VolcanoBadgeQuest:PokecenterCinnabar() end function VolcanoBadgeQuest:CinnabarIsland() - if self:needPokecenter() or not self.registeredPokecenter == "Pokecenter Cinnabar" then + if self:needPokecenter() or self.registeredPokecenter ~= "Pokecenter Cinnabar" then return moveToMap("Pokecenter Cinnabar") elseif not self:isTrainingOver() then return moveToMap("Route 20") @@ -139,7 +139,7 @@ function VolcanoBadgeQuest:SeafoamB4F() if self:canUseNurse() then -- if have 1500 money return talkToNpcOnCell(59,13) else - if not game.getTotalUsablePokemonCount() > 1 then -- Try get 1500money + if not (game.getTotalUsablePokemonCount() > 1) then -- Try get 1500money fatal("don't have enough Pokemons for farm 1500 money and heal the team") else return moveToRectangle(50,10,62,32) diff --git a/Quests/Quest.lua b/Quests/Quest.lua index f22ac86..2bd1de6 100644 --- a/Quests/Quest.lua +++ b/Quests/Quest.lua @@ -5,6 +5,7 @@ local sys = require "Libs/syslib" local game = require "Libs/gamelib" +local team = require "Libs/teamlib" local blacklist = require "blacklist" @@ -19,6 +20,8 @@ function Quest:new(name, description, level, dialogs) o.level = level or 1 o.dialogs = dialogs o.training = true + o.canRun = true + o.canSwitch = true return o end @@ -60,25 +63,39 @@ end -- use this function then function Quest:pokemart(exitMapName) local pokeballCount = getItemQuantity("Pokeball") + --local escapeRopeCount = getItemQuantity("Escape Rope") local money = getMoney() + + --pokeballs if money >= 200 and pokeballCount < 50 then - if not isShopOpen() then - return talkToNpcOnCell(3,5) - else - local pokeballToBuy = 50 - pokeballCount - local maximumBuyablePokeballs = money / 200 - if maximumBuyablePokeballs < pokeballToBuy then - pokeballToBuy = maximumBuyablePokeballs - end - return buyItem("Pokeball", pokeballToBuy) - end - else - return moveToMap(exitMapName) - end + --talk to shop owner - can it be they are always located at 3,5? Doesn't seem right + if not isShopOpen() then return talkToNpcOnCell(3,5) end + + --else prepare buying + local pokeballToBuy = 50 - pokeballCount + local maximumBuyablePokeballs = money / 200 + pokeballToBuy = math.min(pokeballToBuy, maximumBuyablePokeballs) + + return buyItem("Pokeball", pokeballToBuy) + + --escape ropes added for jails and other circumstances +-- elseif money >= 550 and escapeRopeCount < 3 then +-- --talk to shop owner - can it be they are always located at 3,5? Doesn't seem right +-- if not isShopOpen() then return talkToNpcOnCell(3,5) end +-- +-- --else prepare buying +-- local ropesToBuy = 5 - escapeRopeCount +-- local maxBuyableRopes = money / 550 +-- ropesToBuy = math.min(ropesToBuy, maxBuyableRopes) +-- +-- return buyItem("Escape Rope", ropesToBuy) + + --if nothing to buy, leave mart + else return moveToMap(exitMapName) end end function Quest:isTrainingOver() - if game.minTeamLevel() >= self.level then + if team.getLowestLvl() >= self.level then if self.training then -- end the training self:stopTraining() end @@ -88,6 +105,7 @@ function Quest:isTrainingOver() end function Quest:leftovers() + if leftovers_disabled then return end ItemName = "Leftovers" local PokemonNeedLeftovers = game.getFirstUsablePokemon() local PokemonWithLeftovers = game.getPokemonIdWithItem(ItemName) @@ -135,7 +153,7 @@ function Quest:useBike() if hasItem("Bicycle") then if isOutside() and not isMounted() and not isSurfing() and getMapName() ~= "Cianwood City" and getMapName() ~= "Route 41" then useItem("Bicycle") - log("Using: Bicycle") + sys.log("Using: Bicycle") return true --Mounting the Bike else return false @@ -164,24 +182,22 @@ end function Quest:needPokecenter() if getTeamSize() == 1 then - if getPokemonHealthPercent(1) <= 50 then - return true - end + if getPokemonHealthPercent(1) <= 50 then return true end + -- else we would spend more time evolving the higher level ones elseif not self:isTrainingOver() then - if getUsablePokemonCount() == 1 or game.getUsablePokemonCountUnderLevel(self.level) == 0 then - return true - end - else - if not game.isTeamFullyHealed() then - if self.healPokemonOnceTrainingIsOver then - return true - end - else - -- the team is healed and we do not need training - self.healPokemonOnceTrainingIsOver = false - end - end + -- <= needed, if last pkm has no pp, it's also unusable therefor value = 0 + if getUsablePokemonCount() <= 1 + or not team.getAlivePkmToLvl(self.level) + then return true end + + elseif not game.isTeamFullyHealed() + and self.healPokemonOnceTrainingIsOver + then return true + + -- the team is fully healed and training over + else self.healPokemonOnceTrainingIsOver = false end + return false end @@ -199,26 +215,12 @@ local moonStoneTargets = { "Skitty" } -function Quest:advanceSorting() - local pokemonsUsable = game.getTotalUsablePokemonCount() - for pokemonId=1, pokemonsUsable, 1 do - if not isPokemonUsable(pokemonId) then --Move it at bottom of the Team - for pokemonId_ = pokemonsUsable + 1, getTeamSize(), 1 do - if isPokemonUsable(pokemonId_) then - swapPokemon(pokemonId, pokemonId_) - return true - end - end - - end - end - if not isTeamRangeSortedByLevelAscending(1, pokemonsUsable) then --Sort the team without not usable pokemons - return sortTeamRangeByLevelAscending(1, pokemonsUsable) - end - return false -end - function Quest:evolvePokemon() + -- some buffer levels, to ensure every teammember is fully evolved when figthing e4 + -- some leeway for indiviudal quest caps: Kanto e4 is started with lv 95, so evolving could start at 93 + if team.getLowestLvl() >= 90 then enableAutoEvolve() end + -- or team.getHighestLvl() >= 93 --not leveling mixed teams efficiently: lv 38, ...., lv 93 + local hasMoonStone = hasItem("Moon Stone") for pokemonId=1, getTeamSize(), 1 do local pokemonName = getPokemonName(pokemonId) @@ -231,26 +233,27 @@ function Quest:evolvePokemon() return false end +--prevents the sort algorithm being visualized - e.g. when gm inspects team +function Quest:sortInMemory() + --setting lowest level pkm as starter + local starter = team.getStarter() + local lowestAlivePkmToLvl = team.getLowestAlivePkmToLvl(self.level) + if lowestAlivePkmToLvl and --if one exists, skips if nothing found + starter ~= lowestAlivePkmToLvl --skips if found target the starter already + then return swapPokemon(lowestAlivePkmToLvl, starter) end + + --setting highest level pkm, as last defense wall + local highestAlivePkm = team.getHighestPkmAlive() --has to be found or you would have feinted + local lastPkm = team.getLastPkmAlive() + if highestAlivePkm ~= lastPkm then return swapPokemon(highestAlivePkm, lastPkm) end +end + + function Quest:path() - if self.inBattle then - self.inBattle = false - self:battleEnd() - end - if self:evolvePokemon() then - return true - end - --if not isTeamSortedByLevelAscending() then - --return sortTeamByLevelAscending() - --end - if self:advanceSorting() then - return true - end - if self:leftovers() then - return true - end - if self:useBike() then - return true - end + if self:evolvePokemon() then return true end + if self:sortInMemory() then return true end + if self:leftovers() then return true end + if self:useBike() then return true end local mapFunction = self:mapToFunction() assert(self[mapFunction] ~= nil, self.name .. " quest has no method for map: " .. getMapName()) self[mapFunction](self) @@ -260,92 +263,67 @@ function Quest:isPokemonBlacklisted(pokemonName) return sys.tableHasValue(blacklist, pokemonName) end -function Quest:battleBegin() - self.canRun = true - self.canSwitch = true -end - -function Quest:battleEnd() - self.canRun = true - self.canSwitch = true -end - -- I'll need a TeamManager class very soon local blackListTargets = { --it will kill this targets instead catch - "Metapod", - "Kakuna", - "Doduo", - "Hoothoot", - "Zigzagoon" +-- "Metapod", +-- "Kakuna", +-- "Doduo", +-- "Hoothoot", +-- "Zigzagoon" } -function Quest:wildBattle() +function Quest:battle() -- catching local isEventPkm = getOpponentForm() ~= 0 - if isOpponentShiny() or isEventPkm --catch special pkm - or (not isAlreadyCaught() and not sys.tableHasValue(blackListTargets, getOpponentName())) --catch not seen pkm - or (self.pokemon and getOpponentName() == self.pokemon --catch quest related pkm - and self.forceCaught ~= nil and self.forceCaught == false) --try caught only if never caught in this quest - then - if useItem("Pokeball") or useItem("Great Ball") or useItem("Ultra Ball") then return true end - end - - -- team needs no healing - if getTeamSize() == 1 or getUsablePokemonCount() > 1 then + if isWildBattle() --if it's a wild battle: + and (isOpponentShiny() --catch special pkm + or isEventPkm + or (not isAlreadyCaught() --catch not seen pkm + and not self:isPokemonBlacklisted(getOpponentName())) + or (self.pokemon --catch quest related pkm + and getOpponentName() == self.pokemon + and self.forceCaught ~= nil + and self.forceCaught == false)) + then if useItem("Pokeball") or useItem("Great Ball") or useItem("Ultra Ball") then return true end end + + --fighting + local isTeamUsable = getTeamSize() == 1 --if it's our starter, it has to atk + or getUsablePokemonCount() > 1 --otherwise we atk, as long as we have 2 usable pkm + if isTeamUsable then + --level low leveled pkm | switching local opponentLevel = getOpponentLevel() local myPokemonLvl = getPokemonLevel(getActivePokemonNumber()) - if opponentLevel >= myPokemonLvl then + if opponentLevel >= myPokemonLvl + and self.canSwitch + then local requestedId, requestedLevel = game.getMaxLevelUsablePokemon() - if requestedId ~= nil and requestedLevel > myPokemonLvl then - return sendPokemon(requestedId) - end + if requestedLevel > myPokemonLvl + and requestedId ~= nil + then return sendPokemon(requestedId) end end - --TODO: - sys.todo("rested canRun & canSwitch after successful round progression - see survivor class") - if attack() --atk - or self.canSwitch and sendUsablePokemon() --switch in battle ready pkm if able - or self.canRun and run() --run if able + --actual battle + if attack() --atk + or self.canSwitch and sendUsablePokemon() --switch in battle ready pkm if able + or self.canRun and run() --run if able or self.canSwitch and sendAnyPokemon() --switch in any alive pkm if able or game.useAnyMove() --use none damaging moves, to progress battle round - then return - else sys.error("quest.wildBattle", "no battle progression found for a battle headed team") end + then return sys.debug("fighting team", "battle action performed") + else return sys.error("quest.battle", "no battle action for a fighting team") end end - -- team needs healing - if self.canRun and run() --run if able - or self.canSwitch and sendUsablePokemon() --switch in battle ready pkm if able - or attack() --atk - or self.canSwitch and sendAnyPokemon() --switch in any alive pkm if able - or game.useAnyMove() --use none damaging moves, to progress battle round - then return - - else sys.error("quest.wildBattle", "no battle progression found for a pocecenter headed team") end + -- running + if self.canRun and run() --1. we try to run + or attack() --2. we try to attack + or self.canSwitch and sendUsablePokemon() --3. we try to switch pokemon that has pp + or self.canSwitch and sendAnyPokemon() --4. we try to switch to any pokemon alive + or game.useAnyMove() --5. we try to use non-damaging attack + --or BattleManager.useAnyAction() --6. we try to use garbage items + then return end sys.debug("running team", "battle action performed") + sys.error("quest.battle", "no battle action for a running team") end ---could probably be left out | throwing pokeballs at trainer pkms might be an issue. run just returns false -function Quest:trainerBattle() - -- bug: if last pokemons have only damaging but type ineffective - -- attacks, then we cannot use the non damaging ones to continue. - if not self.canRun then -- trying to switch while a pokemon is squeezed end up in an infinity loop - return attack() or game.useAnyMove() - end - return attack() or sendUsablePokemon() or sendAnyPokemon() -- or game.useAnyMove() -end - -function Quest:battle() - if not self.inBattle then - self.inBattle = true - self:battleBegin() - end - if isWildBattle() then - return self:wildBattle() - else - return self:trainerBattle() - end -end - function Quest:dialog(message) if self.dialogs == nil then return false @@ -360,47 +338,54 @@ function Quest:dialog(message) end function Quest:battleMessage(message) - sys.debug("battleMessage: "..message) + --reset after successful round progression if sys.stringContains(message, "Attacks") then - --reset after successful round progression self.canRun = true self.canSwitch = true - elseif sys.stringContains(message, "$CantRun") then - self.canRun = false - - elseif sys.stringContains(message, "$NoSwitch") then - self.canSwitch = false + --reset after ended fight | feinting + elseif sys.stringContains(message, "black out") then + self.canRun = true + self.canSwitch = true - elseif self.pokemon ~= nil and self.forceCaught ~= nil then - if sys.stringContains(message, "caught") and sys.stringContains(message, self.pokemon) then --Force caught the specified pokemon on quest 1time - log("Selected Pokemon: " .. self.pokemon .. " is Caught") - self.forceCaught = true - return true + --feinting + if self.level < 100 + and self:isTrainingOver() + then + self.level = math.max(team:getLowestLvl(), self.level) + 1 + self:startTraining() + log("Increasing " .. self.name .. " quest level to " .. self.level .. ". Training time!") end - elseif sys.stringContains(message, "black out") and self.level < 100 and self:isTrainingOver() then - self.level = math.max(self:getTeamLevel(), self.level) + 1 - self:startTraining() - log("Increasing " .. self.name .. " quest level to " .. self.level .. ". Training time!") - return true + --reset after ended fight | win + elseif sys.stringContains(message, "won the battle") then + self.canRun = true + self.canSwitch = true + + --restrain running + elseif sys.stringContains(message, "$CantRun") --in case resource folder was missing + or sys.stringContains(message, "You can not run away!") + then + self.canRun = false - end - return false -end + --restrain switching + elseif sys.stringContains(message, "$NoSwitch") + or sys.stringContains(message, "You can not switch this Pokemon!") + then + self.canSwitch = false -function Quest:getTeamLevel() - local minLvl = nil - for i = 1, getTeamSize() do - local pkmLvl = getPokemonLevel(i) - minLvl = minLvl or pkmLvl --set first pkm as lvl reference - minLvl = math.min(minLvl, pkmLvl) --get minimum between following team members + --force caught the specified pokemon on quest 1time + elseif self.pokemon ~= nil + and self.forceCaught ~= nil + and sys.stringContains(message, "caught") + and sys.stringContains(message, self.pokemon) + then + log("Selected Pokemon: " .. self.pokemon .. " is Caught") + self.forceCaught = true end - return minLvl end function Quest:systemMessage(message) - sys.debug("systemMessage: "..message) return false end @@ -424,7 +409,7 @@ function Quest:chooseForgetMove(moveName, pokemonIndex) -- Calc the WrostAbility end end end - log("[Learning Move: " .. moveName .. " --> Forget Move: " .. ForgetMoveName .. "]") + sys.log("[Learning Move: " .. moveName .. " --> Forget Move: " .. ForgetMoveName .. "]") return ForgetMoveName end diff --git a/Quests/TemplateQuest.lua b/Quests/TemplateQuest.lua index 171f794..716da6f 100644 --- a/Quests/TemplateQuest.lua +++ b/Quests/TemplateQuest.lua @@ -16,6 +16,7 @@ local sys = require "Libs/syslib" local game = require "Libs/gamelib" +local team = require "Libs/teamlib" local Quest = require "Quests/Quest" local Dialog = require "Quests/Dialog" @@ -108,7 +109,7 @@ end -- a simple method to divide our code and avoid duplication function TemplateQuest:isReadyForJackson() - if getTeamSize() >= 2 and game.minTeamLevel() >= 8 then + if getTeamSize() >= 2 and team.getLowestLvl() >= 8 then return true end return false diff --git a/Tests/test_pclib_retrieveFirstById.lua b/Tests/test_pclib_retrieveFirstById.lua new file mode 100644 index 0000000..e32b827 --- /dev/null +++ b/Tests/test_pclib_retrieveFirstById.lua @@ -0,0 +1,41 @@ +local sys = require "Libs/syslib" +local game = require "Libs/gamelib" +local pc = require "Libs/pclib" +local team = require "Libs/teamlib" +local SurfTarget = require "Data/surfTargets" +local PkmName = require "Data/pokemonNames" +local Quest = require "Quests/Quest" +local Dialog = require "Quests/Dialog" + +local preferredSurferIds = {53} --Snorlax: 38, Psyduck: 54, Paras: 46, Persian: 53 +debug = true + +function onPathAction() + local swapId = nil + --local swapId = team.getLowestLvlPkm() + sys.debug("PC | lowestLVlpkm: "..team.getLowestLvlPkm()) + + local result, boxId, swapId = pc.retrieveFirstFromIds(preferredSurferIds, swapId) --testing for that surf pkm on pc + sys.debug("----PC vars:----", true) + sys.debug("PC | result " .. tostring(result)) + sys.debug("PC | boxId " .. tostring(boxId)) + + -- boxItem is no solution + if result == pc.result.NO_RESULT then + -- quick fix until pathfinder is added, then catching one wouldn't be much of a hassle + return sys.error("fn", "No pokemon in your team or on your computer has the ability to surf. Can't progress Quest") + + --still searching | don't do other actions | return statement needed + elseif result == pc.result.STILL_WORKING then return sys.debug("Starting PC or Switching Boxes") end + + --solution found + --preparing swap target | taking held item, if it has one + local slotId = result + + local msg = "LOG: Found Surfer on BOX: " .. boxId .." Slot: ".. slotId + if swapId then msg = msg.." | Swapping with pokemon in team N: " .. swapId + else msg = msg.." | Added to team." end + + log(msg) + fatal("Finished :)") +end \ No newline at end of file diff --git a/config.lua b/config.lua index 1073c62..2b68455 100644 --- a/config.lua +++ b/config.lua @@ -1,4 +1,24 @@ -KANTO_STARTER_ID=math.random(1,4) -- 1: Fatvegan, 2: Salamender, 3: Aquaturtle, 4: Mickeychu -KANTO_FOSSIL_ID =math.random(1,2) -- 1: Helix, 2: Dome -DOJO_POKEMON_ID =math.random(1,2) -- 1: Hitmonchan, 2: Hitmonlee -BUY_BYKE = true \ No newline at end of file +-- ------Quest related options------ +--generall +BUY_BIKE = true -- true: buy bike, false: buy not +BUY_RODS = true -- true: buy rods, false: buy not + +--regional - kanto +KANTO_STARTER_ID = nil -- nil: random, 1: Fatvegan, 2: Salamender, 3: Aquaturtle, 4: Mickeychu + +KANTO_FOSSIL_ID = nil -- nil: random, 1: Helix, 2: Dome +KANTO_DOJO_POKEMON_ID = nil -- nil: random, 1: Hitmonchan, 2: Hitmonlee + +--regional - jotho +JOTHO_STARTER_ID = nil -- not implemented yet | script will choose starter on it's own + +--regional - hoenn +HOENN_STARTER_ID = nil -- not implemented yet | script will choose starter on it's own + + + +-- ------Bot related options------ +DISABLE_PM = true -- true: private messaging will be disabled, false: no changes will be done + +DEBUG = false -- printing debug comments +TODO = false -- printing todo comments \ No newline at end of file