--[v1.2 beta]-- --====== User Options ======-- local qlowerlimit1 = 420000 -- sets the default first lower limit of Quest Ids to search for. local qupperlimit1 = 430000 -- sets the default first upper limit of Quest Ids to search for. local qlowerlimit2 = nil -- sets the default second lower limit of Quest Ids to search for. local qupperlimit2 = nil -- sets the default second upper limit of Quest Ids to search for. local slowerlimit1 = 490000 -- sets the default first lower limit of Skill Ids to search for. local supperlimit1 = 499999 -- sets the default first upper limit of Skill Ids to search for. local slowerlimit2 = nil -- sets the default second lower limit of Skill Ids to search for. local supperlimit2 = nil -- sets the default second upper limit of Skill Ids to search for. local blowerlimit1 = 500000 -- sets the default first lower limit of Buff Ids to search for. local bupperlimit1 = 500999 -- sets the default first upper limit of Buff Ids to search for. local blowerlimit2 = 620000 -- sets the default second lower limit of Buff Ids to search for. local bupperlimit2 = 629999 -- sets the default second upper limit of Buff Ids to search for. --==========================-- -- code by rock5 local function collectKeys(text) -- local function to find start of string byt finding the null before the string local function findLastNull(address) while memoryReadByte(getProc(), address) ~= 0 do address = address - 1 end return address end -- Start and end address of the text strings local addressPtrsBase = memoryReadInt(getProc(), addresses.getTEXT) local startloc = memoryReadInt(getProc(), addressPtrsBase + 0x268) local endloc = memoryReadInt(getProc(), addressPtrsBase + 0x26C) local searchlen = endloc - startloc -- The pattern and mask. ? wild cards are supported. local pattern = text local mask = text:gsub("[^?]","x") -- Search for all matches local results={} local searchloc = startloc while searchloc < endloc do local found = findPatternInProcess(getProc(), pattern, mask, searchloc, searchlen); if found == 0 then break end -- Search back for start of string local textStartAddress = findLastNull(found) if textStartAddress == nil then -- not found break end -- Read full string local tmpText = memoryReadString(getProc(), textStartAddress+1) -- Search back for matching key string local keyStartAddress = findLastNull(textStartAddress-1) if keyStartAddress < startloc then -- The very first key isn't preceded by a null keyStartAddress = startloc-1 end -- Read key string local tmpKey = memoryReadString(getProc(), keyStartAddress+1) -- Print and add to results table.insert(results,{Key=tmpKey, Name=tmpText}) -- Continue searching for more results searchloc = textStartAddress+ #tmpText + 2 searchlen = endloc - searchloc end return results end local function fixStrings(first, rest) return first:gsub("(.)","?")..rest:lower() end local function process(_name, _exactmatch, _llimit1, _ulimit1, _llimit2, _ulimit2, _skill, _syssearch, _quest) local _starttime = getTime() local _nname = NormaliseString(_name) local _name = _name:gsub("(%a)([%w_']*)", fixStrings) local results = collectKeys(_name) local matches, matchcount = {}, 0 for i,v in pairs(results) do local id; if not _syssearch then id = v.Key:match("^Sys(%d%d%d%d%d%d)_name$") end if id then id = tonumber(id) end if id or _syssearch then local _nresult = NormaliseString(v.Name) local processmatch = true if (not _llimit1 and not _ulimit1 and not _llimit2 and not _ulimit2) or (_llimit1 and _ulimit1 and id >= _llimit1 and id <= _ulimit1) or (_llimit2 and _ulimit2 and id >= _llimit2 and id <= _ulimit2) then if (not _ulimit2 and _ulimit1 and id > _ulimit1) or (_ulimit2 and id > _ulimit2) then break end if ((_exactmatch and _nname == _nresult) or (not _exactmatch)) then local tmp, addr = {} if _syssearch then tmp.SystemText, tmp.Text = v.Key, v.Name else tmp.Id, tmp.Name = id, v.Name end if _skill or _quest then addr = GetItemAddress(id) end if addr and _skill then tmp.CastTime, tmp.Range = memoryReadFloat(getProc(), addr + addresses.skillCastTime_offset), memoryReadUInt(getProc(), addr + addresses.skillRange_offset) end if addr and _quest then local _qtype = {[0] = "normal", [2] = "daily", [3] = "public"} local _typ = memoryReadInt(getProc(), addr + addresses.questGroup_offset) if _quest == "all" then tmp.Level, tmp.Type = memoryReadUInt(getProc(), addr + 0xA0), _qtype[_typ] else if _qtype[_typ] == _quest then tmp.Level, tmp.Type = memoryReadUInt(getProc(), addr + 0xA0), _qtype[_typ] else processmatch = false end end end if processmatch then matchcount = matchcount + 1 printf("Match %s\n\n",matchcount) table.print(tmp) print("") matches[matchcount] = tmp end end end end end local _runtime = deltaTime(getTime(), _starttime) / 1000 printf("Search took %0.2f seconds.\n\n", _runtime) if #matches > 1 then cprintf(cli.yellow, "%s Matches Found.\n\n", matchcount) return matches elseif #matches == 1 then if _syssearch then cprintf(cli.yellow, "%s\n\n", matches[1].SystemText) return matches[1].Key else cprintf(cli.yellow, "The Id is: %s\n\n", matches[1].Id) return matches[1].Id end else cprintf(cli.lightred, "No Matches Found.\n\n") return false end end local function process2(searchstring, exactstringmatch, srchlwrlimit1, srchuprlimit1, srchlwrlimit2,srchuprlimit2, questsearch, skillsearch) local ids, count, starttime, matchesfound = {}, 0, getTime(), 0; local addr, idname, lowname; local qtype = {[0] = "normal", [2] = "daily", [3] = "public"} local function getAndPrintData(mid) local tmp, allok, printmatch = {}, true, true; if questsearch then local typ = memoryReadInt(getProc(), addr + addresses.questGroup_offset) if questsearch == "all" then tmp.Level, tmp.Type = memoryReadUInt(getProc(), addr + 0xA0), qtype[typ] else if qtype[typ] == questsearch then tmp.Level, tmp.Type = memoryReadUInt(getProc(), addr + 0xA0), qtype[typ] else printmatch = false allok = false end end elseif skillsearch then tmp.CastTime, tmp.Range = memoryReadFloat(getProc(), addr + addresses.skillCastTime_offset), memoryReadUInt(getProc(), addr + addresses.skillRange_offset) end if allok then tmp.Id, tmp.Name = mid, idname end if printmatch then count = count + 1 printf("Match %s\n\n", count) table.print(tmp) print("") ids[count] = tmp end end if srchlwrlimit1 and srchuprlimit1 then for id = srchlwrlimit1, srchuprlimit1 do printf(id.."\r") addr = GetItemAddress(id) if addr then idname = memoryReadStringPtr( getProc(), addr + addresses.nameOffset, 0 ) if idname then lowname = NormaliseString(idname) end end if idname and exactstringmatch and lowname and lowname == searchstring then getAndPrintData(id) end if idname and not exactstringmatch and lowname and lowname:find(searchstring) then getAndPrintData(id) end end end if srchlwrlimit2 and srchuprlimit2 then for id = srchlwrlimit2, srchuprlimit2 do printf(id.."\r") addr = GetItemAddress(id) if addr then idname = memoryReadStringPtr( getProc(), addr + addresses.nameOffset, 0 ) if idname then lowname = NormaliseString(idname) end end if idname and exactstringmatch and lowname and lowname == searchstring then getAndPrintData(id) end if idname and not exactstringmatch and lowname and lowname:find(searchstring) then getAndPrintData(id) end end end local runtime = deltaTime(getTime(), starttime) / 1000 printf("Search took %0.2f seconds.\n\n", runtime) if #ids > 1 then cprintf(cli.yellow, "%s Matches Found.\n\n", count) return ids elseif #ids == 1 then cprintf(cli.yellow, "The Id is: %s\n\n", ids[1].Id) return ids[1].Id else cprintf(cli.lightred, "No Matches Found.\n\n") return false end end function GetIdByName(gidname, gidexactmatch, gidllimit1, gidulimit1, gidllimit2, gidulimit2) if gidname == nil then error("GetIdByName Error: Name must not be nil.") elseif gidname ~= nil and type(gidname) ~= "string" then error("GetIdByName Error: Name must be a string.") end if gidexactmatch == nil then gidexactmatch = true else if type(gidexactmatch) ~= "boolean" then error("GetIdByName Error: Unrecognized exact match type.") end end local gidllimit1, gidulimit1 = tonumber(gidllimit1), tonumber(gidulimit1); local gidllimit2, gidulimit2 = tonumber(gidllimit2), tonumber(gidulimit2); process(gidname, gidexactmatch, gidllimit1, gidulimit1, gidllimit2, gidulimit2) end function GetQuestId(qname, questtype, qexactmatch, qllimit1, qulimit1, qllimit2, qulimit2) if qname == nil then error("GetQuestId Error: Quest Name must not be nil.") elseif qname ~= nil then if type(qname) == "string" then qname = NormaliseString(qname) else error("GetQuestId Error: Quest Name must be a string.") end end if questtype == nil then questtype = "all" elseif questtype ~= nil then if type(questtype) == "string" then questtype = questtype:lower() if questtype ~= "all" and questtype ~= "normal" and questtype ~= "daily" and questtype ~= "public" then questtype = "all" end else error("GetQuestId Error: Invalid quest type.") end end if qexactmatch == nil then qexactmatch = true else if type(qexactmatch) ~= "boolean" then error("GetQuestId Error: Unrecognized exact match type.") end end local qllimit1, qulimit1 = tonumber(qllimit1) or qlowerlimit1, tonumber(qulimit1) or qupperlimit1; local qllimit2, qulimit2 = tonumber(qllimit2) or qlowerlimit2, tonumber(qulimit2) or qupperlimit2; process(qname, qexactmatch, qllimit1, qulimit1, qllimit2, qulimit2, nil, nil, questtype) end function GetSkillId(sname, sexactmatch, sllimit1, sulimit1, sllimit2, sulimit2) if sname == nil then error("GetSkillId Error: Skill Name must not be nil.") elseif sname ~= nil and type(sname) ~= "string" then error("GetSkillId Error: Skill Name must be a string.") end if sexactmatch == nil then sexactmatch = true else if type(sexactmatch) ~= "boolean" then error("GetSkillId Error: Unrecognized exact match type.") end end local sllimit1, sulimit1 = tonumber(sllimit1) or slowerlimit1, tonumber(sulimit1) or supperlimit1; local sllimit2, sulimit2 = tonumber(sllimit2) or slowerlimit2, tonumber(sulimit2) or supperlimit2; process(sname, sexactmatch, sllimit1, sulimit1, sllimit2, sulimit2, true) end function GetBuffId(bname, bexactmatch, bllimit1, bulimit1, bllimit2, bulimit2) if bname == nil then error("GetBuffId Error: Skill Name must not be nil.") elseif bname ~= nil and type(bname) ~= "string" then error("GetBuffId Error: Skill Name must be a string.") end if bexactmatch == nil then bexactmatch = true else if type(bexactmatch) ~= "boolean" then error("GetBuffId Error: Unrecognized exact match type.") end end local bllimit1, bulimit1 = tonumber(bllimit1) or blowerlimit1, tonumber(bulimit1) or bupperlimit1; local bllimit2, bulimit2 = tonumber(bllimit2) or blowerlimit2, tonumber(bulimit2) or bupperlimit2; process(bname, bexactmatch, bllimit1, bulimit1, bllimit2, bulimit2) end function GetSysText(systext, sysexactmatch) if systext == nil then error("GetSysText Error: Text must not be nil.") elseif systext ~= nil and type(systext) ~= "string" then error("GetSysText Error: Text must be a string.") end if sysexactmatch == nil then sysexactmatch = true else if type(sysexactmatch) ~= "boolean" then error("GetSysText Error: Unrecognized exact match type.") end end process(systext, sysexactmatch, nil, nil, nil, nil, nil, true) end