├── BadCase's_GGIl2cpp_Toolbox_v1.0.0.lua └── README.md /BadCase's_GGIl2cpp_Toolbox_v1.0.0.lua: -------------------------------------------------------------------------------- 1 | script_title = "BadCase's (GGIl2cpp by Kruvcraft) Toolbox" 2 | bc = { 3 | Toast = function(toast_string, emoji) 4 | local _ = utf8.char(9552) 5 | gg.toast(script_title .. "\n\n" .. emoji .. _ .. _ .. _ .. _ .. _ .. _ .. _ .. _ .. _ .. _ 6 | .. _ .. _ .. _ .. emoji .. "\n\n" .. toast_string .. "\n\n" .. emoji .. _ .. _ 7 | .. _ .. _ .. _ .. _ .. _ .. _ .. _ .. _ .. _ .. _ .. _ .. emoji) 8 | end, 9 | Alert = function(headerString, bodyString, emoji) 10 | if #bodyString > 0 then 11 | gg.alert(script_title .. "\n\n" .. emoji .. " " .. headerString .. " " .. emoji .. "\n\n" .. bodyString) 12 | else 13 | gg.alert(script_title .. "\n\n" .. emoji .. " " .. headerString .. " " .. emoji) 14 | end 15 | end, 16 | Choice = function(headerString, bodyString, emoji) 17 | if #bodyString > 0 then 18 | return script_title .. "\n\n" .. emoji .. " " .. headerString .. " " .. emoji .. "\n\n" .. bodyString 19 | else 20 | return script_title .. "\n\n" .. emoji .. " " .. headerString .. " " .. emoji 21 | end 22 | end, 23 | Prompt = function(headerString, emoji) 24 | return script_title .. "\n\n" .. emoji .. " " .. headerString .. " " .. emoji 25 | end 26 | } 27 | 28 | local file = io.open('Il2cppApi.lua',"r") 29 | 30 | local update = false 31 | 32 | if file ~= nil then 33 | local updateMenu = gg.choice({ 34 | "✅ Yes", 35 | "❌ No" 36 | }, 37 | nil, 38 | bc.Choice("Update GGIl2cpp", "Do you want to download the latest version of GGIl2cpp?", "ℹ️") 39 | ) 40 | if updateMenu ~= nil and updateMenu == 1 then 41 | update = true 42 | end 43 | end 44 | 45 | if file == nil or update == true then 46 | bc.Alert("GGIl2cpp Download", "Press Yes on the next screen to download GGIl2cpp, the script will not work without it.", "ℹ️") 47 | os.rename("Il2cppApi.lua","Il2cppApi.old.lua") 48 | io.open("Il2cppApi.lua","w+"):write(gg.makeRequest("https://raw.githubusercontent.com/kruvcraft21/GGIl2cpp/master/build/Il2cppApi.lua").content):close() 49 | end 50 | 51 | require('Il2cppApi') 52 | Il2cpp() 53 | 54 | arch = gg.getTargetInfo() 55 | 56 | ggil2cppFrontend = { 57 | home = function() 58 | local checkSaveList = gg.getSelectedListItems() 59 | if #checkSaveList > 0 then 60 | ggil2cppFrontend.handleClick() 61 | else 62 | local options = { 63 | "FindClass", 64 | "FindMethods", 65 | "FindFields", 66 | "FindObject", 67 | "PatchesAddress", 68 | "Search", 69 | "ScriptCreator" 70 | } 71 | local optionsMenu = { 72 | "➡️ FindClass", 73 | "➡️ FindMethods", 74 | "➡️ FindFields", 75 | "➡️ FindObject", 76 | "➡️ PatchesAddress", 77 | "🔍 Keyword Search", 78 | "⚙️ Script Creator", 79 | "❌ Exit" 80 | } 81 | local menu = gg.choice( 82 | optionsMenu, 83 | nil, 84 | bc.Choice("Main Menu", "Select a function.", "ℹ️") 85 | ) 86 | if menu ~= nil then 87 | if menu == #optionsMenu then 88 | os.exit() 89 | end 90 | _G["ggil2cppFrontend"][options[menu]]() 91 | end 92 | end 93 | end, 94 | mySplit = function(inputstr, sep) 95 | sep = sep or "%s" 96 | local t = {} 97 | for field, s in string.gmatch(inputstr, "([^" .. sep .. "]*)(" .. sep .. "?)") do 98 | table.insert(t, field) 99 | if s == "" then 100 | end 101 | end 102 | return t 103 | end, 104 | Search = function() 105 | ggil2cppEdits.getGlobalMetadataStrings() 106 | ggil2cppEdits.searchMenu() 107 | end, 108 | ScriptCreator = function() 109 | scriptCreator.scriptMenu() 110 | end, 111 | retrievedClasses = {}, 112 | FindClass = function() 113 | local menu = gg.prompt({ 114 | bc.Prompt("FindClass Menu", "ℹ️") .. "\nEnter Class names or addresses seperated by commas. (ClassName1,0xFFFFFFFF)", 115 | "Dump Methods", 116 | "Dump Fields" 117 | }, { 118 | "", 119 | true, 120 | true 121 | }, { 122 | "text", 123 | "checkbox", 124 | "checkbox" 125 | }) 126 | if menu ~= nil then 127 | local classesTable = ggil2cppFrontend.mySplit(menu[1], ",") 128 | local classesTableStatic = ggil2cppFrontend.mySplit(menu[1], ",") 129 | for i, v in pairs(classesTable) do 130 | if v:find("^0x") then 131 | classesTable[i] = tonumber(classesTable[i]) 132 | end 133 | end 134 | local tempTable = {} 135 | for i, v in pairs(classesTable) do 136 | tempTable[i] = { 137 | Class = v, 138 | MethodsDump = menu[2], 139 | FieldsDump = menu[3] 140 | } 141 | end 142 | local result = Il2cpp.FindClass(tempTable) 143 | local tempTable = {} 144 | for index, value in pairs(result) do 145 | for i, v in pairs(value) do 146 | ggil2cppFrontend.retrievedClasses[classesTableStatic[index]] = v 147 | tempTable[i] = { 148 | address = tonumber(v.ClassAddress, 16), 149 | flags = gg.TYPE_DWORD, 150 | name = "Class: " .. classesTableStatic[index] .. "\n" .. tostring(v) 151 | } 152 | end 153 | end 154 | gg.addListItems(tempTable) 155 | bc.Alert("Classes Added ", #tempTable .. " Classes added to the Save List.", "ℹ️") 156 | end 157 | end, 158 | retrievedMethods = {}, 159 | FindMethods = function(methodNames) 160 | local menu = gg.prompt({ 161 | bc.Prompt("FindMethods Menu", "ℹ️") .. "\nEnter Method names or offsets seperated by commas. (MethodName1,0xFFFF)" 162 | }, { 163 | methodNames 164 | }, { 165 | "text" 166 | }) 167 | if menu ~= nil then 168 | local methodsTable = ggil2cppFrontend.mySplit(menu[1], ",") 169 | for i, v in pairs(methodsTable) do 170 | if v:find("^0x") then 171 | methodsTable[i] = tonumber(methodsTable[i]) 172 | end 173 | end 174 | local result = Il2cpp.FindMethods(methodsTable) 175 | local tempTable = {} 176 | for index, value in pairs(result) do 177 | for i, v in pairs(value) do 178 | ggil2cppFrontend.retrievedMethods[#ggil2cppFrontend.retrievedMethods + 1] = v 179 | local prepName = "[" .. #ggil2cppFrontend.retrievedMethods .. "]\n" 180 | for k, val in pairs(v) do 181 | prepName = prepName .. "\n" .. k .. ": " .. tostring(val) 182 | end 183 | tempTable[i] = { 184 | address = tonumber(v.AddressInMemory, 16), 185 | flags = gg.TYPE_DWORD, 186 | name = prepName 187 | } 188 | end 189 | end 190 | gg.addListItems(tempTable) 191 | bc.Alert("Methods Added ", #tempTable .. " Methods added to the Save List.", "ℹ️") 192 | end 193 | end, 194 | retrievedFields = {}, 195 | FindFields = function(fieldNames) 196 | local menu = gg.prompt({ 197 | bc.Prompt("FindFields Menu", "ℹ️") .. "\nEnter Field names or addresses seperated by commas. (FieldName1,0xFFFFFFFF)" 198 | }, 199 | fieldNames, 200 | { 201 | "text" 202 | }) 203 | if menu ~= nil then 204 | local fieldsTable = ggil2cppFrontend.mySplit(menu[1], ",") 205 | local result = Il2cpp.FindFields(fieldsTable) 206 | local tempTable = {} 207 | for index, value in pairs(result) do 208 | for i, v in pairs(value) do 209 | ggil2cppFrontend.retrievedFields[#ggil2cppFrontend.retrievedFields + 1] = v 210 | local prepName = "[" .. #ggil2cppFrontend.retrievedFields .. "]\n" 211 | for k, val in pairs(v) do 212 | prepName = prepName .. "\n" .. k .. ": " .. tostring(val) 213 | end 214 | tempTable[i] = { 215 | address = tonumber(v.ClassAddress, 16), 216 | flags = gg.TYPE_DWORD, 217 | name = prepName 218 | } 219 | end 220 | end 221 | gg.addListItems(tempTable) 222 | bc.Alert("Fields Added ", #tempTable .. " Fields added to the Save List.", "ℹ️") 223 | end 224 | end, 225 | FindObject = function() 226 | local menu = gg.prompt({ 227 | bc.Prompt("FindObject Menu", "ℹ️") .. "\nEnter Class names or addresses seperated by commas. (ClassName1,0xFFFFFFFF)" 228 | }, { 229 | "" 230 | }, { 231 | "text" 232 | }) 233 | if menu ~= nil then 234 | local classesTable = ggil2cppFrontend.mySplit(menu[1], ",") 235 | local classesTableStatic = ggil2cppFrontend.mySplit(menu[1], ",") 236 | for i, v in pairs(classesTable) do 237 | if v:find("^0x") then 238 | classesTable[i] = tonumber(classesTable[i]) 239 | end 240 | end 241 | local result = Il2cpp.FindObject(classesTable) 242 | local tempTable = {} 243 | for index, value in pairs(result) do 244 | for i, v in pairs(value) do 245 | tempTable[i] = { 246 | address = v.address, 247 | flags = gg.TYPE_DWORD, 248 | name = "Class Instance: " .. classesTableStatic[index] 249 | } 250 | end 251 | end 252 | gg.addListItems(tempTable) 253 | bc.Alert("Instances Added ", #tempTable .. " Class instances added to Save List.", "ℹ️") 254 | end 255 | end, 256 | PatchesAddress = function(className, methodName) 257 | local edit 258 | local createEdit = gg.choice({ 259 | "✅ Yes", 260 | "❌ No" 261 | }, 262 | nil, 263 | bc.Choice("Create Edit", "Do you want to create a hex edit first?", "ℹ️") 264 | ) 265 | if createEdit ~= nil then 266 | if createEdit == 1 then 267 | edit = ggil2cppEdits.createEdit() 268 | end 269 | end 270 | local menu = gg.prompt({ 271 | bc.Prompt("PatchesAddress Menu", "ℹ️") .. "\nEnter Class Name", 272 | "Enter Method Name", 273 | "Value To Patch (\\x20\\x00\\x80\\x52\\xc0\\x03\\x5f\\xd6)" 274 | }, { 275 | className, 276 | methodName, 277 | edit 278 | }, { 279 | "text", 280 | "text", 281 | "text"} 282 | ) 283 | if menu ~= nil then 284 | local Method1 = Il2cpp.FindMethods({menu[2]})[1] 285 | local s = menu[3] 286 | s = s:gsub("\\x(%x%x)", function(x) 287 | return string.char(tonumber(x, 16)) 288 | end) 289 | for k, v in ipairs(Method1) do 290 | if v.ClassName == menu[1] then 291 | ggil2cppFrontend.createRestore(tonumber(v.AddressInMemory, 16), #s) 292 | Il2cpp.PatchesAddress(tonumber(v.AddressInMemory, 16), s) 293 | end 294 | end 295 | end 296 | end, 297 | restoreTable = {}, 298 | restoreValues = function(address) 299 | gg.setValues(ggil2cppFrontend.restoreTable[tostring(address)]) 300 | ggil2cppFrontend.restoreTable[tostring(address)] = nil 301 | end, 302 | createRestore = function(address, byteCount) 303 | ::create:: 304 | if not ggil2cppFrontend.restoreTable[tostring(address)] or ggil2cppFrontend.restoreTable[tostring(address)] == nil then 305 | local tempTable = {} 306 | local offset = 0 307 | for i = 1, byteCount do 308 | tempTable[i] = { 309 | address = address + offset, 310 | flags = gg.TYPE_BYTE 311 | } 312 | offset = offset + 1 313 | end 314 | tempTable = gg.getValues(tempTable) 315 | ggil2cppFrontend.restoreTable[tostring(address)] = tempTable 316 | elseif #ggil2cppFrontend.restoreTable[tostring(address)] < byteCount then 317 | ggil2cppFrontend.restoreValues(address) 318 | goto create 319 | end 320 | end, 321 | handleClick = function() 322 | local saveList = gg.getSelectedListItems() 323 | local classes = {} 324 | local classInstances = {} 325 | local fields = {} 326 | local methods = {} 327 | local instanceFields = {} 328 | for i, v in pairs(saveList) do 329 | if v.name:find("Class:") then 330 | table.insert(classes, v) 331 | end 332 | if v.name:find("Class Instance:") then 333 | table.insert(classInstances, v) 334 | end 335 | if v.name:find("MethodName") then 336 | table.insert(methods, v) 337 | end 338 | if v.name:find("FieldName") then 339 | table.insert(fields, v) 340 | end 341 | if v.name:find("Instance Header:") then 342 | table.insert(instanceFields, v) 343 | end 344 | end 345 | local menu = gg.choice({ 346 | "➡️ Classes (" .. ggil2cppFrontend.menuCount(classes) .. ")", 347 | "➡️ Class Instances (" .. ggil2cppFrontend.menuCount(classInstances) .. ")", 348 | "➡️ Methods (" .. ggil2cppFrontend.menuCount(methods) .. ")", 349 | "➡️ Fields (" .. ggil2cppFrontend.menuCount(fields) .. ")", 350 | "➡️ Instance Fields (" .. ggil2cppFrontend.menuCount(instanceFields) .. ")" 351 | }, 352 | nil, 353 | bc.Choice("Save List Menu", "Select type of value to handle.", "ℹ️") 354 | ) 355 | if menu ~= nil then 356 | if menu == 1 then 357 | ggil2cppFrontend.classMenu(classes) 358 | end 359 | if menu == 2 then 360 | ggil2cppFrontend.classInstanceMenu(classInstances) 361 | end 362 | if menu == 3 then 363 | ggil2cppFrontend.methodMenu(methods) 364 | end 365 | if menu == 4 then 366 | ggil2cppFrontend.fieldMenu(fields) 367 | end 368 | if menu == 5 then 369 | ggil2cppFrontend.instanceFieldMenu(instanceFields) 370 | end 371 | end 372 | end, 373 | menuCount = function(countTable) 374 | if countTable ~= nil and #countTable > 0 then 375 | return #countTable 376 | else 377 | return "❌" 378 | end 379 | end, 380 | instanceFieldMenu = function(instanceTable) 381 | local menu = gg.choice({ 382 | "✅ Yes", 383 | "❌ No" 384 | }, 385 | nil, 386 | bc.Choice("Remove Instances", "Remove fields for these instances from Save List?", "ℹ️") 387 | ) 388 | if menu ~= nil and menu == 1 then 389 | local saveList = gg.getListItems() 390 | for i, v in pairs(instanceTable) do 391 | local address = v.name:gsub(".+(Instance Header: .+)", "%1") 392 | for index, value in pairs(saveList) do 393 | if value.name:find(address) then 394 | saveList[index] = nil 395 | end 396 | end 397 | end 398 | gg.clearList() 399 | gg.addListItems(saveList) 400 | end 401 | end, 402 | classMenu = function(classTable) 403 | local menuItems = {} 404 | local classesTable = {} 405 | for i, v in pairs(classTable) do 406 | local className = v.name:gsub("Class: ([A-Za-z0-9]+).+", "%1") 407 | menuItems[i] = className 408 | classesTable[i] = ggil2cppFrontend.retrievedClasses[className] 409 | end 410 | local menu = gg.choice( 411 | menuItems, 412 | nil, 413 | bc.Choice("Class Selection Menu", "Select a Class.", "ℹ️") 414 | ) 415 | if menu ~= nil then 416 | local classOptions = gg.choice({ 417 | "📋 Copy Data", 418 | "➡️ Methods (" .. ggil2cppFrontend.menuCount(classesTable[menu].Methods) .. ")", 419 | "➡️ Fields (" .. ggil2cppFrontend.menuCount(classesTable[menu].Fields) .. ")", 420 | "⚙️ Create Script Edit/Function" 421 | }, 422 | nil, 423 | bc.Choice("Class Menu", "Select an option.", "ℹ️") 424 | ) 425 | if classOptions ~= nil then 426 | if classOptions == 1 then 427 | gg.copyText(classTable[menu].name) 428 | end 429 | if classOptions == 2 then 430 | local classMethodsMenuItems = {} 431 | for i, v in pairs(classesTable[menu].Methods) do 432 | classMethodsMenuItems[i] = v.ReturnType .. " " .. v.MethodName 433 | end 434 | local classMethodsMenu = gg.choice( 435 | classMethodsMenuItems, 436 | nil, 437 | bc.Choice("Method Selection Menu", "Select a Method.", "ℹ️") 438 | ) 439 | if classMethodsMenu ~= nil then 440 | local doWithMenu = gg.choice({ 441 | "➡️ Load Methods with name to Save List", 442 | "⚙️ Edit Method" 443 | }, 444 | nil, 445 | bc.Choice("Method Menu", "Select an option.", "ℹ️") 446 | ) 447 | if doWithMenu ~= nil then 448 | if doWithMenu == 1 then 449 | ggil2cppFrontend.FindMethods(classesTable[menu].Methods[classMethodsMenu].MethodName) 450 | end 451 | if doWithMenu == 2 then 452 | ggil2cppFrontend.PatchesAddress(classesTable[menu].ClassName, classesTable[menu].Methods[classMethodsMenu].MethodName) 453 | end 454 | end 455 | end 456 | end 457 | if classOptions == 3 then 458 | local classFieldsMenuItems = {} 459 | for i, v in pairs(classesTable[menu].Fields) do 460 | classFieldsMenuItems[i] = v.Offset .. " " .. v.Type .. " " .. v.FieldName 461 | end 462 | local classFieldsMenu = gg.choice( 463 | classFieldsMenuItems, 464 | nil, 465 | bc.Choice("Field Selection Menu", "Select a Field.", "ℹ️") 466 | ) 467 | if classFieldsMenu ~= nil then 468 | local doWithMenu = gg.choice({ 469 | "➡️ Load Fields with name to Save List", 470 | "➡️ Load all instances of Class and Field to Save List" 471 | }, 472 | nil, 473 | bc.Choice("Field Menu", "Select an option.", "ℹ️") 474 | ) 475 | if doWithMenu ~= nil then 476 | if doWithMenu == 1 then 477 | ggil2cppFrontend.FindFields(classesTable[menu].Fields[classFieldsMenu].FieldName) 478 | end 479 | if doWithMenu == 2 then 480 | local result = Il2cpp.FindObject({classesTable[menu].ClassName})[1] 481 | local tempTable = {} 482 | for i, v in pairs(result) do 483 | tempTable[#tempTable + 1] = { 484 | address = v.address, 485 | flags = gg.TYPE_DWORD, 486 | name = "Class Instance: " .. classesTable[menu].ClassName 487 | } 488 | tempTable[#tempTable + 1] = { 489 | address = v.address + tonumber(classesTable[menu].Fields[classFieldsMenu].Offset, 16), 490 | flags = gg.TYPE_DWORD, 491 | name = "Field Name: " .. classesTable[menu].Fields[classFieldsMenu].FieldName .. 492 | "\nOffset: " .. classesTable[menu].Fields[classFieldsMenu].Offset .. 493 | "\nInstance Header: " .. v.address 494 | } 495 | end 496 | gg.addListItems(tempTable) 497 | bc.Alert("Instances Added ", #tempTable .. " Class and Field instances added to Save List.", "ℹ️") 498 | end 499 | end 500 | end 501 | end 502 | if classOptions == 4 then 503 | scriptCreator.handleClass(classesTable[menu]) 504 | end 505 | end 506 | end 507 | end, 508 | classInstanceMenu = function(classInstanceTable) 509 | local menu = gg.choice({ 510 | "➡️ Load instance fields" 511 | }, 512 | nil, 513 | bc.Choice("Class Instance Menu", "", "ℹ️") 514 | ) 515 | if menu ~= nil then 516 | local classes = {} 517 | local headers = {} 518 | for i, v in pairs(classInstanceTable) do 519 | headers[i] = v.address 520 | classes[v.name:gsub("Class Instance: (.+)", "%1")] = v.address 521 | end 522 | local fixedClasses = {} 523 | for k, v in pairs(classes) do 524 | table.insert(fixedClasses, k) 525 | end 526 | local tempTable = {} 527 | for i, v in pairs(fixedClasses) do 528 | tempTable[i] = { 529 | Class = v, 530 | MethodsDump = false, 531 | FieldsDump = true 532 | } 533 | end 534 | local result = Il2cpp.FindClass(tempTable) 535 | local tempTable = {} 536 | for index, value in pairs(result) do 537 | for i, v in pairs(value[1].Fields) do 538 | for ind, val in pairs(headers) do 539 | table.insert(tempTable, { 540 | address = val + tonumber(v.Offset, 16), 541 | flags = gg.TYPE_DWORD, 542 | name = "Field Name: " .. v.FieldName .. 543 | "\nOffset: " .. v.Offset .. 544 | "\nInstance Header: " .. val 545 | }) 546 | end 547 | end 548 | end 549 | gg.addListItems(tempTable) 550 | bc.Alert("Field Values Added ", #tempTable .. " Field values added to Save List.", "ℹ️") 551 | end 552 | end, 553 | methodMenu = function(methodTable) 554 | local menuItems = {} 555 | local methodsTable = {} 556 | for i, v in pairs(methodTable) do 557 | local methodIndex = v.name:gsub("^.([0-9]+).+", "%1") 558 | methodIndex = tonumber(methodIndex) 559 | methodsTable[i] = ggil2cppFrontend.retrievedMethods[methodIndex] 560 | menuItems[i] = methodsTable[i].MethodName 561 | end 562 | local mainMenu = gg.choice( 563 | menuItems, 564 | nil, 565 | bc.Choice("Method Selection Menu", "Select a Method.", "ℹ️") 566 | ) 567 | if mainMenu ~= nil then 568 | local mainMenuItems = {"📋 Copy Data", "⚙️ Edit Method", "⚙️ Create Script Edit/Function"} 569 | if ggil2cppFrontend.restoreTable[tostring(tonumber(methodsTable[mainMenu].AddressInMemory, 16))] then 570 | mainMenuItems[4] = "Restore Original Values" 571 | end 572 | local menu = gg.choice( 573 | mainMenuItems, 574 | nil, 575 | bc.Choice("Method Menu", "Select an option.", "ℹ️") 576 | ) 577 | if menu ~= nil then 578 | if menu == 1 then 579 | gg.copyText(methodTable[mainMenu].name) 580 | end 581 | if menu == 2 then 582 | ggil2cppFrontend.PatchesAddress(methodsTable[mainMenu].ClassName, methodsTable[mainMenu].MethodName) 583 | end 584 | if menu == 3 then 585 | local tempTable = {} 586 | local addToTable = scriptCreator.handleMethods({methodsTable[mainMenu]}) 587 | table.insert(tempTable, addToTable) 588 | scriptCreator.createFunction(tempTable) 589 | end 590 | if menu == 4 then 591 | ggil2cppFrontend.restoreValues(tonumber(methodsTable[mainMenu].AddressInMemory, 16)) 592 | bc.Alert("Values Restored", "Original values restored.", "ℹ️") 593 | end 594 | end 595 | end 596 | end, 597 | fieldMenu = function(fieldTable) 598 | local menuItems = {} 599 | local fieldsTable = {} 600 | for i, v in pairs(fieldTable) do 601 | local fieldIndex = v.name:gsub("^.([0-9]+).+", "%1") 602 | fieldIndex = tonumber(fieldIndex) 603 | fieldsTable[i] = ggil2cppFrontend.retrievedFields[fieldIndex] 604 | menuItems[i] = fieldsTable[i].FieldName 605 | end 606 | local mainMenu = gg.choice( 607 | menuItems, 608 | nil, 609 | bc.Choice("Field Selection Menu", "Select a Field.", "ℹ️") 610 | ) 611 | if mainMenu ~= nil then 612 | local menu = gg.choice({ 613 | "📋 Copy Data", 614 | "➡️ Get Field Instances", 615 | "⚙️ Create Script Edit/Function" 616 | }, 617 | nil, 618 | bc.Choice("Field Menu", "Select an option.", "ℹ️") 619 | ) 620 | if menu ~= nil then 621 | if menu == 1 then 622 | gg.copyText(fieldTable[mainMenu].name) 623 | end 624 | if menu == 2 then 625 | local result = Il2cpp.FindObject({fieldsTable[mainMenu].ClassName})[1] 626 | for i, v in pairs(result) do 627 | result[i].address = result[i].address + tonumber(fieldsTable[mainMenu].Offset, 16) 628 | end 629 | gg.loadResults(result) 630 | bc.Alert("Field Instances Added ", #result .. " Field instance added to Search Tab.", "ℹ️") 631 | end 632 | if menu == 3 then 633 | local tempTable = {} 634 | local addToTable = scriptCreator.handleFields({fieldsTable[mainMenu]}) 635 | table.insert(tempTable, addToTable) 636 | scriptCreator.createFunction(tempTable) 637 | end 638 | end 639 | end 640 | end 641 | } 642 | ggil2cppEdits = { 643 | searchMenu = function() 644 | local searchPrompt = gg.prompt({ 645 | bc.Prompt("Search Menu", "ℹ️") .. "\nEnter Keyword", 646 | "Secondary Keyword", 647 | "Case Sensitive", 648 | "Search For Classes", 649 | "Search For Fields", 650 | "Search For Methods" 651 | }, { 652 | "", 653 | "", 654 | true, 655 | true, 656 | true, 657 | true 658 | }, { 659 | "text", 660 | "text", 661 | "checkbox", 662 | "checkbox", 663 | "checkbox", 664 | "checkbox" 665 | }) 666 | if searchPrompt ~= nil then 667 | local resultsTable = {} 668 | local resultsTable2 = {} 669 | local resultsTable3 = {} 670 | local fieldResultCount = 0 671 | local methodResultCount = 0 672 | local classResultCount = 0 673 | local multiChoiceValues = {} 674 | for i, v in pairs(ggil2cppEdits.globalMetadataStrings) do 675 | if searchPrompt[3] == false then 676 | local lowerSearch = string.lower(searchPrompt[1]) 677 | local lowerSearch2 = string.lower(searchPrompt[2]) 678 | local lowerString = string.lower(v) 679 | if lowerString:find(lowerSearch) and lowerString:find(lowerSearch2) then 680 | table.insert(resultsTable, v) 681 | table.insert(resultsTable2, v) 682 | if searchPrompt[4] == true then 683 | table.insert(resultsTable3, v) 684 | end 685 | multiChoiceValues[#multiChoiceValues + 1] = true 686 | end 687 | elseif v:find(searchPrompt[1]) and v:find(searchPrompt[2]) then 688 | table.insert(resultsTable, v) 689 | table.insert(resultsTable2, v) 690 | if searchPrompt[4] == true then 691 | table.insert(resultsTable3, v) 692 | end 693 | multiChoiceValues[#multiChoiceValues + 1] = true 694 | end 695 | end 696 | local results = gg.multiChoice (resultsTable, multiChoiceValues,"Uncheck values you do not want to search for.") 697 | if results ~= nil then 698 | local tempTable1 = {} 699 | local tempTable2 = {} 700 | local tempTable3 = {} 701 | for i,v in pairs (results) do 702 | table.insert(tempTable1, resultsTable[i]) 703 | table.insert(tempTable2, resultsTable[i]) 704 | table.insert(tempTable3, resultsTable[i]) 705 | end 706 | resultsTable = tempTable1 707 | resultsTable2 = tempTable2 708 | if searchPrompt[4] == true then 709 | resultsTable3 = tempTable3 710 | end 711 | end 712 | local classLimit = #resultsTable 713 | if searchPrompt[5] == true then 714 | local result = Il2cpp.FindFields(resultsTable) 715 | local tempTable = {} 716 | for index, value in pairs(result) do 717 | if not value.Error then 718 | for i, v in pairs(value) do 719 | fieldResultCount = fieldResultCount + 1 720 | table.insert(resultsTable3,v.ClassName) 721 | end 722 | end 723 | end 724 | end 725 | if searchPrompt[6] == true then 726 | local result = Il2cpp.FindMethods(resultsTable2) 727 | local tempTable = {} 728 | for index, value in pairs(result) do 729 | if not value.Error then 730 | for i, v in pairs(value) do 731 | methodResultCount = methodResultCount + 1 732 | table.insert(resultsTable3,v.ClassName) 733 | end 734 | end 735 | end 736 | end 737 | local classResultsTable = {} 738 | local classResultsAdded = {} 739 | for i, v in pairs(resultsTable3) do 740 | if not classResultsAdded[v] then 741 | classResultsAdded[v] = true 742 | classResultsTable[#classResultsTable + 1] = { 743 | Class = v, 744 | MethodsDump = true, 745 | FieldsDump = true 746 | } 747 | end 748 | end 749 | local result = Il2cpp.FindClass(classResultsTable) 750 | local tempTable = {} 751 | for index, value in pairs(result) do 752 | if not value.Error then 753 | for i, v in pairs(value) do 754 | if index <= classLimit then 755 | classResultCount = classResultCount + 1 756 | end 757 | ggil2cppFrontend.retrievedClasses[v.ClassName] = v 758 | tempTable[#tempTable + 1] = { 759 | address = tonumber(v.ClassAddress, 16), 760 | flags = gg.TYPE_DWORD, 761 | name = "Class: ".. v.ClassName .. "\n" .. tostring(v) 762 | } 763 | end 764 | end 765 | end 766 | gg.addListItems(tempTable) 767 | bc.Alert("Search Results", "Field Results ("..fieldResultCount..")\nMethod Results ("..methodResultCount..")\nClass Results (".. classResultCount..")\n"..#tempTable .. " Classes added to save list.", "ℹ️") 768 | end 769 | end, 770 | s_b_s = ":" .. string.char(0) .. "mscorlib.dll" .. string.char(0), 771 | e_b_s = "00h;00h;0~~0;0~~0;0~~0;00h;0~~0;00h;0~~0;00h;FFh;FFh::12", 772 | getMetadataStringsRange = function() 773 | gg.setRanges(gg.REGION_OTHER) 774 | gg.clearResults() 775 | ::try_ca:: 776 | gg.searchNumber(ggil2cppEdits.s_b_s, gg.TYPE_BYTE, false, gg.SIGN_EQUAL, nil, nil, 1) 777 | if gg.getResultsCount() == 0 and ca_range ~= true then 778 | ca_range = true 779 | gg.setRanges(gg.REGION_C_ALLOC) 780 | goto try_ca 781 | end 782 | if gg.getResultsCount() == 0 and ca_range == true then 783 | print("Global-Metadata Not Found") 784 | end 785 | local start_search = gg.getResults(1) 786 | gg.clearResults() 787 | ggil2cppEdits.range_start = start_search[1].address 788 | for i, v in pairs(gg.getRangesList()) do 789 | if v["start"] < ggil2cppEdits.range_start and v["end"] > ggil2cppEdits.range_start then 790 | metadata_end = v["end"] 791 | break 792 | end 793 | end 794 | gg.searchNumber(ggil2cppEdits.e_b_s, gg.TYPE_BYTE, false, gg.SIGN_EQUAL, ggil2cppEdits.range_start, nil, 1) 795 | local end_search = gg.getResults(1) 796 | ggil2cppEdits.range_end = end_search[1].address 797 | gg.clearResults() 798 | end, 799 | getGlobalMetadataStrings = function() 800 | if ggil2cppEdits.globalMetadataStrings then 801 | return 802 | else 803 | ggil2cppEdits.globalMetadataStrings = {} 804 | end 805 | ggil2cppEdits.getMetadataStringsRange() 806 | bc.Toast("Dumping String Data", "ℹ️") 807 | local dump_start = 0 808 | local dump_end = 0 809 | gg.dumpMemory(ggil2cppEdits.range_start, ggil2cppEdits.range_end, gg.EXT_STORAGE .. "/bc/", gg.DUMP_SKIP_SYSTEM_LIBS) 810 | for i, v in pairs(gg.getRangesList()) do 811 | if ggil2cppEdits.range_start > v.start and ggil2cppEdits.range_start < v["end"] then 812 | local dwordValueToHex = string.format('%x', v.start) 813 | if #dwordValueToHex == 8 or #dwordValueToHex == 10 or #dwordValueToHex == 12 then 814 | dump_start = dwordValueToHex 815 | else 816 | local sub = #dwordValueToHex / 2 817 | sub = tonumber("-" .. sub) 818 | dwordValueToHex = dwordValueToHex:sub(sub) 819 | dump_start = dwordValueToHex 820 | end 821 | local dwordValueToHex = string.format('%x', v["end"]) 822 | if #dwordValueToHex == 8 or #dwordValueToHex == 10 or #dwordValueToHex == 12 then 823 | dump_end = dwordValueToHex 824 | else 825 | local sub = #dwordValueToHex / 2 826 | sub = tonumber("-" .. sub) 827 | dwordValueToHex = dwordValueToHex:sub(sub) 828 | dump_end = dwordValueToHex 829 | end 830 | break 831 | end 832 | end 833 | local BUFSIZE = 4 ^ 13 834 | local f = io.input(gg.EXT_STORAGE .. "/bc/" .. gg.getTargetPackage() .. "-" .. dump_start .. "-" .. dump_end .. ".bin") 835 | local start_capture = false 836 | trimmed_content = "" 837 | local trim_until = 31886460 838 | local current_size = 0 839 | while true do 840 | local rest = f:read(BUFSIZE) 841 | current_size = current_size + 67108864 842 | if rest and string.find(rest, "mscorlib.dll.") then 843 | start_capture = true 844 | bc.Toast("Strings Found", "ℹ️") 845 | end 846 | if start_capture == true then 847 | if rest then 848 | trimmed_content = trimmed_content .. rest 849 | if current_size >= trim_until then 850 | trimmed_content = trimmed_content:gsub(".+(mscorlib.dll..+)", "%1") 851 | trimmed_content = string.sub(trimmed_content, 1, ggil2cppEdits.range_end - ggil2cppEdits.range_start) 852 | break 853 | end 854 | else 855 | trimmed_content = trimmed_content:gsub(".+(mscorlib.dll..+)", "%1") 856 | end 857 | end 858 | end 859 | ggil2cppEdits.globalMetadataStrings = ggil2cppFrontend.mySplit(trimmed_content, "\x00") 860 | trimmed_content = nil 861 | end, 862 | editSpace = gg.allocatePage(gg.PROT_READ | gg.PROT_WRITE, Il2cpp.globalMetadataEnd), 863 | createEdit = function() 864 | local menu_type = {"➡️ Boolean", "➡️ Integer", "➡️ Single (float)", "➡️ Double", "➡️ End Function"} 865 | local edit_type = gg.choice( 866 | menu_type, 867 | nil, 868 | bc.Choice("Select Type Of Edit", "", "ℹ️") 869 | ) 870 | if edit_type ~= nil then 871 | if edit_type == 1 then 872 | edits = ggil2cppEdits.getBoolEdit() 873 | end 874 | if edit_type == 2 then 875 | edits = ggil2cppEdits.getIntEdit() 876 | if arch.x64 then 877 | edits = {nil, ggil2cppEdits.setValues(ggil2cppEdits.editSpace, edits[2])} 878 | else 879 | edits = {ggil2cppEdits.setValues(ggil2cppEdits.editSpace, edits[1]), nil} 880 | end 881 | end 882 | if edit_type == 3 then 883 | local floatType = gg.choice({ 884 | "➡️ Exact Float (0 - 429503284)", 885 | "➡️ Simple Float (Single line edit)" 886 | }, 887 | nil, 888 | bc.Choice("Float Menu", "Select an option.", "ℹ️") 889 | ) 890 | if floatType ~= nil then 891 | if floatType == 1 then 892 | edits = ggil2cppEdits.getComplexFloatEdit("Single") 893 | if arch.x64 then 894 | edits = {nil, ggil2cppEdits.setValues(ggil2cppEdits.editSpace, edits[2])} 895 | else 896 | edits = {ggil2cppEdits.setValues(ggil2cppEdits.editSpace, edits[1]), nil} 897 | end 898 | end 899 | if floatType == 2 then 900 | edits = ggil2cppEdits.getSimpleFloatEdit() 901 | end 902 | end 903 | end 904 | if edit_type == 4 then 905 | edits = ggil2cppEdits.getComplexFloatEdit("Double") 906 | if arch.x64 then 907 | edits = {nil, ggil2cppEdits.setValues(ggil2cppEdits.editSpace, edits[2])} 908 | else 909 | edits = {ggil2cppEdits.setValues(ggil2cppEdits.editSpace, edits[1]), nil} 910 | end 911 | end 912 | end 913 | if edit_type == 5 then 914 | edits = {"\\x1E\\xFF\\x2F\\xE1", "\\xC0\\x03\\x5F\\xD6"} 915 | end 916 | if arch.x64 then 917 | return edits[2] 918 | else 919 | return edits[1] 920 | end 921 | end, 922 | setValues = function(address, edits) 923 | local address_table = {} 924 | local offset = 0 925 | local count = 1 926 | repeat 927 | address_table[count] = {} 928 | address_table[count].address = address + offset 929 | address_table[count].flags = gg.TYPE_DWORD 930 | address_table[count].value = edits[count] 931 | offset = offset + 4 932 | count = count + 1 933 | until (count == #edits + 1) 934 | gg.setValues(address_table) 935 | return ggil2cppEdits.getBytes(address, #address_table * 4) 936 | end, 937 | getBytes = function(address, numberOfBytes) 938 | local hexBytes = "" 939 | local offset = 0 940 | local bytesTable = {} 941 | for i = 1, numberOfBytes do 942 | bytesTable[i] = { 943 | address = address + offset, 944 | flags = gg.TYPE_BYTE 945 | } 946 | offset = offset + 1 947 | end 948 | bytesTable = gg.getValues(bytesTable) 949 | for i, v in pairs(bytesTable) do 950 | hexBytes = hexBytes .. "\\x" .. string.format('%02X', v.value):gsub("FFFFFFFFFFFFFF", "") 951 | end 952 | return hexBytes 953 | end, 954 | getBoolEdit = function() 955 | local arm7Edit = { 956 | isTrue = "\\x01\\x00\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 957 | isFalse = "\\x00\\x00\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1" 958 | } 959 | local arm8Edit = { 960 | isTrue = "\\x20\\x00\\x80\\x52\\xC0\\x03\\x5F\\xD6", 961 | isFalse = "\\x00\\x00\\x80\\x52\\xC0\\x03\\x5F\\xD6" 962 | } 963 | local menu = gg.choice({ 964 | "➡️ True", 965 | "➡️ False" 966 | }, 967 | nil, 968 | bc.Choice("Set Boolean Edit", "", "ℹ️") 969 | ) 970 | if menu ~= nil then 971 | if menu == 1 then 972 | return {arm7Edit.isTrue, arm8Edit.isTrue} 973 | end 974 | if menu == 2 then 975 | return {arm7Edit.isFalse, arm8Edit.isFalse} 976 | end 977 | end 978 | end, 979 | getIntEdit = function() 980 | local edits_arm7 = {} 981 | local edits_arm8 = {} 982 | ::set_val:: 983 | local menu = gg.prompt({ 984 | bc.Prompt("Enter Number -255 to 65535", "ℹ️") 985 | }, { 986 | }, { 987 | "number" 988 | }) 989 | if menu ~= nil then 990 | if tonumber(menu[1]) < -256 or tonumber(menu[1]) > 65535 then 991 | bc.Alert("Set A Valid Number", "Set a valid number from -255 to 65535.", "⚠️") 992 | goto set_val 993 | end 994 | if tonumber(menu[1]) == 0 then 995 | edits_arm8[1] = "~A8 MOV W0, WZR" 996 | else 997 | edits_arm8[1] = "~A8 MOV W0, #" .. menu[1] 998 | end 999 | edits_arm8[2] = "~A8 RET" 1000 | if menu[1]:find("[-]") then 1001 | edits_arm7[1] = "~A MVN R0, #" .. menu[1]:gsub("[-]", "") 1002 | edits_arm7[2] = "~A BX LR" 1003 | else 1004 | edits_arm7[1] = "~A MOVW R0, #" .. menu[1] 1005 | edits_arm7[2] = "~A BX LR" 1006 | end 1007 | return {edits_arm7, edits_arm8} 1008 | end 1009 | end, 1010 | getComplexFloatEdit = function(method_type) 1011 | local max_value = 429503284 1012 | ::set_value:: 1013 | local set_val = gg.prompt({ 1014 | bc.Prompt("Set " .. method_type .. " Value (Max " .. max_value .. ")", "ℹ️") 1015 | }, { 1016 | }, { 1017 | "number" 1018 | }) 1019 | if set_val ~= nil and tonumber(set_val[1]) <= max_value then 1020 | target = tonumber(set_val[1]) 1021 | local float_edits_arm7 = {} 1022 | local float_edits_arm8 = {} 1023 | if target <= 65535 and target >= 0 then 1024 | if method_type == "Single" then 1025 | float_edits_arm7[1] = "~A MOVW R0, #" .. target 1026 | float_edits_arm7[2] = "100A00EEr" -- VMOV S0, R0 1027 | float_edits_arm7[3] = "C00AB8EEr" -- VCVT.F32.S32 S0, S0 1028 | float_edits_arm7[4] = "100A10EEr" -- VMOV R0, S0 1029 | float_edits_arm7[5] = "1EFF2FE1r" -- BX LR 1030 | if target == 0 then 1031 | float_edits_arm8[1] = "~A8 MOV W0, WZR" 1032 | else 1033 | float_edits_arm8[1] = "~A8 MOV W0, #" .. target 1034 | end 1035 | float_edits_arm8[2] = "0000271Er" -- FMOV S0, W0 1036 | float_edits_arm8[3] = "00D8215Er" -- SCVTF S0, S0 1037 | float_edits_arm8[4] = "0000261Er" -- FMOV W0, S0 1038 | float_edits_arm8[5] = "C0035FD6r" -- RET 1039 | elseif method_type == "Double" then 1040 | float_edits_arm7[1] = "~A MOVW R0, #" .. target 1041 | float_edits_arm7[2] = "~A VMOV S0, R0" 1042 | float_edits_arm7[3] = "~A VCVT.F64.U32 D0, S0" 1043 | float_edits_arm7[4] = "~A VMOV R0, R1, D0" 1044 | float_edits_arm7[5] = "1EFF2FE1r" -- BX LR 1045 | if target == 0 then 1046 | float_edits_arm8[1] = "~A8 MOV W0, WZR" 1047 | else 1048 | float_edits_arm8[1] = "~A8 MOV W0, #" .. target 1049 | end 1050 | float_edits_arm8[2] = "~A8 SCVTF D0, W0" 1051 | float_edits_arm8[3] = "C0035FD6r" -- RET 1052 | end 1053 | end 1054 | if target <= 131072 and target >= 65537 then 1055 | float_val_2 = target - 65535 1056 | if method_type == "Single" then 1057 | float_edits_arm7[1] = "~A MOVW R0, #65535" 1058 | float_edits_arm7[2] = "~A MOVW R1, #" .. float_val_2 1059 | float_edits_arm7[3] = "010080E0r" -- ADD R0, R0, R1 1060 | float_edits_arm7[4] = "100A00EEr" -- VMOV S0, R0 1061 | float_edits_arm7[5] = "C00AB8EEr" -- VCVT.F32.S32 S0, S0 1062 | float_edits_arm7[6] = "100A10EEr" -- VMOV R0, S0 1063 | float_edits_arm7[7] = "1EFF2FE1r" -- BX LR 1064 | float_edits_arm8[1] = "~A8 MOV W0, #65535" 1065 | float_edits_arm8[2] = "~A8 MOV W1, #" .. float_val_2 1066 | float_edits_arm8[3] = "0000010Br" -- ADD W0, W0, W1 1067 | float_edits_arm8[4] = "0000271Er" -- FMOV S0, W0 1068 | float_edits_arm8[5] = "00D8215Er" -- SCVTF S0, S0 1069 | float_edits_arm8[6] = "0000261Er" -- FMOV W0, S0 1070 | float_edits_arm8[7] = "C0035FD6r" -- RET 1071 | elseif method_type == "Double" then 1072 | float_edits_arm7[1] = "~A MOVW R0, #65535" 1073 | float_edits_arm7[2] = "~A MOVW R1, #" .. float_val_2 1074 | float_edits_arm7[3] = "~A ADD R0, R0, R1" 1075 | float_edits_arm7[4] = "~A VMOV S0, R0" 1076 | float_edits_arm7[5] = "~A VCVT.F64.U32 D0, S0" 1077 | float_edits_arm7[6] = "~A VMOV R0, R1, D0" 1078 | float_edits_arm7[7] = "1EFF2FE1r" -- BX LR 1079 | float_edits_arm8[1] = "~A8 MOV W0, #65535" 1080 | float_edits_arm8[2] = "~A8 MOV W1, #" .. float_val_2 1081 | float_edits_arm8[3] = "~A8 ADD W0, W0, W1" 1082 | float_edits_arm8[4] = "~A8 SCVTF D0, W0" 1083 | float_edits_arm8[5] = "C0035FD6r" -- RET 1084 | end 1085 | end 1086 | if target > 131072 and target < 429503284 then 1087 | for i = 2, 65536 do 1088 | rem = target % i 1089 | mult = i 1090 | sub_total = rem * mult 1091 | add_to = target - sub_total 1092 | if add_to <= 65536 and add_to > 0 then 1093 | if method_type == "Single" then 1094 | float_edits_arm7[1] = "~A MOVW R0, #" .. rem 1095 | float_edits_arm7[2] = "~A MOVW R1, #" .. mult 1096 | float_edits_arm7[3] = "900100E0r" -- MUL R0, R0, R1 1097 | float_edits_arm7[4] = "~A MOVW R1, #" .. add_to 1098 | float_edits_arm7[5] = "010080E0r" -- ADD R0, R0, R1 1099 | float_edits_arm7[6] = "100A00EEr" -- VMOV S0, R0 1100 | float_edits_arm7[7] = "C00AB8EEr" -- VCVT.F32.S32 S0, S0 1101 | float_edits_arm7[8] = "100A10EEr" -- VMOV R0, S0 1102 | float_edits_arm7[9] = "1EFF2FE1r" -- BX LR 1103 | float_edits_arm8[1] = "~A8 MOV W0, #" .. rem 1104 | float_edits_arm8[2] = "~A8 MOV W1, #" .. mult 1105 | float_edits_arm8[3] = "007C011Br" -- MUL W0, W0, W1 1106 | float_edits_arm8[4] = "~A8 MOV W1, #" .. add_to 1107 | float_edits_arm8[5] = "0000010Br" -- ADD W0, W0, W1 1108 | float_edits_arm8[6] = "0000271Er" -- FMOV S0, W0 1109 | float_edits_arm8[7] = "00D8215Er" -- SCVTF S0, S0 1110 | float_edits_arm8[8] = "0000261Er" -- FMOV W0, S0 1111 | float_edits_arm8[9] = "C0035FD6r" -- RET 1112 | elseif method_type == "Double" then 1113 | float_edits_arm7[1] = "~A MOVW R0, #" .. rem 1114 | float_edits_arm7[2] = "~A MOVW R1, #" .. mult 1115 | float_edits_arm7[3] = "~A MUL R0, R0, R1" 1116 | float_edits_arm7[4] = "~A MOVW R1, #" .. add_to 1117 | float_edits_arm7[5] = "~A ADD R1, R0, R1" 1118 | float_edits_arm7[6] = "~A VMOV S0, R0" 1119 | float_edits_arm7[7] = "~A VCVT.F64.U32 D0, S0" 1120 | float_edits_arm7[8] = "~A VMOV R0, R1, D0" 1121 | float_edits_arm7[9] = "1EFF2FE1r" -- BX LR 1122 | float_edits_arm8[1] = "~A8 MOV W0, #" .. rem 1123 | float_edits_arm8[2] = "~A8 MOV W1, #" .. mult 1124 | float_edits_arm8[3] = "~A8 MUL W0, W0, W1" 1125 | float_edits_arm8[4] = "~A8 MOV W1, #" .. add_to 1126 | float_edits_arm8[5] = "~A8 ADD W0, W0, W1" 1127 | float_edits_arm8[6] = "~A8 SCVTF D0, W0" 1128 | float_edits_arm8[7] = "C0035FD6r" -- RET 1129 | end 1130 | break 1131 | end 1132 | end 1133 | end 1134 | if float_edits_arm7 and float_edits_arm8 then 1135 | return {float_edits_arm7, float_edits_arm8} 1136 | end 1137 | elseif target > 429503283 then 1138 | bc.Alert("Value Is Too High", "Set lower than 429503283.", "⚠️") 1139 | goto set_value 1140 | elseif target < 0 then 1141 | bc.Alert("Value Is Too Low", "Set to 0 or higher.", "⚠️") 1142 | goto set_value 1143 | end 1144 | end, 1145 | simpleFloatsTable = { 1146 | ["ARM7"] = { 1147 | { 1148 | ["hex_edits"] = "\\x01\\x01\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1149 | ["float_value"] = 2 1150 | }, { 1151 | ["hex_edits"] = "\\x41\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1152 | ["float_value"] = 8 1153 | }, { 1154 | ["hex_edits"] = "\\42\\04\\A0\\E3\\x1E\\xFF\\x2F\\xE1", 1155 | ["float_value"] = 32 1156 | }, { 1157 | ["hex_edits"] = "\\x43\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1158 | ["float_value"] = 128 1159 | }, { 1160 | ["hex_edits"] = "\\x11\\x03\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1161 | ["float_value"] = 512 1162 | }, { 1163 | ["hex_edits"] = "\\x45\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1164 | ["float_value"] = 2048 1165 | }, { 1166 | ["hex_edits"] = "\\x46\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1167 | ["float_value"] = 8192 1168 | }, { 1169 | ["hex_edits"] = "\\x47\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1170 | ["float_value"] = 32768 1171 | }, { 1172 | ["hex_edits"] = "\\x12\\x03\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1173 | ["float_value"] = 131072 1174 | }, { 1175 | ["hex_edits"] = "\\x49\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1176 | ["float_value"] = 524288 1177 | }, { 1178 | ["hex_edits"] = "\\x05\\x02\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1179 | ["float_value"] = 8589934592 1180 | }, { 1181 | ["hex_edits"] = "\\x51\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1182 | ["float_value"] = 34359738368 1183 | }, { 1184 | ["hex_edits"] = "\\x52\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1185 | ["float_value"] = 137438953472 1186 | }, { 1187 | ["hex_edits"] = "\\x53\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1188 | ["float_value"] = 549755813888 1189 | }, { 1190 | ["hex_edits"] = "\\x15\\x03\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1191 | ["float_value"] = 2199023255552 1192 | }, { 1193 | ["hex_edits"] = "\\x55\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1194 | ["float_value"] = 8796093022208 1195 | }, { 1196 | ["hex_edits"] = "\\x56\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1197 | ["float_value"] = 35184372088832 1198 | }, { 1199 | ["hex_edits"] = "\\x57\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1200 | ["float_value"] = 140737488355328 1201 | }, { 1202 | ["hex_edits"] = "\\x16\\x03\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1203 | ["float_value"] = 562949953421312 1204 | }, { 1205 | ["hex_edits"] = "\\x59\\x04\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1206 | ["float_value"] = 2251799813685248 1207 | }, { 1208 | ["hex_edits"] = "\\x06\\x02\\xA0\\xE3\\x1E\\xFF\\x2F\\xE1", 1209 | ["float_value"] = 36893488147419103000 1210 | }}, 1211 | ["ARM8"] = { 1212 | { 1213 | ["hex_edits"] = "\\x00\\x00\\xA8\\x52\\xC0\\x03\\x5F\\xD6", 1214 | ["float_value"] = 2 1215 | }, { 1216 | ["hex_edits"] = "\\x00\\x20\\xA8\\x52\\xC0\\x03\\x5F\\xD6", 1217 | ["float_value"] = 8 1218 | }, { 1219 | ["hex_edits"] = "\\x00\\x40\\xA8\\x52\\xC0\\x03\\x5F\\xD6", 1220 | ["float_value"] = 32 1221 | }, { 1222 | ["hex_edits"] = "\\x00\\x60\\xA8\\x52\\xC0\\x03\\x5F\\xD6", 1223 | ["float_value"] = 128 1224 | }, { 1225 | ["hex_edits"] = "\\x00\\x80\\xA8\\x52\\xC0\\x03\\x5F\\xD6", 1226 | ["float_value"] = 512 1227 | }, { 1228 | ["hex_edits"] = "\\x00\\xA0\\xA8\\x52\\xC0\\x03\\x5F\\xD6", 1229 | ["float_value"] = 2048 1230 | }, { 1231 | ["hex_edits"] = "\\x00\\xC0\\xA8\\x52\\xC0\\x03\\x5F\\xD6", 1232 | ["float_value"] = 8192 1233 | }, { 1234 | ["hex_edits"] = "\\x00\\xE0\\xA8\\x52\\xC0\\x03\\x5F\\xD6", 1235 | ["float_value"] = 32768 1236 | }, { 1237 | ["hex_edits"] = "\\x00\\x00\\xA9\\x52\\xC0\\x03\\x5F\\xD6", 1238 | ["float_value"] = 131072 1239 | }, { 1240 | ["hex_edits"] = "\\x00\\x20\\xA9\\x52\\xC0\\x03\\x5F\\xD6", 1241 | ["float_value"] = 524288 1242 | }, { 1243 | ["hex_edits"] = "\\x00\\x00\\xAA\\x52\\xC0\\x03\\x5F\\xD6", 1244 | ["float_value"] = 8589934592 1245 | }, { 1246 | ["hex_edits"] = "\\x00\\x20\\xAA\\x52\\xC0\\x03\\x5F\\xD6", 1247 | ["float_value"] = 34359738368 1248 | }, { 1249 | ["hex_edits"] = "\\x00\\x40\\xAA\\x52\\xC0\\x03\\x5F\\xD6", 1250 | ["float_value"] = 137438953472 1251 | }, { 1252 | ["hex_edits"] = "\\x00\\x60\\xAA\\x52\\xC0\\x03\\x5F\\xD6", 1253 | ["float_value"] = 549755813888 1254 | }, { 1255 | ["hex_edits"] = "\\x00\\x80\\xAA\\x52\\xC0\\x03\\x5F\\xD6", 1256 | ["float_value"] = 2199023255552 1257 | }, { 1258 | ["hex_edits"] = "\\x00\\xA0\\xAA\\x52\\xC0\\x03\\x5F\\xD6", 1259 | ["float_value"] = 8796093022208 1260 | }, { 1261 | ["hex_edits"] = "\\x00\\xC0\\xAA\\x52\\xC0\\x03\\x5F\\xD6", 1262 | ["float_value"] = 35184372088832 1263 | }, { 1264 | ["hex_edits"] = "\\x00\\xE0\\xAA\\x52\\xC0\\x03\\x5F\\xD6", 1265 | ["float_value"] = 140737488355328 1266 | }, { 1267 | ["hex_edits"] = "\\x00\\x00\\xAB\\x52\\xC0\\x03\\x5F\\xD6", 1268 | ["float_value"] = 562949953421312 1269 | }, { 1270 | ["hex_edits"] = "\\x00\\x20\\xAB\\x52\\xC0\\x03\\x5F\\xD6", 1271 | ["float_value"] = 2251799813685248 1272 | }, { 1273 | ["hex_edits"] = "\\x00\\x00\\xAC\\x52\\xC0\\x03\\x5F\\xD6", 1274 | ["float_value"] = 36893488147419103000 1275 | }} 1276 | }, 1277 | getSimpleFloatEdit = function() 1278 | local edits_arm7 1279 | local edits_arm8 1280 | local menu_table = {} 1281 | for i, v in pairs(Il2Cpp.simpleFloatsTable["ARM7"]) do 1282 | menu_table[#menu_table + 1] = v.float_value 1283 | end 1284 | local menu = gg.choice( 1285 | menu_table, 1286 | nil, 1287 | bc.Choice("Select Float Value", "", "ℹ️") 1288 | ) 1289 | if menu ~= nil then 1290 | edits_arm7 = Il2Cpp.simpleFloatsTable["ARM7"][menu].hex_edits 1291 | edits_arm8 = Il2Cpp.simpleFloatsTable["ARM8"][menu].hex_edits 1292 | return {edits_arm7, edits_arm8} 1293 | end 1294 | end 1295 | } 1296 | 1297 | scriptCreator = { 1298 | scriptMenu = function() 1299 | local menu = gg.choice({ 1300 | "➡️ Functions (" .. #scriptCreator.createdFunctions .. ")", 1301 | "🔀 Menu Editor", 1302 | "💾 Export Script" 1303 | }, 1304 | nil, 1305 | bc.Choice("Script Creator", "", "ℹ️") 1306 | ) 1307 | if menu ~= nil then 1308 | if menu == 1 then 1309 | scriptCreator.functionsMenu() 1310 | end 1311 | if menu == 2 then 1312 | scriptCreator.menuEditor() 1313 | end 1314 | if menu == 3 then 1315 | scriptCreator.generateScript() 1316 | end 1317 | end 1318 | end, 1319 | menuEditor = function() 1320 | local menu = gg.choice({ 1321 | "➡️ Edit Function Names", 1322 | "➡️ Edit Menu Order" 1323 | }, 1324 | nil, 1325 | bc.Choice("Menu Editor", "", "ℹ️") 1326 | ) 1327 | if menu ~= nil then 1328 | if menu == 1 then 1329 | local menuItems = {} 1330 | local menuType = {} 1331 | for i, v in pairs(scriptCreator.createdFunctions) do 1332 | menuItems[i] = v.functionName 1333 | menuType[i] = "text" 1334 | end 1335 | local renameFunctions = gg.prompt( 1336 | menuItems, 1337 | menuItems, 1338 | menuType 1339 | ) 1340 | if renameFunctions ~= nil then 1341 | for i, v in pairs(scriptCreator.createdFunctions) do 1342 | v.functionName = renameFunctions[i] 1343 | end 1344 | end 1345 | end 1346 | if menu == 2 then 1347 | local menuItems = {} 1348 | local menuType = {} 1349 | local currentPosition = {} 1350 | local isSet = {} 1351 | for i, v in pairs(scriptCreator.createdFunctions) do 1352 | menuItems[i] = v.functionName .. " [1; " .. #scriptCreator.createdFunctions .. "]" 1353 | currentPosition[i] = i 1354 | menuType[i] = "number" 1355 | isSet[i] = false 1356 | end 1357 | ::setorder:: 1358 | local reorderMenu = gg.prompt( 1359 | menuItems, 1360 | currentPosition, 1361 | menuType 1362 | ) 1363 | if reorderMenu ~= nil then 1364 | for i, v in pairs(reorderMenu) do 1365 | isSet[tonumber(v)] = true 1366 | end 1367 | for i, v in pairs(isSet) do 1368 | if v == false then 1369 | for index, value in pairs(isSet) do 1370 | value = false 1371 | end 1372 | goto setorder 1373 | end 1374 | end 1375 | local tempTable = {} 1376 | for i, v in pairs(scriptCreator.createdFunctions) do 1377 | tempTable[tonumber(reorderMenu[i])] = v 1378 | end 1379 | scriptCreator.createdFunctions = tempTable 1380 | end 1381 | end 1382 | end 1383 | end, 1384 | functionsMenu = function() 1385 | local menuItems = {} 1386 | for i, v in pairs(scriptCreator.createdFunctions) do 1387 | menuItems[i] = v.functionName 1388 | end 1389 | local menu = gg.choice( 1390 | menuItems, 1391 | nil, 1392 | bc.Choice("Edit Functions", "Select function to edit.", "ℹ️") 1393 | ) 1394 | if menu ~= nil then 1395 | local functionMenu = gg.choice({ 1396 | "➡️ Delete Field Edits", 1397 | "➡️ Delete Method Edits", 1398 | "➡️ Delete Function" 1399 | }, 1400 | nil, 1401 | bc.Choice("Edit Function", "", "ℹ️") 1402 | ) 1403 | if functionMenu ~= nil then 1404 | if functionMenu == 1 then 1405 | local editsItems = {} 1406 | for i, v in pairs(scriptCreator.createdFunctions[menu].edits) do 1407 | editsItems[i] = "" 1408 | for index, value in pairs(v.fieldEdits) do 1409 | editsItems[i] = editsItems[i] .. value.FieldName .. "\n" 1410 | end 1411 | end 1412 | local editsIndex = gg.choice( 1413 | editsItems, 1414 | nil, 1415 | bc.Choice("Fields Menu", "Select Edit to delete Field edit from.", "ℹ️") 1416 | ) 1417 | local fieldEditsItems = {} 1418 | for i, v in pairs(scriptCreator.createdFunctions[menu].edits[editsIndex].fieldEdits) do 1419 | fieldEditsItems[i] = v.FieldName 1420 | end 1421 | local fieldEdits = gg.multiChoice( 1422 | fieldEditsItems, 1423 | nil, 1424 | bc.Choice("Select Field edits to delete", "", "ℹ️") 1425 | ) 1426 | if fieldEdits ~= nil then 1427 | for i, v in pairs(fieldEdits) do 1428 | table.remove(scriptCreator.createdFunctions[menu].edits[editsIndex].fieldEdits, i) 1429 | end 1430 | bc.Alert("Edits Deleted", "Field edits removed from the function "..menuItems[menu], "ℹ️") 1431 | end 1432 | end 1433 | if functionMenu == 2 then 1434 | local editsItems = {} 1435 | for i, v in pairs(scriptCreator.createdFunctions[menu].edits) do 1436 | editsItems[i] = "" 1437 | for index, value in pairs(v.methodEdits) do 1438 | editsItems[i] = editsItems[i] .. value.MethodName .. "\n" 1439 | end 1440 | end 1441 | local editsIndex = gg.choice( 1442 | editsItems, 1443 | nil, 1444 | bc.Choice("Methods Menu", "Select Edit to delete Method edit from.", "ℹ️") 1445 | ) 1446 | local methodEditsItems = {} 1447 | for i, v in pairs(scriptCreator.createdFunctions[menu].edits[editsIndex].methodEdits) do 1448 | methodEditsItems[i] = v.MethodName 1449 | end 1450 | local methodEdits = gg.multiChoice( 1451 | methodEditsItems, 1452 | nil, 1453 | bc.Choice("Select Method edits to delete", "", "ℹ️") 1454 | ) 1455 | if methodEdits ~= nil then 1456 | for i, v in pairs(methodEdits) do 1457 | table.remove(scriptCreator.createdFunctions[menu].edits[editsIndex].methodEdits, i) 1458 | end 1459 | bc.Alert("Edits Deleted", "Method edits removed from the function "..menuItems[menu], "ℹ️") 1460 | end 1461 | end 1462 | if functionMenu == 3 then 1463 | local confirmDelete = gg.choice({ 1464 | "✅ Yes", 1465 | "❌ No" 1466 | }, 1467 | nil, 1468 | bc.Choice("Delete Function", "Are you sure you want to delete this function?", "ℹ️") 1469 | ) 1470 | if confirmDelete ~= nil and confirmDelete == 1 then 1471 | table.remove(scriptCreator.createdFunctions, menu) 1472 | bc.Alert("Function Deleted", menuItems[menu] .. " has been deleted." , "ℹ️") 1473 | end 1474 | end 1475 | end 1476 | end 1477 | end, 1478 | exportScript = function(scriptString) 1479 | file = io.open(gg.EXT_STORAGE .. "/Download/" .. gg.getTargetPackage() .. "." .. os.date("%b_%d_%Y_%H.%M") .. ".lua", "w+") 1480 | file:write(scriptString) 1481 | file:close() 1482 | bc.Alert("Script Exported", "The script has been saved to your Download folder.", "ℹ️") 1483 | end, 1484 | createdFunctions = {}, 1485 | handleClass = function(classTable) 1486 | local tempTable = {} 1487 | ::continue:: 1488 | local menu = gg.choice({ 1489 | "➡️ Fields", 1490 | "➡️ Methods", 1491 | "➡️ Done" 1492 | }, 1493 | nil, 1494 | bc.Choice("Create Edits", "Select type of edit to create.", "ℹ️") 1495 | ) 1496 | if menu ~= nil then 1497 | if menu == 1 then 1498 | local addToTable = scriptCreator.handleFields(classTable.Fields) 1499 | table.insert(tempTable, addToTable) 1500 | bc.Alert("Edits Created", "Fields edits created.", "ℹ️") 1501 | goto continue 1502 | end 1503 | if menu == 2 then 1504 | local addToTable = scriptCreator.handleMethods(classTable.Methods) 1505 | table.insert(tempTable, addToTable) 1506 | bc.Alert("Edits Created", "Method edits created.", "ℹ️") 1507 | goto continue 1508 | end 1509 | if menu == 3 then 1510 | scriptCreator.createFunction(tempTable) 1511 | end 1512 | end 1513 | end, 1514 | createFunction = function(tempTable) 1515 | local createNew 1516 | if #scriptCreator.createdFunctions > 0 then 1517 | local addOrNew = gg.choice({ 1518 | "🆕 Create New Function", 1519 | "➕ Add To Function" 1520 | }, 1521 | nil, 1522 | bc.Choice("Function Menu", "Create new function or add to existing one?", "ℹ️") 1523 | ) 1524 | if addOrNew ~= nil then 1525 | if addOrNew == 1 then 1526 | createNew = true 1527 | end 1528 | if addOrNew == 2 then 1529 | createNew = false 1530 | end 1531 | end 1532 | else 1533 | createNew = true 1534 | end 1535 | if createNew ~= nil then 1536 | if createNew == true then 1537 | local nameFunction = gg.prompt({ 1538 | bc.Prompt("Enter name for function", "ℹ️") 1539 | }, { 1540 | }, { 1541 | "text" 1542 | }) 1543 | if nameFunction ~= nil then 1544 | table.insert(scriptCreator.createdFunctions, { 1545 | functionName = nameFunction[1], 1546 | edits = tempTable 1547 | }) 1548 | bc.Alert("Function Added", "Edits have been added to new function "..nameFunction[1], "ℹ️") 1549 | end 1550 | end 1551 | if createNew == false then 1552 | local menuItems = {} 1553 | for i, v in pairs(scriptCreator.createdFunctions) do 1554 | menuItems[i] = v.functionName 1555 | end 1556 | local funcMenu = gg.choice( 1557 | menuItems, 1558 | nil, 1559 | bc.Choice("Select Function", "Select function to insert edits into.", "ℹ️") 1560 | ) 1561 | if funcMenu ~= nil then 1562 | for i, v in pairs(tempTable) do 1563 | for index, value in pairs( 1564 | scriptCreator.createdFunctions[funcMenu].edits) do 1565 | local classFound = false 1566 | if v.Class == value.Class then 1567 | classFound = true 1568 | if v.methodEdits then 1569 | if v.methodEdits and value.methodEdits then 1570 | for editIndex, editValue in pairs(v.methodEdits) do 1571 | table.insert(value.methodEdits, editValue) 1572 | end 1573 | else 1574 | value.methodEdits = v.methodEdits 1575 | end 1576 | elseif v.fieldEdits then 1577 | if v.fieldEdits and value.fieldEdits then 1578 | for editIndex, editValue in pairs(v.fieldEdits) do 1579 | table.insert(value.fieldEdits, editValue) 1580 | end 1581 | else 1582 | value.fieldEdits = v.fieldEdits 1583 | end 1584 | end 1585 | break 1586 | end 1587 | if classFound == false then 1588 | table.insert(scriptCreator.createdFunctions[funcMenu].edits, v) 1589 | bc.Alert("Edits Added", "Edits have been added to "..scriptCreator.createdFunctions[funcMenu].functionName, "ℹ️") 1590 | end 1591 | end 1592 | end 1593 | end 1594 | end 1595 | end 1596 | end, 1597 | handleFields = function(fieldsTable) 1598 | local menuItems = {} 1599 | for i, v in pairs(fieldsTable) do 1600 | menuItems[i] = v.FieldName 1601 | end 1602 | local menu = gg.multiChoice( 1603 | menuItems, 1604 | nil, 1605 | bc.Choice("Select Fields", "Select Fields to create edits for.", "ℹ️") 1606 | ) 1607 | if menu ~= nil then 1608 | local promptItems = {} 1609 | local promptTypes = {} 1610 | for i, v in pairs(menu) do 1611 | promptItems[#promptItems + 1] = menuItems[i] 1612 | promptTypes[#promptTypes + 1] = "number" 1613 | end 1614 | ::set_edits:: 1615 | local editMenu = gg.prompt( 1616 | promptItems, 1617 | nil, 1618 | promptTypes 1619 | ) 1620 | if editMenu ~= nil then 1621 | local edits = {} 1622 | for i, v in pairs(editMenu) do 1623 | table.insert(edits, { 1624 | FieldName = promptItems[i], 1625 | edit = v 1626 | }) 1627 | if #v == 0 then 1628 | goto set_edits 1629 | end 1630 | end 1631 | return { 1632 | Class = fieldsTable[1].ClassName, 1633 | fieldEdits = edits 1634 | } 1635 | end 1636 | end 1637 | end, 1638 | handleMethods = function(methodsTable) 1639 | local menuItems = {} 1640 | local functionEdits = {} 1641 | for i, v in pairs(methodsTable) do 1642 | menuItems[i] = v.MethodName 1643 | end 1644 | local menu = gg.multiChoice( 1645 | menuItems, 1646 | nil, 1647 | bc.Choice("Select Methods", "Select Methods to create edits for.", "ℹ️") 1648 | ) 1649 | if menu ~= nil then 1650 | local menuItems2 = {} 1651 | for i, v in pairs(menu) do 1652 | menuItems2[#menuItems2 + 1] = menuItems[i] 1653 | end 1654 | ::set_edits:: 1655 | local selectedMenu = gg.choice( 1656 | menuItems2, 1657 | nil, 1658 | bc.Choice("Select Method", "Select Method to create edit for.", "ℹ️") 1659 | ) 1660 | if selectedMenu ~= nil then 1661 | local edit 1662 | local createEdit = gg.choice({ 1663 | "✅ Yes", 1664 | "❌ No" 1665 | }, 1666 | nil, 1667 | bc.Choice("Create Edit", "Do you want to create a hex edit first?", "ℹ️") 1668 | ) 1669 | if createEdit ~= nil then 1670 | if createEdit == 1 then 1671 | edit = ggil2cppEdits.createEdit() 1672 | end 1673 | end 1674 | local editMenu = gg.prompt({ 1675 | bc.Prompt("Edit Menu", "ℹ️") .. "\nValue To Patch (\\x20\\x00\\x80\\x52\\xc0\\x03\\x5f\\xd6)" 1676 | }, { 1677 | edit 1678 | }, { 1679 | "text" 1680 | }) 1681 | if editMenu ~= nil then 1682 | functionEdits[selectedMenu] = editMenu[1] 1683 | end 1684 | end 1685 | if #menuItems2 == #functionEdits then 1686 | local edits = {} 1687 | for i, v in pairs(functionEdits) do 1688 | table.insert(edits, { 1689 | MethodName = menuItems2[i], 1690 | edit = v 1691 | }) 1692 | end 1693 | return { 1694 | Class = methodsTable[1].ClassName, 1695 | methodEdits = edits 1696 | } 1697 | else 1698 | goto set_edits 1699 | end 1700 | end 1701 | end, 1702 | generateScript = function() 1703 | local menu = gg.prompt({ 1704 | bc.Prompt("Enter a title for your script", "ℹ️") 1705 | }, { 1706 | }, { 1707 | "text" 1708 | }) 1709 | if menu ~= nil then 1710 | local scriptTitle = menu[1] 1711 | local scriptTable = { 1712 | 'functionTable = ' .. tostring(scriptCreator.createdFunctions), 1713 | '', 1714 | 'scriptTitle = "' .. scriptTitle .. '"', 1715 | '', 1716 | 'local file = io.open("Il2cppApi.lua","r")', 1717 | 'if file == nil then', 1718 | ' io.open("Il2cppApi.lua","w+"):write(gg.makeRequest("https://raw.githubusercontent.com/kruvcraft21/GGIl2cpp/master/build/Il2cppApi.lua").content):close()', 1719 | 'end', 1720 | 'require("Il2cppApi")', 1721 | 'Il2cpp()', 1722 | '', 1723 | 'restoreFields = {}', 1724 | 'restoreMethods = {}', 1725 | '', 1726 | 'function handleClick(editsTable, functionIndex)', 1727 | ' if restoreFields[functionIndex] or restoreMethods[functionIndex] then', 1728 | ' if restoreFields[functionIndex] then', 1729 | ' gg.setValues(restoreFields[functionIndex])', 1730 | ' restoreFields[functionIndex] = nil', 1731 | ' end', 1732 | ' if restoreMethods[functionIndex] then', 1733 | ' gg.setValues(restoreMethods[functionIndex])', 1734 | ' restoreMethods[functionIndex] = nil', 1735 | ' end', 1736 | ' gg.alert(functionTable[functionIndex].functionName .. " Disabled")', 1737 | ' else', 1738 | ' for i, v in pairs(editsTable) do', 1739 | ' local getMethods = false', 1740 | ' local getFields = false', 1741 | ' if v.fieldEdits then', 1742 | ' getFields = true', 1743 | ' end', 1744 | ' if v.methodEdits then', 1745 | ' getMethods = true', 1746 | ' end', 1747 | ' local classTable = Il2cpp.FindClass({', 1748 | ' {', 1749 | ' Class = v.Class,', 1750 | ' MethodsDump = getMethods,', 1751 | ' FieldsDump = getFields', 1752 | ' }})[1][1]', 1753 | ' if v.fieldEdits then', 1754 | ' restoreFields[functionIndex] = {}', 1755 | ' handleFieldEdits(v.Class, v.fieldEdits, classTable, functionIndex)', 1756 | ' end', 1757 | ' if v.methodEdits then', 1758 | ' restoreMethods[functionIndex] = {}', 1759 | ' handleMethodEdits(v.Class, v.methodEdits, classTable, functionIndex)', 1760 | ' end', 1761 | ' end', 1762 | ' gg.alert(functionTable[functionIndex].functionName .. " Enabled")', 1763 | ' end', 1764 | 'end', 1765 | '', 1766 | 'function handleFieldEdits(className, fieldEditsTable, classTable, functionIndex)', 1767 | ' local classInstances = Il2cpp.FindObject({className})[1]', 1768 | ' local tempTable = {}', 1769 | ' for i, v in pairs(classInstances) do', 1770 | ' for index, value in pairs(fieldEditsTable) do', 1771 | ' for fieldIndex, fieldData in pairs(classTable.Fields) do', 1772 | ' if value.FieldName == fieldData.FieldName then', 1773 | ' tempTable[#tempTable + 1] = {', 1774 | ' address = v.address + tonumber(fieldData.Offset, 16),', 1775 | ' flags = gg.TYPE_DWORD,', 1776 | ' value = value.edit', 1777 | ' }', 1778 | ' end', 1779 | ' end', 1780 | ' end', 1781 | ' end', 1782 | ' restoreFields[functionIndex] = gg.getValues(tempTable)', 1783 | ' gg.setValues(tempTable)', 1784 | 'end', 1785 | '', 1786 | 'function handleMethodEdits(className, methodEditsTable, classTable, functionIndex)', 1787 | ' for i, v in pairs(methodEditsTable) do', 1788 | ' for index, value in pairs(classTable.Methods) do', 1789 | ' if v.MethodName == value.MethodName then', 1790 | ' restoreMethods[functionIndex] = backupValues(tonumber(value.AddressInMemory, 16), #v.edit)', 1791 | ' Il2cpp.PatchesAddress(tonumber(value.AddressInMemory, 16), v.edit)', 1792 | ' end', 1793 | ' end', 1794 | ' end', 1795 | 'end', 1796 | '', 1797 | 'function backupValues(address, byteCount)', 1798 | ' local tempTable = {}', 1799 | ' local offset = 0', 1800 | ' for i = 1, byteCount do', 1801 | ' tempTable[i] = {', 1802 | ' address = address + offset,', 1803 | ' flags = gg.TYPE_BYTE', 1804 | ' }', 1805 | ' offset = offset + 1', 1806 | ' end', 1807 | ' tempTable = gg.getValues(tempTable)', 1808 | ' return tempTable', 1809 | 'end', 1810 | '', 1811 | 'function home()', 1812 | ' local menuItems = {}', 1813 | ' for i, v in pairs(functionTable) do', 1814 | ' menuItems[i] = v.functionName', 1815 | ' end', 1816 | ' local menu = gg.choice(menuItems, nil, scriptTitle)', 1817 | ' if menu ~= nil then', 1818 | ' handleClick(functionTable[menu].edits, menu)', 1819 | ' end', 1820 | 'end', 1821 | '', 1822 | 'home()', 1823 | '', 1824 | 'print("⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚")', 1825 | 'print("⧚⧚⧚ Script Created With")', 1826 | 'print("⧚⧚⧚ BadCase\'s (GGIl2cpp by Kruvcraft) Toolbox")', 1827 | 'print("⧚⧚⧚")', 1828 | 'print("⧚⧚⧚")', 1829 | 'print("⧚⧚⧚ Website")', 1830 | 'print("⧚⧚⧚ BadCase.org")', 1831 | 'print("⧚⧚⧚")', 1832 | 'print("⧚⧚⧚ Telegram Group")', 1833 | 'print("⧚⧚⧚ t.me/BadCaseDotOrgSupport")', 1834 | 'print("⧚⧚⧚")', 1835 | 'print("⧚⧚⧚ Donate With PayPal")', 1836 | 'print("⧚⧚⧚ paypal.me/BadCaseDotOrg")', 1837 | 'print("⧚⧚⧚")', 1838 | 'print("⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚⧚")', 1839 | 'while true do', 1840 | ' if gg.isVisible() then', 1841 | ' gg.setVisible(false)', 1842 | ' home()', 1843 | ' end', 1844 | ' gg.sleep(100)', 1845 | 'end' 1846 | } 1847 | local scriptString = "" 1848 | for i, v in pairs(scriptTable) do 1849 | scriptString = scriptString .. v .. "\n" 1850 | end 1851 | scriptCreator.exportScript(scriptString) 1852 | end 1853 | end 1854 | } 1855 | 1856 | ggil2cppFrontend.home() 1857 | gg.showUiButton() 1858 | 1859 | while true do 1860 | if gg.isClickedUiButton() then 1861 | ggil2cppFrontend.home() 1862 | end 1863 | gg.sleep(100) 1864 | end 1865 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GGIl2cpp-Toolbox 2 | This script provides a frontend for all of the core functions of kruvcraft21's 3 | 4 | GGIl2cpp https://github.com/kruvcraft21/GGIl2cpp 5 | 6 | FindClass: Calls GGIl2cpp's Il2cpp.FindClass() function and loads results to the Save List. Selecting results in the Save List opens a menu to copy data, load Field instances, make Method edits and create Field and Method edits for exported scripts. 7 | 8 | FindFields: Calls GGIl2cpp's Il2cpp.FindFields() function and loads results to the Save List. Selecting results in the Save List opens a menu to copy data, load instances of the Field and create Field edits for exported scripts. 9 | 10 | FindMethods: Calls GGIl2cpp's Il2cpp.FindMethods() function and loads results to the Save List. Selecting results in the Save List opens a menu to copy data, edit Methods and create Method edits for exported scripts. 11 | 12 | FindObject: Calls GGIl2cpp's Il2cpp.FindObject() function and loads results to the Save List. Selecting results in the Save List opens a menu to load Field instances. 13 | 14 | PatchesAddress: Calls GGIl2cpp's Il2cpp.PatchesAddress() function which edits a Method in Xa with a hex byte edit. The script can create the hex byte edits for you or you can enter them manually. 15 | 16 | Keyword Search: Allows you to search for Classes, Methods and Fields by keyword instead of exact name. Classes will be added to the Save List for Class and Field results, Methods will be added for Method results. 17 | 18 | Script Creator: Allows you to edit created function names, modify menu order and export scripts. 19 | --------------------------------------------------------------------------------