Jump to content

CmP

Contributor
  • Posts

    663
  • Joined

  • Last visited

  • Days Won

    49

Everything posted by CmP

  1. CmP

    addListItems with v.name

    This is wrong. "t" is a table of tables, so "v" in our loop refers to particular sub-table (one per iteration). Lua reference manual states the following: In our case it means that "v" is a reference to same table as "t[index]", so any of these references can be used to set value of a field in that same table. Here is the code to illustrates that "name" field of sub-tables is indeed being set: local t = { {address = 0x11223344, flags = gg.TYPE_DWORD, value = 0}, {address = 0x11223348, flags = gg.TYPE_DWORD, value = 0} } for i, v in ipairs(t) do v.name = "Characters" end for i, v in ipairs(t) do print(i, t[i].name) end
  2. CmP

    addListItems with v.name

    You need to either filter the table returned by "getListItems" function via "deleting" (setting to nil) elements that have different name or build a new table only with elements that have desired name. Here is an example of implementing the first approach (first 5 lines of the code): How to remove named value in the save list? (#86ip1n3c)
  3. Byte value of 0xB8 is -72 in decimal if you interpret it as signed byte and 184 if you interpret is as unsigned byte, so these are just different interpretations of the same value. Just convert them to hexadecimal and extract byte values from the result. I have no idea why it is so hard to understand. Example: convert 12345 decimal value to bytes. 1. 12345 = 0x3039 2. Byte values are 0x30 and 0x39 (to be searched in this order) or 48 and 57 in decimal.
  4. Yes, you have everything that is needed to find the value and to modify it to any other (in allowed range). To search for 3000 try search string "11;184::2" with type "Byte". If there will be more than 2 results, you will need to do refine search by changing the value in the game and searching the new value the same way. For example, if the new value is 2500, you will need to use the following search string "9;196::2".
  5. More like you need to find out the values of first and seconds bytes that together correspond to the value you need. The following code may work for values in range [0;32767]: local value = 3000 local firstByte = value % 256 local secondByte = (value >> 8) % 256 local searchString = string.format("%d;%d::2", secondByte, firstByte) print(searchString) -- 11;184::2 As you see, this is slightly incorrect. That would be correct for value 3003. Also you may want ordered group search like in my example in which case you need to search for bytes in the correct order.
  6. The values for bytes that I provided are hexadecimal. So with 10 I meant 0x10 (16) and with 27 I meant 0x27 (39). Try them. Also from your video it seems that bytes do not need to be swapped so ignore that step.
  7. Convert the value to hexadecimal and swap first byte with the second one. Example for 10000: 1. 10000 is 0x2710. 2. "27 10" after swap is "10 27".
  8. Possibly that the bytes are simply reversed. 0x64 is 100. Try "00 01" to see the result. 256 to be expected.
  9. Incorrect search string for type "Dword". "searchNumber" function returns string in case of failure so it is possible to check whether function completed successfully: local ret = gg.searchNumber("1.000", gg.TYPE_DWORD) if type(ret) == "string" then print("Error: " .. ret) else print("Success") end
  10. If there are results in results list, "searchNumber" function performs refine search. For new search don't forget to call "clearResults" function before calling "searchNumber" function. Second search happens instantly after the first one and only results from the first search are used to search in, that's why you get 0 results after both searches.
  11. Demonstration of work.mp4
  12. Then just use "value" field of one structure as "address" field of other structure. For example: local ptr = {{address = 0x11223348, flags = gg.TYPE_QWORD}} ptr = gg.getValues(ptr) -- Getting value of a pointer local val = {{address = ptr[1].value, flags = gg.TYPE_DWORD}} -- Using pointer value as address val = gg.getValues(val) print("Pointer at address " .. ptr[1].address .. " points to the value " .. val[1].value .. " at address " .. val[1].address)
  13. CmP

    Lua Script Help

    @MonkeySAN you probably forgot to end the loop before calling "setValues" function. It doesn't need to be called in loop, just once after it instead.
  14. CmP

    Looping issue

    Since "searchNumber" function expects a string as it's first argument, numeric value is converted to string before it is used to determine what to search for. Test code for your case from the video: local value = 0.1 for i = 1, 9 do print(value) value = value + 0.1 end Code execution result: The problem should be obvious now. The solution is to not rely on automatic number to string conversion unless you are sure that it's result will be equal to what you expect.
  15. CmP

    Looping issue

    Just as @MonkeySAN mentioned, you don't need to guess whether anything was found and replaced. Instead it is enough to add logging to the code to find that out: loop = 0.1 for i = 0, 98 do print(string.format("Searching: %.15f", loop)) gg.searchNumber(loop, gg.TYPE_DOUBLE) local found = gg.getResultsCount() print(string.format("Found: %d", found)) gg.getResults(found) local edited = gg.editAll(500, gg.TYPE_DOUBLE) print(string.format("Edited: %d", edited)) gg.clearResults() loop = loop + 0.1 end This way you would see how many results were found and edited and it wouldn't be needed to guess anything.
  16. Strangely enough, it seems that the instructions are still read from process memory after they have been executed once, but after some more executions of the instructions, they are indeed "cached" and are no longer read from memory. I figured that out from several observations, but I don't know how this mechanism of instructions "caching" really works in libhoudini or other translation solutions.
  17. Firstly, since we are dealing with bitwise operations, it is reasonable to convert all values to hex: Anti-cheat 1 = 0x50D00B6E Anti-cheat 2 = 0x120B5C6E Real value = 0x428C0000 Now let's define new values that are derived from these "anti-cheat" values: Key1 = Anti-cheat 1 = 0x50D00B6E Key2 = Anti-cheat 2 with 2nd and 3rd bytes swapped = 0x125C0B6E Real value can then be calculated from previously defined values like this: Real value = Key1 XOR Key2 Real value = 0x50D00B6E XOR 0x125C0B6E = 0x428C0000 Following the same steps for this example: Anti-cheat 1 = 0x50015F1D Anti-cheat 2 = 0x135F511D Real value = 0x43500000 Key1 = 0x50015F1D Key2 = 0x13515F1D Real value = 0x50015F1D XOR 0x13515F1D = 0x43500000
  18. Variable "lastIndex" indicates index of the last element of the table that will be edited, meaning that up to first 5 values will be edited. It can be less than 5 when saved list has less values, but it won't be more than 5. The approach is same, just little modification to the code is needed. For example, code of the second example from my previous post can be modified this way: local items = gg.getListItems() local count = #items local firstIndex = 3 local lastIndex = 7 if lastIndex > count then lastIndex = count end local newItems = {} for i = firstIndex, lastIndex do local item = items[i] newItems[#newItems + 1] = {address = item.address, flags = item.flags, value = "12345"} end gg.setValues(newItems)
  19. There are multiple ways to achieve the same result. Either you can use table returned by "gg.getListItems" function and modify required fields before calling "gg.setValues" function with this table as argument or you can create a new table based on values from returned table, but with required fields having different values on your choice and then call "gg.setValues" function passing the newly created table to it as argument. Example of implementing the first way: local items = gg.getListItems() local count = #items local lastIndex = 5 if lastIndex > count then lastIndex = count end for i = 1, lastIndex do items[i].value = "12345" end for i = lastIndex + 1, count do items[i] = nil end gg.setValues(items) Example of implementing the second way: local items = gg.getListItems() local count = #items local lastIndex = 5 if lastIndex > count then lastIndex = count end local newItems = {} for i = 1, lastIndex do local item = items[i] newItems[i] = {address = item.address, flags = item.flags, value = "12345"} end gg.setValues(newItems)
  20. But there is no need to load saved values as search results in the first place. The same can be accomplished without such redundancy using "gg.setValues" function: local items = gg.getListItems() for i, v in ipairs(items) do if v.flags == gg.TYPE_FLOAT then v.value = "0.10000000149" end end gg.setValues(items)
  21. has which data type? If this is known of course. Can you get encrypted value (interpreted as dword) that corresponds to real value in game being 0?
  22. Even if encrypted value is interpreted as float by the game, one still needs to know exact values to be able to analyze how values in the pairs you provided are related. That's why you were asked to provide the values interpreted as dword.
  23. Alternatively to the solution above by ItsSC, the following function can be used to swap endianness of a string that represents 4-byte hex value: function swapEndianness(str) return (str:gsub('(..)(..)(..)(..)', '%4%3%2%1')) end
  24. Check if the following solution suffices for your case: How to goto a pointer in a script? (#7hphwlq4)
  25. In "offset" function: And right after the call to it: Instead of adding table of tables to "vPool" table, add just tables that contain info about a particular memory item. For example, in your code instead of addItem(vPool, r) do addItem(vPool, r[1])
×
×
  • 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.