• Cheat Engine и Lua. Старт

    Прикреплена Перенесена ce lua
    1
    0 Голоса
    1 Сообщения
    285 Просмотры
    MasterGHM
    Где писать Lua код? Lua Engine окно, которое вызывается из главного окна CE. Lua Console окно, которое вызывается из окна отладки CE. Окно Autoassembler скрипта с вставки {$lua}, {$asm} Lua Engine окно и Autoassembler-ные скрипты могут сохраняться в файлах Cheat Engine *.CT. *.CETRAINER, *.EXE Lua Console для пошаговой отладки Lua кода и просмотров результатов ошибок и функции print() Моя первая программа Сначала узнаем версию для CE 6.7 и это будет первая программа Запускаем CE и жмем ctrl+alt+L и Lua Engine, вводим print(_VERSION) \-->> Lua 5.3 Вторая программа showMessage('Hello World!') Следующий шаг — собрать справочные материалы и практические руководства. Неважно какими они будут по сложности и объему. Всегда можно будет обратиться к ним позже, когда потребуется что-то найти. Справочные материалы Если CE использует версию Lua 5.3, то нужен официальный справочник по этой версии. Ищем Lua 5.3 (https://www.lua.org/manual/5.3/) Cheat Engine Lua Basics (http://wiki.cheatengine.org/index.php?title=Lua_Basics ) Category:Assembler(http://wiki.cheatengine.org/index.php?title=Category:Assembler) Lua Functions and Classes (http://wiki.cheatengine.org/index.php?title=Lua) Introduction to Lua using Cheat Engine: Beginner to Basic Script Writer! (http://dsasmblr.com/introduction-to-lua-using-cheat-engine-beginner-to-basic-script-writer/) Setup a Lua auto attach script (http://wiki.cheatengine.org/index.php?title=Tutorials:Lua:Setup_Auto_Attach) Lua Debugging (http://wiki.cheatengine.org/index.php?title=Lua_Debugging) Практические руководства Tables Tutorial (http://lua-users.org/wiki/TablesTutorial) Learn Lua in 15 Minutes (http://tylerneylon.com/a/learn-lua/) Lua за 60 минут (https://zserge.wordpress.com/2012/02/23/lua-за-60-минут/) Я обращаюсь к celua.txt и defines.lua. Находятся в директории Cheat Engine. В этих файлах краткое справочное руководство. Стоит также отметить, что Cheat Engine 6.7 написана на Lazarus. Написав, например программу по рисованию фигур, линий на форме на Lazarus или Delphi можно будет понять, как сделать также классами и функциями на CE Lua. А что нельзя сделать CE Lua, то решается внедрением и исполнения кода в саму Cheat Engine. Продолжение следует...
  • Рубрика "Lua код сегодня" №5 (активирующий скрипт)

    Прикреплена Перенесена ce lua ce aa active rec ce memrec важно обучалка
    3
    3
    0 Голоса
    3 Сообщения
    172 Просмотры
    MasterGHM
    Update: Если скрипт не запускается, то вызывать reinitializeSymbolhandler(true) Пример здесь
  • Собираем ссылки на разные источники

    Прикреплена Перенесена todo источники
    7
    1
    0 Голоса
    7 Сообщения
    316 Просмотры
    MasterGHM
    Попробуй другой браузер или кеш браузера почистить. Может поможет. Иногда ссылки кешируются и автоматически подставляются неверные.
  • Шаблон скрипта для проверки MD5 в Cheat Engine с авто-активацией чита

    Перенесена
    1
    0 Голоса
    1 Сообщения
    76 Просмотры
    MasterGHM
    Шаблон скрипта для проверки MD5 в Cheat Engine с авто-активацией чита Сначала дается краткий сжатый код. function onOpenProcess(processid) reinitializeSymbolhandler() local md5Process = GetMd5Process(processid) PrintMd5Process(process, md5Process) local isSupportedVersion = CheckingMd5CurrentProcess(md5Process) local lineResult = isSupportedVersion and 'Is supported version. Activating cheat...' or 'Is not supported version.' if not isSupportedVersion then speakEnglish(lineResult, false) messageDialog('Error', lineResult, mtError, mbClose) else speakEnglish(lineResult, true) -- Активация простого чита: поиск и заморозка адреса здоровья autoAssemble([[ alloc(newmem,2048) label(code) label(return) "Base.exe"+123456: code: mov [eax],(int)999 return: jmp return newmem: jmp "Base.exe"+123456 nop jmp return ]]) messageDialog('Success', 'Cheat activated for health: 999', mtInformation, mbOK) end end А потом дается объяснение. Все нужно в формате nodebb ce_md5_cheat.lua md5 - это алгоритм хэширования exe-файла, который позволяет точно идентифицировать версию игры или приложения. Это критично для .CT таблиц в Cheat Engine, чтобы избежать ошибок из-за обновлений, меняющих смещения структур памяти. В случае несоответствия MD5 версии показывается диалог ошибки и звуковое оповещение. Если версия поддерживается, скрипт автоматически активирует простой чит (в примере - заморозка здоровья на 999 по смещению "Base.exe"+123456; замените на реальные значения для вашей игры). Обязательно проверяйте MD5 перед использованием таблиц, чтобы смещения структур не сдвинулись из-за патчей! Получить md5 открытого процесса и записать его в MD5_CHEKING вручную \-- Функция для ручного вывода md5 ранее подключенного процесса. Для установки MD5_CHEKING PrintMd5CurrentProcess() Пример проверки md5 с авто-активацией function onOpenProcess(processid) reinitializeSymbolhandler() local md5Process = GetMd5Process(processid) PrintMd5Process(process, md5Process) local isSupportedVersion = CheckingMd5CurrentProcess(md5Process) local lineResult = isSupportedVersion and 'Is supported version. Activating cheat...' or 'Is not supported version.' if not isSupportedVersion then speakEnglish(lineResult, false) messageDialog('Error', lineResult, mtError, mbClose) else speakEnglish(lineResult, true) -- Активация простого чита: поиск и заморозка адреса здоровья autoAssemble([[ alloc(newmem,2048) label(code) label(return) "Base.exe"+123456: code: mov [eax],(int)999 return: jmp return newmem: jmp "Base.exe"+123456 nop jmp return ]]) messageDialog('Success', 'Cheat activated for health: 999', mtInformation, mbOK) end end
  • Unity3d. Easing functions в Unity & DoTween

    Перенесена
    1
    3
    0 Голоса
    1 Сообщения
    458 Просмотры
    MasterGHM
    Функции анимации для Unity FrameWork для UNity3d: https://dotween.demigiant.com/ Документация: https://dotween.demigiant.com/documentation.php Принцип: Узнаем, что анимировать. Например, подсветку. Узнаем, как анимировать. Например, идем https://easings.net/ смотрим график и тип анимации. Например, мне нужна анимация easeOutSine. По ней должна меняться частота цвета подсветки Далее ищем какой-нибудь пример в поисковике по работе с цветом. Пусть это будет using DG.Tweening; using UnityEngine; public class ColorChanger : MonoBehaviour { [SerializeField] private MeshRenderer meshRenderer; private void Awake() { // меняется цвет материала DOVirtual.Color(Color.black, Color.white, 10, (value) => { meshRenderer.material.color = value; }); } } Смотрим документацию ...В этом примере, material при каждом разе пересоздается с новым цветом в каждом кадре отрисовки, поэтому надо менять на sharedMaterial. Этот пример надо переделать с анимацией Ищем функцию анимации Пишем пример. Анимируем мерцание цвета с возрастающей частотой по InQuint IEnumerator ShowWriteButton() { Image image = writeButton.GetComponent<Image>(); Color originalColor = image.color; float frequency = 0; DOVirtual.Float(0.01f, 0.1f, 1f, v => frequency = v).SetEase(Ease.InQuint); var currentTime = Time.time; yield return new WaitForSeconds(0.5f); while (Time.time - currentTime <= 1f) { image.color = originalColor; yield return new WaitForSeconds(frequency); image.color = colorWrite; yield return new WaitForSeconds(frequency); } } StartCoroutine(ShowWriteButton()); В этом примере происходят параллельно две операции: изменение частоты по InQuint и использование этой частоты для подсветки кнопки. Много примеров в документации... Dotween библиотека популярна. Её можно использовать для полета камеры, для перемещения объектов, подсветки и т.п.
  • Visual Studio. Топ 10 часто используемых горячих клавиш

    Перенесена vs hotkey
    1
    0 Голоса
    1 Сообщения
    1k Просмотры
    MasterGHM
    Предлагаю поделиться своими ТОП горячими клавишами в Visual Studio. ctrl + ] найти закрывающие скобки функции, класса. С shift можно выбрать внутри. shift + alt + (. или <) перемещение по выделенными словам как f3 вперед или назад alt + лев. кнопка мышки установка мульти курсора. После выбор по shift или в пункт 2, 4. shift +u или ctl +u сделать выделенный текст строчными или прописными ctrl + R + G - удалить неиспользуемые пространства имен ctrl + shift + v кольцевой буфер обмена ctrl + K + S обернуть строки (в регион, namespace, if и т.п.) ctrl + alt + X окно элементов (перетаскиваем туда выделенные строки в своим папки. Это для хранения истории своих строк кода) ctrl + K поставить закладку ctrl +K+K создать/убрать закладку ctrl +K+N / CTRL+K+P перемещение по закладкам ctrl +K+L удалить все закладки ctrl + T показать список задач. Перемещение строки или выделенных строк alt +↑ переместить строку вверх alt +↓ переместить строку вниз alt + shift +arrow keys(←,↑,↓,→) выбор колонок текста ctrl +arrow keys(←,→) перемещение по словами ctrl +arrow keys(↑,↓) движение списка и т.п.
  • Запустить активирющий скрипт CE 7.5

    Перенесена ce aa active rec ce lua важно
    5
    1 Голоса
    5 Сообщения
    365 Просмотры
    MasterGHM
    Кнопка "^"
  • Функция autoAssemble

    Перенесена ce aa ce lua autoassemble
    2
    1 Голоса
    2 Сообщения
    2k Просмотры
    PitronicP
    Пользователь @MasterGH написал в Функция autoAssemble: // Скрипт похожий на таблицу АА Маленькое замечание. Два слеша используются для коментариев в асм. На луа используются пунктир не менее двух чёрточек. Если пользователь не разбирается, он не поймёт почему луа выдаёт ошибку. Тему поправил.
  • Безусловные и условные пыжки.

    Перенесена
    1
    1 Голоса
    1 Сообщения
    148 Просмотры
    PitronicP
    Иногда код ассемблера необходимо с делать с условием пример фильтр свой чужой. Реализовать это можно сравнением двух адресов и задать условие. Сравнение задаётся командой cmp, после которой идёт условие прыжка , после которого выполняется ваш код. пример мы нашли смещение от адреса число которое равно 1 от начала структуры адреса игрока и нам надо если оно равно чтоб здоровье было больше. и так пишем наш код. cmp [eax+1234],1 // сравнили наш адрес фильтра с единицей jne code // если не равно прыжок на метку code mov [eax+40],#99999 // а если равно кроме метки code могут быть безымянные метки @F прыжок в перёд @B прыжок назад пример cmp [eax+1234],1 // сравнили наш адрес фильтра с еденицей jne @F // если не равно прыжок в перёд mov [eax+40],#99999 // а если равно также есть чистая безымянная метка которая позволит сделать два условия @@: безымянная метка пример с этим же кодом cmp [eax+1234],1 // сравнили наш адрес фильтра с единицей jne @F // если не равно прыжок в перёд mov [eax+40],#99999 // а если равно @@: // прыжок на безымянную метку mov [eax+40],0 // если [eax+1234],1 не равен это наш враг и с метки @@: не наш игрок умирает Теперь таблица условных прыжков и переходов: JA прыжок, если выше JAE прыжок, если выше или равно JB прыжок, если ниже JBE прыжок, если меньше или равно JC Прыгает, если перенос JCXZ прыжок, если равно нулю JE прыжок, если равно JG прыжок, если больше JGE прыжок, если больше или равно JL прыжок, если меньше JLE прыжок, если меньше или равно Прыжок JNA, если не выше JNAE прыжок, если не выше или не равно Прыжок JNB, если не ниже JNBE прыжок, если не ниже или не равно Переход JNC, если не выполняется перенос JNE прыжок, если не равно Переход JNG, если не больше JNL прыжок, если не меньше JNO переходит, если не переполнено JZ прыжок если равно нулю.
  • Как контролировать включение и выключение скриптов в таблице

    Перенесена ce lua условие управление
    1
    0 Голоса
    1 Сообщения
    95 Просмотры
    MasterGHM
    Как контролировать включение и выключение скриптов в таблице AA или "Autoassembler code" код похожий на язык программирования ассемблера. Кратко, он позволяет менять игровой код. Подробнее Cheat Engine:Auto Assembler (http://wiki.cheatengine.org/index.php?title=Cheat_Engine:Auto_Assembler) Обычный АА-скрипт состоит из двух директив и добавляется в таблицу CE как запись // Код срабатывающий как при активации, так и при деактивации [ENABLE] // Код активации [DISABLE] // Код деактивации Чтобы код активировался, нужно включить галку напротив записи в таблице и наоборот выключить. Есть такие директивы как {$lua} и {$asm}. Под {$lua} пишут Lua скрипт, под {$asm} пишут АА-скрипт. Мы можем проверить Lua скриптом любое условие и разрешить включать галку или выключать галку. Например, через "syntaxcheck" — проверку синтаксиса или другое условие . Если проверка не прошла, то не получится галку включить и не получится выключить, если что-то пойдет не так. В Lua строка из двух минусов "--", обозначает комментарий. {$lua} \-- Расскоментируйте или закоментируйте пару строк ниже \-- if syntaxcheck then return end \-- error[666] = 666 \------------------------------ ENABLE ------------------------------ [ENABLE] \-- Расскоментируйте или закоментируйте пару строк ниже \-- if syntaxcheck then return end \-- error[666] = 666 \------------------------------ DISABLE ------------------------------ [DISABLE] \-- Расскоментируйте или закоментируйте пару строк ниже \-- if syntaxcheck then return end \-- error[666] = 666 Попробовав разные варианты вы увидите, что нельзя включать или выключать галку в разных ситуациях. Например в этой получится включить галку, а выключить нет из-за ошибки. {$lua} \-- if syntaxcheck then return end \-- некоторый lua код правильный или не правильный \-- error[666] = 666 \------------------------------ ENABLE ------------------------------ [ENABLE] \--if syntaxcheck then return end \-- некоторый lua код \-- некоторый lua код правильный или не правильный \-- error[666] = 666 \------------------------------ DISABLE ------------------------------ [DISABLE] if syntaxcheck then return end \-- некоторый lua код \-- некоторый lua код правильный или не правильный error[666] = 666 Следующий вариант проверяет открыт ли процесс. Если нет, то покажет сообщение. Как узнать, что процесс был закрыт после открытия process - зарезервированное переменная, показывает что процесс открыт (http://wiki.cheatengine.org/index.php?title=Lua:process) В комментариях можно увидеть при каких условиях блокируются включение галки {$lua} -- code before either enable/disable section runs for both just like with AA code if syntaxcheck then return end [ENABLE] if process == nil then showMessage('Процесс не подключен. Галка не будет включена') return end if process ~= nil and readInteger(process) == nil then showMessage('Процесс был закрыт. Галка не будет включена') return end [DISABLE] -- Галку можно выключить, но код выключения выполнять если процесс подключен if process ~= nil and readInteger(process) ~= nil then print('Attached to ' .. process) else showMessage('The process closed') end
  • Часть1. Lua простые регулярные выражения

    Перенесена ce lua regular
    1
    1
    0 Голоса
    1 Сообщения
    169 Просмотры
    MasterGHM
    Есть такой плагин "AA Maker" и там довольно интересные регулярные выражения на Lua. Разберем некоторые выражения Выражение ''%[(.*)%]' - захват всего, что в квадратных скобках Пример local s = 'mov eax, [ecx + 4]' print(string.match(s, '%[(.*)%]')) \--> ecx + 4 Символ "%" нужно всегда ставить перед специальными символами такими как ^$()%.[]*+-? Символ "%[" и "%]" означают квадратные скобки в строке Разбирая комбинацию (.*). Точка означает любой символ, а символ умножить означает повторение любого символа Круглые скобки означают "подшаблон" Подшаблоны В шаблон можно включить подшаблоны, выделив их круглыми скобками. Если найденная строка соответствует шаблону, то ее подстроки, соответствующие подшаблонам, будут доступны для будущего использования. Подшаблоны пронумерованы согласно их левым круглым скобкам. Например, в шаблоне "(a*(.)%w(%s*))", часть строки, соответствующая "a*(.)%w(%s*)" будет зафиксирована как первый подшаблон (и поэтому имеет номер 1); любые символы попавшие под соответствие "." будут зафиксированы как подшаблон номер 2, и часть строки, соответствующая "%s*" получит номер 3. Специальный вариант использования подшаблонов - получение текущей позиции в строке. Для этого используются пустые подшаблоны (). Например, если мы применим шаблон "()aa()" к строке "flaaap", то получим два результата: 3 и 5. Шаблон не может содержать вложенные ноли. Используйте %z вместо этого. Т.е. можем извлечь содержимое инструкции. Примеры "(.*)" - захват всей строки "/(.*)/" - захват всего, что находится между КРАЙНИМИ символами / "/(.-)/" - захват всего, что находится между ПЕРВЫМИ ДВУМЯ символами / Пример из ААMaker плагина local _,_,x = string.find(opcode, '%[(.*)%]') из функции ниже Функция string.find("СТРОКА", "ШАБЛОН") возвращает номер позиции начала начала и конца шаблона Пример print(string.find('some string', 'me')) \--> 3 4 Вся функция с комментариями из AAMaker \-- Таблица паттернов для нескольких инструкций inc, mov, fld, fstp (ключи таблицы) \-- Они нужны для создания автоматического АА кода, через замену строк другими строками \- {$Type} — очевидно для типа byte, word, dword \- [x] — очевидно обращение к адресу \- {$Value} — это значение \- \r\n — переход на следующую строку \-- Что будем делать с этой таблицой будет видно по коду или смотрите плагин PATTERN = { ['inc'] = 'mov{$Type}[x],{$Value}', ['mov'] = 'mov{$Type}[x],{$Value}\r\n{$OriginalCode}', ['fld'] = 'mov{$Type}[x],{$Value}\r\n{$OriginalCode}', ['fstp'] = '{$OriginalCode}\r\n'..'mov{$Type}[x],{$Value}' } \-- Не очень понятно зачем квадратные скобки у ключей. Можно написать не ['inc'], а 'inc' \-- Функция проверки паттерна function checkPattern() -- Получение имени адреса из адреса dv_address1 (выделенный адрес в дизассемблере) local address = getNameFromAddress(dv_address1) -- Получение инструкции по имени адреса local _,opcode = splitDisassembledString(disassemble(address)) -- ComboBox.Text свойство равно "Injection" или "AOBScanModule" local choose = getProperty(cmbCheatType,"Text") if choose == 'Injection' or choose == 'AOBScanModule' then -- Перебор по ключу и значению таблицы PATTERN for key,value in pairs(PATTERN) do -- Если в опкоде нашли ключ из таблицы паттернов -- Где key это inc, mov, fld, fstp (см. выше таблицу PATTERN) -- Где opcode это например инструкция 'inc [edx + 4]' if string.find(opcode,key) ~= nil then local _,_,x = string.find(opcode, '%[(.*)%]') if x ~= nil then -- В value будет значение 'mov{$Type}[x],{$Value}' patternInjectAsmCode = value -- Нашли паттерн и вернули его return true end end end end -- Паттерн не нашли в таблице, вернули false patternInjectAsmCode = '{$OriginalCode}' return false end \-- patternInjectAsmCode Чтобы посмотреть результат, сделал скрин отладки Lua кода Функции по работе со строками. Link Используемые источники: link, link, link, link aamaker.lua
  • Часть2. Lua простые регулярные выражения

    Перенесена lua regular ce lua
    1
    0 Голоса
    1 Сообщения
    91 Просмотры
    MasterGHM
    Если нужно найти начало и конец подстроки. Пример Попробуем найти слово lab в троке gamehacklab.ru print(string.find('gamehacklab.ru', 'lab')) >9 11 Если не найдена подстрока, то вернет nil. С помощью string.match можем выводить не индексы, а строку print(string.match('gamehacklab.ru', 'lab')) >lab С помощью string.gmatch можем выводить последовательно строки Где 'a.' означает символ 'a' и еще один следующий любой local result = string.gmatch('gamehacklab.ru', 'a.') print(result()) print(result()) print(result()) вывод >am >ac >ab Здесь комбинация символов "%a+" означает искать слово пока оно не закончится s = "hello world from Lua" for w in string.gmatch(s, "%a+") do print(w) end Вывод > hello > world > from > Lua А здесь заполняем таблицу ключ — значение из строки, которую можно было бы взять из файла t = {} s = "X=0, Y=0, Z=0" for k, v in string.gmatch(s, "(%w+)=(%w+)") do t[k] = v end for i, v in pairs(t) do print(i..' = '..v) end Вывод >Z = 0 >X = 0 >Y = 0 Пока на этом все... Более сложные примеры в предыдущей части записи
  • Рубрика "Lua код сегодня" №6 (проверка по md5)

    Перенесена md5 ce lua speak важно обучалка фишки
    1
    0 Голоса
    1 Сообщения
    241 Просмотры
    MasterGHM
    Получить md5 открытого процесса и записать его в MD5_CHEKING вручную \-- Функция для ручного вывода md5 ранее подключенного процесcа. Для установки MD5_CHEKING PrintMd5CurrentProcess() Пример проверки md5 function onOpenProcess(processid) reinitializeSymbolhandler() local md5Process = GetMd5Process(processid) PrintMd5Process(process, md5Process) local isSupportedVersion = CheckingMd5CurrentProcess(md5Process) local lineResult = isSupportedVersion and 'Is supported version.' or 'Is not supported version.' if not isSupportedVersion then speakEnglish(lineResult, false) messageDialog('Error', lineResult, mtError, mbClose) end end ce_md5.lua md5 - это алгоритм некоторой суммы байтов exe-шника. Позволит точно идентифицировать exe-шник, для которого будет сделана .CT таблица с указателями или сигнатурами. В случае несоответствия будет показан диалог сообщения и звуковое оповещение проговаривания текста ошибки. Будет необходимо проверять md5, чтобы смещения у структур точно не поменялись.
  • Обзор игры STELLARIS

    Перенесена Не решенные todo обзор игра
    7
    0 Голоса
    7 Сообщения
    254 Просмотры
    MasterGHM
    Ты можешь через CE ставить брейкпоинт. Читать регистр. Писать в него. Отпускать отладку. Память не будет меняться/палится. Но можно,скорее в его,запалить точеи останова. Перезаписывать память кода и данных через драйвер ce разово или по таймеру. В этом случае память может палиться. Тогда пробовать через CE сделать хуки на чтение памяти и возвращать оригинальные байты. погуглить про скрытие процессов, секций памяти, модулей, хуки на функции (чтение памяти, получение списка процессов...). Хук позволит функцию перенаправить на свою, изменить результат и вернуть его. посмотреть про обработку исключений в исхолниках на примере stealthmode плагина в ce
  • Телепорт на 10 слотов и на 3 типа данных (float, double, integer)

    Перенесена Не решенные ce lua телепорт озвучка шаблоны
    8
    0 Голоса
    8 Сообщения
    338 Просмотры
    PitronicP
    У меня не горит, более того пока не делаю телепорт, просто чтоб знать как, спросил. Будет время расскажешь. Только бы не забыл.
  • Поиск в региона памяти модуля

    Перенесена фишки ce plugin обучалка
    5
    1
    0 Голоса
    5 Сообщения
    206 Просмотры
    PitronicP
    вот доказательство что старым версиям твой плагин нужен будет.
  • CE 6.8 Обзор нового инструмента поиска по структурам

    Перенесена ce structure блог compare
    8
    2
    0 Голоса
    8 Сообщения
    247 Просмотры
    MasterGHM
    Пользователь @Pitronic написал в CE 6.8 Обзор нового инструмента поиска по структурам: Разрешаю в этой теме всё что в той дополнить Спасибо, за твое разрешение. Мне, кажется, это две разные статьи и лучше в новой теме. @Pitronic публиковать статьи тоже можешь.. Там еще можно добавлять теги и выбирать раздел.
  • Крафт в StarsOne

    Перенесена unity dnspy блог
    1
    8
    0 Голоса
    1 Сообщения
    86 Просмотры
    MasterGHM
    В оригинале, если нет всех компонентов рецепта, то нельзя скрафтить вещь. Цель: скрафтить без компонетов по нажатию кнопки Игра на Unity и можно пробовать использовать в dnSpy модифицировать файл Assembly-CSharp.dll Открываем файлик и смотрим на классы связанные с крафтом Так находим кнопку, которая создаст указанное количество вещей крафта в CreateItem Задача скрафтить по имеющемуся рецепту любую вещь. Для этого я добавляю проверку количества вещей и удаляю лишний код. Под сполерами оригинальный и модифицированный код Модифицированный код using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using UnityEngine; public partial class Crafting : MonoBehaviour { public void CreateItem(int curCraft, int craftCount) { if (this.timeBreak >= 0.3f) { // Добавили одну вещь крафта if (craftCount == 0) { craftCount = 1; } if (craftCount != 0) { this.succes = true; CraftRecipe component = this.craftObjects[curCraft].GetComponent<CraftRecipe>(); // Здесь удалили код, который должен расходовать вещи из инвентаря // ... if (this.succes) { this.iks = this.craftObjects[curCraft].GetComponent<CraftRecipe>().countCreate * craftCount; for (int m = 0; m < this.craftObjects[curCraft].GetComponent<CraftRecipe>().countCreate * craftCount; m++) { this.emptyCell = Inventory.inv.FindItemForStack(this.craftObjects[curCraft].name); if (this.emptyCell >= 0) { if (Inventory.inv.items[this.emptyCell].stack + this.iks <= Inventory.inv.items[this.emptyCell].maxStack) { Inventory.inv.items[this.emptyCell].stack += this.iks; break; } this.iks -= Inventory.inv.items[this.emptyCell].maxStack - Inventory.inv.items[this.emptyCell].stack; Inventory.inv.items[this.emptyCell].stack = Inventory.inv.items[this.emptyCell].maxStack; } else { this.emptyCell = Inventory.inv.FindEmptyCell(); if (this.emptyCell >= 0) { this.cloneItem = Inventory.inv.CreateItem(this.craftObjects[curCraft]); if (this.cloneItem.maxStack >= this.iks) { this.cloneItem.stack = this.iks; Inventory.inv.items[this.emptyCell] = this.cloneItem; break; } this.cloneItem.stack = this.cloneItem.maxStack; this.iks -= this.cloneItem.maxStack; Inventory.inv.items[this.emptyCell] = this.cloneItem; } else { if (this.craftObjects[curCraft].GetComponent<Item>().maxStack >= this.iks) { PlayerNetwork.inst.CallCmdCreateItem(this.craftObjects[curCraft].name, Inventory.inv.transform.position - Vector3.forward * 2f + FloatingOrigin.offset, Quaternion.identity, this.iks, this.craftObjects[curCraft].GetComponent<Item>().health); break; } PlayerNetwork.inst.CallCmdCreateItem(this.craftObjects[curCraft].name, Inventory.inv.transform.position - Vector3.forward * 2f + FloatingOrigin.offset, Quaternion.identity, this.craftObjects[curCraft].GetComponent<Item>().maxStack, this.craftObjects[curCraft].GetComponent<Item>().health); this.iks -= this.craftObjects[curCraft].GetComponent<Item>().maxStack; } new WaitForEndOfFrame(); } } } } this.timeBreak = 0f; } } } Оригинальный public void CreateItem(int curCraft, int craftCount) { if (this.timeBreak >= 0.3f) { if (craftCount != 0) { this.succes = true; CraftRecipe component = this.craftObjects[curCraft].GetComponent<CraftRecipe>(); int[] array = new int[7]; int[] array2 = new int[7]; for (int i = 0; i < 7; i++) { if (this.succes && component.ingredients[i] != null) { array2[i] = component.countIngredients[i]; if (array2[i] <= 0) { array2[i] = 1; } array2[i] *= craftCount; for (int j = 0; j < Inventory.inv.items.Length; j++) { if (Inventory.inv.items[j] != null && component.ingredients[i].name == Inventory.inv.items[j].prefName) { array[i] += Inventory.inv.items[j].stack; } } if (array[i] < array2[i]) { this.succes = false; } } } if (this.succes) { for (int k = 0; k < 7; k++) { if (component.ingredients[k] != null) { for (int l = 0; l < Inventory.inv.items.Length; l++) { if (Inventory.inv.items[l] != null && array2[k] > 0 && component.ingredients[k].name == Inventory.inv.items[l].prefName) { this.iks = Inventory.inv.items[l].stack; Inventory.inv.items[l].stack -= array2[k]; array2[k] -= this.iks; if (array2[k] <= 0) { break; } } } } } this.iks = this.craftObjects[curCraft].GetComponent<CraftRecipe>().countCreate * craftCount; for (int m = 0; m < this.craftObjects[curCraft].GetComponent<CraftRecipe>().countCreate * craftCount; m++) { this.emptyCell = Inventory.inv.FindItemForStack(this.craftObjects[curCraft].name); if (this.emptyCell >= 0) { if (Inventory.inv.items[this.emptyCell].stack + this.iks <= Inventory.inv.items[this.emptyCell].maxStack) { Inventory.inv.items[this.emptyCell].stack += this.iks; break; } this.iks -= Inventory.inv.items[this.emptyCell].maxStack - Inventory.inv.items[this.emptyCell].stack; Inventory.inv.items[this.emptyCell].stack = Inventory.inv.items[this.emptyCell].maxStack; } else { this.emptyCell = Inventory.inv.FindEmptyCell(); if (this.emptyCell >= 0) { this.cloneItem = Inventory.inv.CreateItem(this.craftObjects[curCraft]); if (this.cloneItem.maxStack >= this.iks) { this.cloneItem.stack = this.iks; Inventory.inv.items[this.emptyCell] = this.cloneItem; break; } this.cloneItem.stack = this.cloneItem.maxStack; this.iks -= this.cloneItem.maxStack; Inventory.inv.items[this.emptyCell] = this.cloneItem; } else { if (this.craftObjects[curCraft].GetComponent<Item>().maxStack >= this.iks) { PlayerNetwork.inst.CallCmdCreateItem(this.craftObjects[curCraft].name, Inventory.inv.transform.position - Vector3.forward * 2f + FloatingOrigin.offset, Quaternion.identity, this.iks, this.craftObjects[curCraft].GetComponent<Item>().health); break; } PlayerNetwork.inst.CallCmdCreateItem(this.craftObjects[curCraft].name, Inventory.inv.transform.position - Vector3.forward * 2f + FloatingOrigin.offset, Quaternion.identity, this.craftObjects[curCraft].GetComponent<Item>().maxStack, this.craftObjects[curCraft].GetComponent<Item>().health); this.iks -= this.craftObjects[curCraft].GetComponent<Item>().maxStack; } new WaitForEndOfFrame(); } } } } this.timeBreak = 0f; } } Изменяем весь класс или метов в этом окне Если выводит ошибки при компяляции, то скачиваем IlSpy и его код вставляем в код в dnSpy. Или качаем DnSpy 3.2.0 или ранее Изменения сохраняем в модуль, запускаем игру и крафтим. Получить все рецепты (не проверял правда, попробуйте если хотите) Вещи не ломаются. Убрать отнятие "здоровья" у вещи
  • CE рисование через дополнительный поток

    Перенесена ce thread ce lua ce draw ce видео
    1
    0 Голоса
    1 Сообщения
    72 Просмотры
    MasterGHM
    На видео показано рисование через поток и рисование без потока CE Native Thread Когда происходит рисование без потока, то окно нельзя подвинуть, не работает кнопка и даже не возможно работать с Cheat Engine function FilledWithPixels() while true do ::begin:: UDF1.repaint() for x=1,UDF1.Canvas.Width do for y=1,UDF1.Canvas.Height do local min = math.random(1, 0xFFFF) local max = math.random(0xFFFF, 0x00FFFFFF) UDF1.Canvas.SetPixel(x,y, math.random (min, max)) if(needReUpdate) then needReUpdate = false goto begin end end end t.suspend() end end t = createNativeThreadSuspended(FilledWithPixels) t.name = 'New thread 1' needReUpdate = true UDF1 = createForm() UDF1.Width = 400 UDF1.Height = 200 btn = createButton(UDF1) btn.OnClick = function (sender) needReUpdate = true t.resume() end
  • Создать структуру программно

    Перенесена ce structure ce lua
    2
    2
    0 Голоса
    2 Сообщения
    118 Просмотры
    MasterGHM
    Решил попробовать написать CE Lua скрипт, который прочесывает структуру и в Dissect data/structures окне создавал бы структуру только со смещениями, с которыми код работает, т.е. читает или пишет. Например, мой персонаж прогуливается по городу, а каждые 200 мс ставится брейкпоинт на смещение +1 до гипотетической N границы структуры (например до 4096). Я не успел сделать определение типа, но смещения внутри структуры получить я успел. Итак, находим начало структуры любой. Запускаем Lua скрипт и просто что-то делаем в игре. Потом вылазит текст с дизассемблированными инструкциями и смещениями. Уже по этим логам можно определить вручную к каким смещением было обращение (адреса по ним мы и будем менять или сравнивать структуры между собой позже) по виду инструкции и соседнему смещению уже примерно можно определить тип данных и их размер Осталось сделать определение типа, а это не так уж долго сделать и осталось взять код из предыдущих записей в блоге формирования структуры в окне dessect data. Так мы получим структуру только с активными смещениями, (а зачем нам пассивные?) и определим в них тип, я надеюсь определим правильно Пример кода, который я использовал addressStructure1 = 0x412E0200 --> адрес начала структуры в любой игре sizeStructure = 100 --> гипототический размер структуры 100 для быстрых поисков, по умолчанию 4096 indexStructure = 0 --> индекс внутри структуры, который будет перемещаться вместе с breakPointAddress breakPointAddress = 0 --> адрес, на который сейчас постален брейкпоинт waitTimeTillBreak = 300 --> частота активности смещеиня resultText = '' --> конкатенация частей текста в этой переменной \-- Функция пытается поставить брейкпоинт на следующий байт в структуре function TryNextSetBreakPointToAddress() debug_removeBreakpoint(breakPointAddress) indexStructure = indexStructure + 1 if indexStructure > sizeStructure then debugTimer.Interval = 1000 debugTimer.Enabled = false debugTimer.destroy() debug_continueFromBreakpoint(co_run) print(resultText) --> вывод результата с завершением отладки return end breakPointAddress = addressStructure1 + indexStructure debug_setBreakpoint(breakPointAddress, 1, bptAccess, bpmDebugRegister) debug_continueFromBreakpoint(co_run) end \-- Любимая функция снятия отладочных данных function debugger_onBreakpoint() -- проверить обращение к структуре prevAddress = getPreviousOpcode(RIP) resultText = resultText..string.format('Offset: + %X : %s', indexStructure, disassemble(prevAddress)) .. '\r\n' TryNextSetBreakPointToAddress() return 1 end \-- Простой таймер debugTimer = createTimer(nil, false) debugTimer.OnTimer = function(timer) TryNextSetBreakPointToAddress() end debugTimer.Interval = waitTimeTillBreak debugTimer.Enabled = true breakPointAddress = addressStructure1 + indexStructure debug_setBreakpoint(breakPointAddress, 1, bptAccess, bpmDebugRegister)
Любое копирование материалов с указанием первоисточника.
СeLua[RU] 2026©