Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


CmP last won the day on March 3

CmP had the most liked content!

Recent Profile Visitors

16,999 profile views

CmP's Achievements


Proficient (10/14)

  • Posting Machine Rare
  • One Year In
  • One Month Later
  • Week One Done
  • Dedicated Rare

Recent Badges



  1. As others mentioned above, this is not something that needs a fix from user side. The regions that were identified by GG as "C++ alloc" or "C++ heap" on Android 10 and earlier versions are (in some, but not all, cases) identified as "Other" on Android 11 and higher versions. So the solution is do the following:
  2. The idea is to read enough bytes at once and then trim the string to first occurrence of quote character instead of reading one byte at a time until quote character is encountered. Generally, first approach should be better in terms of performance, because each read from memory takes significantly more time than several Lua operations, even if just one byte needs to be read. I thought to add 12 to get position of first byte of the answer that is the next one after last quote character in searched string. I don't immediately see why it doesn't work as expected, but it seems that there is a mistake somewhere and it's fixed by your correction to use "+ 11" instead of "+ 12".
  3. You should also consider refactoring the code to make it simpler and cleaner. For example, your "MENU1" function can be refactored to something like the following: function MENU1() gg.setRanges(gg.REGION_ANONYMOUS) gg.clearResults() gg.searchNumber(':","answer":"', gg.TYPE_BYTE) local count = gg.getResultsCount() local results = gg.getResults(count) local answers = {} for i = 1, count, 12 do local address = results[i].address + 12 local maxLength = 1024 local answer = readBytesToString(address, maxLength) answer = answer:match('[^"]*') -- match part up to first quote character table.insert(answers, answer) end for number, answer in ipairs(answers) do print(string.format("Answer #%d:", number), answer) end gg.alert("Answer See [ON]") end Let me know, if the code above works for you.
  4. To output a string Lua implementation in GG treats it as UTF-8 (by themselves Lua strings are just byte arrays), so reading bytes from memory to Lua string and passing the string to a function that outputs it ("print", "gg.alert", "gg.toast", etc) should be enough to achieve desired result in your case. Here is an example of function for reading bytes from memory and constructing string from them: function readBytesToString(address, length) local values = {} for i = 0, length - 1 do values[i] = {address = address + i, flags = gg.TYPE_BYTE} end values = gg.getValues(values) local bytes = {} for i, v in ipairs(values) do bytes[i] = v.value & 0xFF end return string.char(table.unpack(bytes)) end Call it with address to read from as first argument and amount of bytes to read as second argument, for example: local startAddress = 0x12340000 local bytesToRead = 20 local result = readBytesToString(startAddress, bytesToRead) print(result)
  5. CmP

    Edit only one final value

    You can use second parameter of "getResults" function to get (only) the last result: local count = gg.getResultsCount() local result = gg.getResults(1, count - 1) result[1].value = 123 gg.setValues(result)
  6. Preserving selection state only of some menu items can be done by adding a table for specifying menu items whose selection state needs to be preserved and updating "selection" table after the call to "multiChoice" function according to the added table and user's selection of items. Here is an example of how it can be implemented based on your code: function updateSelection(selection, keysToUpdate, newSelection) newSelection = newSelection or {} for i = 1, #selection do if keysToUpdate[i] then -- if item's selection state needs to be updated selection[i] = newSelection[i] or false -- update item's selection state and ensure that new value is not nil else selection[i] = false -- reset item's selection state to unselected end end end local options = {'Skip Game', 'Infinite Ammo', 'Exit'} local selection = {false, false, false} local remember = {[2] = true} function start() local choices = gg.multiChoice(options, selection) updateSelection(selection, remember, choices) if choices == nil then return end if choices[3] then print('Exited') os.exit() end if choices[1] then gg.toast('GAME SKIPPED') end if choices[2] then gg.toast('ON') else gg.toast('OFF') end end while true do if gg.isVisible() then gg.setVisible(false) start() end gg.sleep(100) end
  7. I can confirm the behavior of fuzzy search that is shown in the video. Some values of floating-point types (Float and Double), despite not changing, pass both "Increased" and "Decreased" conditions (but not "Changed", it correctly filters most of them out). It's not absolutely clear whether such behavior is intentional or not, but from user's side it's fairly easy to account for it. First time after making target value change in the game, search for values that have "changed". After that "increased" and "decreased" modes can be used as usual to find values that have increased or decreased correspondingly. Search tab toolbar contains "Remove" item (). Tapping on it causes dialog to be displayed with it's first option being "Remove all". Choosing the option clears results list allowing to start new fuzzy search.
  8. Relevant explanation from StackOverflow answer: https://stackoverflow.com/a/6389082
  9. It's because of fundamentals of how Lua is implemented. The implementations (official one and LuaJ) are single-threaded, therefore only one operation can be performed at a time. Nothing can be done about it without changing the implementation.
  10. How does that achieve the goal though? Original "searchNumber" function needs to be called anyway to actually perform the search. When it's called, it will only return after the search is finished (successfully or by cancellation). So how would a coroutine do anything when Lua executes native (i.e. not Lua one) function?
  11. Can you explain how would coroutines make that possible? How would you pass execution to a coroutine after calling "searchNumber", when it is doing it's job? Coroutines don't make it possible to execute code in parallel.
  12. Check the code carefully. Your manually retyped code has difference in second and third lines of loop body. Second line of loop's body from my code: heightValuesCheck[(i - 1) * 3 + 2] = {address = v.address - 0x100, flags = gg.TYPE_FLOAT} And how you retyped it: heightValuesCheck[(i - 1) * 3 + 1] = {address = v.address - 0x100, flags = gg.TYPE_FLOAT} It should be "(i - 1) * 3 + 2" there for the code to work as intended. Third line of loop's body in your retyped code needs to be fixed accordingly. This code is a minor optimization for adding elements to the end of array part of the table for the case of adding 3 elements per loop iteration. It achieves same result as more familiar "[#heightValuesCheck + 1]". The expression "(i - 1) * 3" is for calculating "base" index for three elements to be added to the table during iteration "i". At the first iteration, when i = 1, the expression evaluates to 0. At the second iteration (i = 2) the expression evaluates to 3. At the third to 6, and so on. To calculate index for the first element to be added during iteration, 1 is added to the result of the expression, giving index of 1 at the first iteration, 4 at the second iteration, 7 at the third iteration, and so on. Likewise, index of the second element to be added during iteration is calculated by adding 2 to the result of the expression and index of the third element - by adding 3.
  13. First and the most important thing that can be done to optimize the code is to call "setValues" once after loop(s) instead of calling it each time for the whole table after setting "value" field of one sub-table. It is extremely redundant to call "setValues" N times for table of N values (sub-tables). It only needs to be called once, after desired values of "value" field of all sub-tables (for which the value needs to be edited) have been set. One other thing that can be done is to have one table for all values instead of three tables, since all values need to be edited the same way. This won't make the code noticeably more or less efficient, but it will allow to replace fragments of code that are repeated three times (once for each table) with one instance of them for combined table. The code with the changes suggested above can look like the following: function theGiant() if giants == on then gg.setRanges(gg.REGION_ANONYMOUS | gg.REGION_OTHER) gg.clearResults() gg.searchNumber('h 85 EB 91 3F 6F 12 03 3C', gg.TYPE_BYTE) -- corrected the type here gg.refineNumber('h 85', gg.TYPE_BYTE) local results = gg.getResults(50) gg.clearResults() local heightValuesCheck = {} for i, v in ipairs(results) do heightValuesCheck[(i - 1) * 3 + 1] = {address = v.address - 0x104, flags = gg.TYPE_FLOAT} heightValuesCheck[(i - 1) * 3 + 2] = {address = v.address - 0x100, flags = gg.TYPE_FLOAT} heightValuesCheck[(i - 1) * 3 + 3] = {address = v.address - 0xFC, flags = gg.TYPE_FLOAT} end heightValuesCheck = gg.getValues(heightValuesCheck) -- filtering the tables, so that only tables with value '1' are left to avoid possible crashing during editing. heightValues = {} for i, v in ipairs(heightValuesCheck) do if v.value == 1 then heightValues[#heightValues + 1] = v end end -- editing, user input = ON for i, v in ipairs(heightValues) do v.value = '2.125478' end gg.setValues(heightValues) -- calling the function once, after desired values are set for all table elements else -- editing, user input = OFF for i, v in ipairs(heightValues) do v.value = '1' end gg.setValues(heightValues) -- calling the function once likewise end end
  14. CmP


    "Aarch64 = arm64" statement is correct. AArch64 is the name of 64-bit ARM architecture. Both names refer to the same thing.
  15. Try changing the option for GG to work with SELinux as mentioned here: Android 11 My phone is rooted but game gaurdian not work properly I'm downloading latest version it's not fix (#axy2r12m)
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.