Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Auto Assembler Template Engine (compiled templates)

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Extensions
View previous topic :: View next topic  
Author Message
TheyCallMeTim13
Wiki Contributor
Reputation: 50

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Tue Dec 21, 2021 4:46 am    Post subject: Auto Assembler Template Engine (compiled templates) Reply with quote

Auto Assembler Template Engine ("compiled templates")

For Lua Script Templates see this post.

This is an auto assembler template engine that compiles/renders templates, the template engine is based off this blog post. You can access variables and run lua code in the templates using the appropriate tags. There are two file's you'll need to start; "TemplateEngine.lua" and "AutoAssemblerTemplates.lua". You can just stick them both in the "autorun" folder. And you'll need to create the "Templates\cea" Folder (in the "autorun" folder) for the templates. It uses "registerAutoAssemblerTemplate" when loading so they will be in the same menu as the standard CE auto assembler templates.

When CE loads, "AutoAssemblerTemplates" will scan the templates folder for "LoadOrder.lua" if found and it returns a table/array of file names it will load in that order; if not found is will scan the templates folder for any ".CEA" files. When it finds a template file it will also look for "[template file name].settings.lua", the settings file is not required but allows for more control of the template and menu items added to the auto assembler form. The settings file can return a table of the template's settings, but this is not required (more on why later).

For simple output you can use "<<" and ">>" tags, what ever is returned will be converted to string if not already and replace where the open and close tags are; these can be a called function, variable, or just a string/number. For lua code you can use "<%" and "%>" tags, these can be full lua code; thus you can set/create variables, use loops, and if statements.

For an archive with the needed files and one example template and setting file see this post else you can download the main files below.


Using a template file named "My basic template.CEA" like this:
Code:
// Cheat Engine Version: << getCEVersion() >>
<% print('This will print when rendered but will not render in the template.') %>
//------------------------------ ENABLE ------------------------------
[ENABLE]
<% local text = 'here is a local variable created in the template.' %>
<< text >> So that's pretty cool.

// if you need "\<<" or "\<%" to be in the rendered template then you need to escape them.
// A single "<" doesn't need to be escaped, nor do ">>" and "%>".
{$lua}
print('This is in the template and not processed when rendered.')
{$asm}
//------------------------------ DISABLE ------------------------------
[DISABLE]


It will show up in the auto assembler form's template menu as "My basic template" and render like this:
Code:
// Cheat Engine Version: 7.2

//------------------------------ ENABLE ------------------------------
[ENABLE]

here is a local variable created in the template. So that's pretty cool.

// if you need "<<" or "<%" to be in the rendered template then you need to escape them.
// A single "<" doesn't need to be escaped, nor do ">>" and "%>".
{$lua}
print('This is in the template and not processed when rendered.')
{$asm}
//------------------------------ DISABLE ------------------------------
[DISABLE]



There is another special file named "Header.CEA" which is rendered then passed to the template as "Header":
Code:

<< Header >>
// This allows for a common header without polluting the template file it self
// and can have lua code like the template files.
// But it will be a blank line if there's no header file.



For a settings file for "My basic template.CEA" we can create a file named "My basic template.settings.lua" like this:
Code:
local settings = {
   Caption = 'Custom: Basic Template',
   Shortcut = 'Ctrl+Alt+1',
}
return settings


Template settings are listed here:
Code:
Template Settings:
   Caption : string
      The caption of the template's menu item.
   Shortcut : string
      The shortcut of the template's menu item.
   AskForInjectionAddress : boolean
      Will prompt for a different address than the selected memory view lines if set to true.
      Allows the injection point to be offset from the AOB.
   AskForHookName : boolean
      Will prompt for a hook name if set to true.
   InjectionInfoLinesCount : number
      Will override the default number of lines in the "InjectionInfo" table.
   AppendToHookName : string
      Will be appended to the hook name if not already (if "AskForHookName" is true).
   WildCard : string/char
      Will override the default wild card if set.


The variables passed to the template, and settings file on final compilation, are listed here:
Code:
Template Variable:
   Address : number
      The address of the injection point.
   AddressString : string
      The address of the injection point as a string. It will be in "module+offset" or hex format.
   AobAddress : number
      The address of the AOB start (first selected line in the memory view form).
   AobAddressString : string
      Same as address but for "AobAddress".
   OriginalBytes : table/array : number
      A table of numbers (base 10) of the original bytes.
   OriginalBytesString : string
      A string of the original bytes in a "XX XX" (base 16) format.
   ModuleName : string
      A string of the module name if the injection point and full AOB is in a module.
   Signature : string
      The AOB in a signature format, for now it just removes hard coded address and 4 byte offsets.
   AOB : table/array : number
      A table of numbers (base 10) of the raw AOB.
   AobOffset : number
      The difference between "AobAddress" and "Address" or nil if they are the same.
   AobOffsetString : string
      The AOB offset in hex format with the appropriate sign (e.g.: "+10" or "-10").
      Or nil if there is no aob offset.
   PointerDefault : string
      Either "dd 0" or "dq 0" based on if the target is 64 bit.
   BaseAddressRegistry : string
      If opcode in the format of "[reg+n]" is found this would be set to "reg".
   OriginalOpcode : table/array : string
      A table of strings of the original opcode lines.
   InjectionInfo : table/array : string
      Disassembler lines before and after the injection point.
   NopBytes : table
      A table of numbers (base 10) of the nop bytes (i.e.: 0x90) for the injection point
      if it's not equal to 5 bytes. It will be an empty table if no nops are needed.
   NopBytesString : string
      The string of the nop bytes in a "XX XX" (base 16) format.
   CEVersion : number
      The current CE version.
   Date : string
      The current date.
   HookName : string
      If the template settings has "AskForHookName" set to true it will prompt for a hook name.
      Then title case the string (e.g.: "some test hook" will be come "Some Test Hook"),
      and set this to that.
   HookNameParsed : string
      If the template settings has "AskForHookName" set to true it will prompt for a hook name.
      Then title case and remove spaces in the string
      (e.g.: "some test hook" will be come "SomeTestHook"), and set this to that.
   FinalCompilation : boolean
      Only for the settings files as they get loaded once when CE loads then again at the start
      of template rendering to get the template settings, and again just before rendering the
      template but only on the last load will the environment be setup.
      So this is used to know if the environment is setup if more environment setup is done in
      the setting file.


Globals are accessible in the templates and settings files, but through a metatable thus they can not be set in a template or setting's file. But the environment variables can be manipulated in the settings file's directly during final compilation.

So say you don't like the signature that is generated and you just want to have a string of all the AOB bytes, but you don't want to do this in the template. You can use a settings file like this:
Code:
if FinalCompilation then
   local bs = ''
   for _, b in ipairs(AOB) do
      bs = bs..string.format('%02X ', b)
   end
   Signature = bs
end


The template will get the new signature when rendered. And any "globals" (not really globals and only exist in the template/settings environment) created in the settings file is passed to the template file.


Full Examples:

[spoiler=Example 1]
So if "GameTile", "GameFileVersion", and "GameVersion" globals aren't set; and you have a "Header.CEA" file like this:
Code:
{
   Process            : << process >>  -  << targetIs64Bit() and 'x64' or 'x32' >>
   Module            : << ModuleName >>
   Game Title         : << GameTitle >>
   Game File Version    : << GameFileVersion >>
   Game Version      : << GameVersion >>
   CE Version         : << CEVersion >>
   Script Version      : 1.0.1
   Date            : << Date >>
   Author            : TheyCallMeTim13
   Name            : << HookNameParsed >>

   << HookName >>
}


And a setting file like this (named "AobGetOpcodeAddress.settings.lua"):
Code:
if FinalCompilation then
   local instLenght = getInstructionSize(Address)
   OpcodeAddressOffset = instLenght - 4
end

local settings = {
   Caption = 'Custom: AOB Get Opcode Address',
   Shortcut = 'Ctrl+Alt+8',
   AskForInjectionAddress = true,
   AskForHookName = true,
   AppendToHookName = 'hook',
}
return settings


And a template file like this (named "AobGetOpcodeAddress.CEA"):
Code:
<< Header >>
{$STRICT}
define(address, << AddressString >>)
define(bytes, << OriginalBytesString >>)

////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]<% if ModuleName then %>
aobScanModule(aob<< HookNameParsed >>, << ModuleName >>, << Signature >>)<% else %>
aobScan(aob<< HookNameParsed >>, << Signature >>)<% end %><% if AobOffsetString then %>
define(inst<< HookNameParsed >>, aob<< HookNameParsed >><< AobOffsetString >>)<% else %>
define(inst<< HookNameParsed >>, aob<< HookNameParsed >>)<% end %>

getOpcodeAddress(ptr<< HookNameParsed >>, inst<< HookNameParsed >>+<< OpcodeAddressOffset >>)
registerSymbol(ptr<< HookNameParsed >>)


////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
unregisterSymbol(inst<< HookNameParsed >>)
unregisterSymbol(ptr<< HookNameParsed >>)
{<% if ModuleName then %>
Module: << ModuleName >>
<% end %>Address: << AddressString >>
AOB Address: << AobAddressString >><% for i, line in ipairs(InjectionInfo) do %>
<< line >><% end %>
}


And you select these lines in the memory view form (CE x64 tutorial step 2):
Code:
Tutorial-x86_64.exe+2B3A9 - 81 BB F0070000 E8030000 - cmp [rbx+000007F0],000003E8 { 1000 }
Tutorial-x86_64.exe+2B3B3 - 75 33                 - jne Tutorial-x86_64.exe+2B3E8
Tutorial-x86_64.exe+2B3B5 - 48 8B 8B C0070000     - mov rcx,[rbx+000007C0]
Tutorial-x86_64.exe+2B3BC - B2 01                 - mov dl,01 { 1 }


And open the auto assembler form ("Ctrl+A"), and select the "Custom: AOB Get Opcode Address" menu item or press "Ctrl+Alt+8". When prompted for the injection address hit enter (keep first selected line) then when prompted for a hook name you enter "tutorial step 2". You'll get a rendered template like this:
Code:
{
   Process            : Tutorial-x86_64.exe  -  x64
   Module            : Tutorial-x86_64.exe
   Game Title         :
   Game File Version    :
   Game Version      :
   CE Version         : 7.2
   Script Version      : 1.0.1
   Date            : 12/21/21
   Author            : TheyCallMeTim13
   Name            : TutorialStep2Hook

   Tutorial Step 2 Hook
}
{$STRICT}
define(address, Tutorial-x86_64.exe+2B3A9)
define(bytes, 81 BB F0 07 00 00 E8 03 00 00)

////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]
aobScanModule(aobTutorialStep2Hook, Tutorial-x86_64.exe, 81BBF0070000xxxxxxxx7533488B8BxxxxxxxxB201)
define(instTutorialStep2Hook, aobTutorialStep2Hook)

getOpcodeAddress(ptrTutorialStep2Hook, instTutorialStep2Hook+6)
registerSymbol(ptrTutorialStep2Hook)


////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
unregisterSymbol(instTutorialStep2Hook)
unregisterSymbol(ptrTutorialStep2Hook)
{
Module: Tutorial-x86_64.exe
Address: Tutorial-x86_64.exe+2B3A9
AOB Address: Tutorial-x86_64.exe+2B3A9
Tutorial-x86_64.exe+2B392 - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B394 - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B396 - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B398 - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B39A - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B39C - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B39E - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B3A0 - 53                - push rbx
Tutorial-x86_64.exe+2B3A1 - 48 8D 64 24 E0    - lea rsp,[rsp-20]
Tutorial-x86_64.exe+2B3A6 - 48 89 CB          - mov rbx,rcx
Tutorial-x86_64.exe+2B3A9 - 81 BB F0070000 E8030000- cmp [rbx+000007F0],000003E8   <<<---- Injection point
Tutorial-x86_64.exe+2B3B3 - 75 33             - jne Tutorial-x86_64.exe+2B3E8
Tutorial-x86_64.exe+2B3B5 - 48 8B 8B C0070000 - mov rcx,[rbx+000007C0]
Tutorial-x86_64.exe+2B3BC - B2 01             - mov dl,01
Tutorial-x86_64.exe+2B3BE - 48 8B 83 C0070000 - mov rax,[rbx+000007C0]
Tutorial-x86_64.exe+2B3C5 - 48 8B 00          - mov rax,[rax]
Tutorial-x86_64.exe+2B3C8 - FF 90 40040000    - call qword ptr [rax+00000440]
Tutorial-x86_64.exe+2B3CE - 48 8B 8B E0070000 - mov rcx,[rbx+000007E0]
Tutorial-x86_64.exe+2B3D5 - 30 D2             - xor dl,dl
Tutorial-x86_64.exe+2B3D7 - 48 8B 83 E0070000 - mov rax,[rbx+000007E0]
Tutorial-x86_64.exe+2B3DE - 48 8B 00          - mov rax,[rax]
}

[/spoiler]

[spoiler=Example 2]
With the same header file as example 1.

And a setting file like this (named "AobFullInjection.settings.lua"):
Code:
local settings = {
   Caption = 'Custom: AOB Full Injection',
   Shortcut = 'Ctrl+Alt+6',
   AskForInjectionAddress = true,
   AskForHookName = true,
   AppendToHookName = 'hook',
}
return settings


And a template file like this (named "AobFullInjection.CEA"):
Code:
<< Header >>
{$STRICT}
define(address, << AddressString >>)
define(bytes, << OriginalBytesString >>)

////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]<% if ModuleName then %>
aobScanModule(aob<< HookNameParsed >>, << ModuleName >>, << Signature >>)<% else %>
aobScan(aob<< HookNameParsed >>, << Signature >>)<% end %><% if AobOffsetString then %>
define(inj<< HookNameParsed >>, aob<< HookNameParsed >><< AobOffsetString >>)<% else %>
define(inj<< HookNameParsed >>, aob<< HookNameParsed >>)<% end %>

assert(inj<< HookNameParsed >>, bytes)
registerSymbol(inj<< HookNameParsed >>)

alloc(mem<< HookNameParsed >>, 0x400, inj<< HookNameParsed >>)

label(ptr<< HookNameParsed >>)
registerSymbol(ptr<< HookNameParsed >>)

label(n_code)
label(o_code)
label(exit)
label(return)

mem<< HookNameParsed >>:
   ptr<< HookNameParsed >>:
      << PointerDefault >>
   align 10 CC
   n_code:
      mov [ptr<< HookNameParsed >>],<< BaseAddressRegistry >>
   o_code:<% for i, line in ipairs(OriginalOpcode) do %>
      << line >><% end %>
   exit:
      jmp return


////
//// ---------- Injection Point ----------
inj<< HookNameParsed >>:
   jmp n_code<% for _, _ in ipairs(NopBytes) do %>
      nop<% end %>
   return:


////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
////
//// ---------- Injection Point ----------
inj<< HookNameParsed >>:
   db bytes

unregisterSymbol(inj<< HookNameParsed >>)

unregisterSymbol(ptr<< HookNameParsed >>)

dealloc(mem<< HookNameParsed >>)
{<% if ModuleName then %>
Module: << ModuleName >>
<% end %>Address: << AddressString >>
AOB Address: << AobAddressString >><% for i, line in ipairs(InjectionInfo) do %>
<< line >><% end %>
}


And you select these lines in the memory view form (CE x64 tutorial step 2):
Code:
Tutorial-x86_64.exe+2B3A6 - 48 89 CB              - mov rbx,rcx
Tutorial-x86_64.exe+2B3A9 - 81 BB F0070000 E8030000 - cmp [rbx+000007F0],000003E8 { 1000 }
Tutorial-x86_64.exe+2B3B3 - 75 33                 - jne Tutorial-x86_64.exe+2B3E8
Tutorial-x86_64.exe+2B3B5 - 48 8B 8B C0070000     - mov rcx,[rbx+000007C0]
Tutorial-x86_64.exe+2B3BC - B2 01                 - mov dl,01 { 1 }


And open the auto assembler form ("Ctrl+A"), and select the "Custom: AOB Full Injection" menu item or press "Ctrl+Alt+6". When prompted for the injection address you enter this address "Tutorial-x86_64.exe+2B3A9" then when prompted for a hook name you enter "tutorial step 2". You'll get a rendered template like this:
Code:
{
   Process            : Tutorial-x86_64.exe  -  x64
   Module            : Tutorial-x86_64.exe
   Game Title         :
   Game File Version    :
   Game Version      :
   CE Version         : 7.2
   Script Version      : 1.0.1
   Date            : 12/21/21
   Author            : TheyCallMeTim13
   Name            : TutorialStep2Hook

   Tutorial Step 2 Hook
}
{$STRICT}
define(address, Tutorial-x86_64.exe+2B3A9)
define(bytes, 81 BB F0 07 00 00 E8 03 00 00)

////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]
aobScanModule(aobTutorialStep2Hook, Tutorial-x86_64.exe, 4889CB81BBF0070000xxxxxxxx7533488B8BxxxxxxxxB201)
define(injTutorialStep2Hook, aobTutorialStep2Hook+3)

assert(injTutorialStep2Hook, bytes)
registerSymbol(injTutorialStep2Hook)

alloc(memTutorialStep2Hook, 0x400, injTutorialStep2Hook)

label(ptrTutorialStep2Hook)
registerSymbol(ptrTutorialStep2Hook)

label(n_code)
label(o_code)
label(exit)
label(return)

memTutorialStep2Hook:
   ptrTutorialStep2Hook:
      dq 0
   align 10 CC
   n_code:
      mov [ptrTutorialStep2Hook],rbx
   o_code:
      cmp [rbx+000007F0],000003E8
   exit:
      jmp return


////
//// ---------- Injection Point ----------
injTutorialStep2Hook:
   jmp n_code
      nop
      nop
      nop
      nop
      nop
   return:


////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
////
//// ---------- Injection Point ----------
injTutorialStep2Hook:
   db bytes

unregisterSymbol(injTutorialStep2Hook)

unregisterSymbol(ptrTutorialStep2Hook)

dealloc(memTutorialStep2Hook)
{
Module: Tutorial-x86_64.exe
Address: Tutorial-x86_64.exe+2B3A9
AOB Address: Tutorial-x86_64.exe+2B3A6
Tutorial-x86_64.exe+2B392 - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B394 - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B396 - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B398 - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B39A - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B39C - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B39E - 00 00             - add [rax],al
Tutorial-x86_64.exe+2B3A0 - 53                - push rbx
Tutorial-x86_64.exe+2B3A1 - 48 8D 64 24 E0    - lea rsp,[rsp-20]
Tutorial-x86_64.exe+2B3A6 - 48 89 CB          - mov rbx,rcx   <<<---- AOB
Tutorial-x86_64.exe+2B3A9 - 81 BB F0070000 E8030000- cmp [rbx+000007F0],000003E8   <<<---- Injection point
Tutorial-x86_64.exe+2B3B3 - 75 33             - jne Tutorial-x86_64.exe+2B3E8
Tutorial-x86_64.exe+2B3B5 - 48 8B 8B C0070000 - mov rcx,[rbx+000007C0]
Tutorial-x86_64.exe+2B3BC - B2 01             - mov dl,01
Tutorial-x86_64.exe+2B3BE - 48 8B 83 C0070000 - mov rax,[rbx+000007C0]
Tutorial-x86_64.exe+2B3C5 - 48 8B 00          - mov rax,[rax]
Tutorial-x86_64.exe+2B3C8 - FF 90 40040000    - call qword ptr [rax+00000440]
Tutorial-x86_64.exe+2B3CE - 48 8B 8B E0070000 - mov rcx,[rbx+000007E0]
Tutorial-x86_64.exe+2B3D5 - 30 D2             - xor dl,dl
Tutorial-x86_64.exe+2B3D7 - 48 8B 83 E0070000 - mov rax,[rbx+000007E0]
Tutorial-x86_64.exe+2B3DE - 48 8B 00          - mov rax,[rax]
}

[/spoiler]



AutoAssemblerTemplates.lua
 Description:

Download
 Filename:  AutoAssemblerTemplates.lua
 Filesize:  13.38 KB
 Downloaded:  862 Time(s)


TemplateEngine.lua
 Description:

Download
 Filename:  TemplateEngine.lua
 Filesize:  3.89 KB
 Downloaded:  812 Time(s)


_________________


Last edited by TheyCallMeTim13 on Sun Feb 20, 2022 6:17 pm; edited 5 times in total
Back to top
View user's profile Send private message Visit poster's website
Csimbi
I post too much
Reputation: 92

Joined: 14 Jul 2007
Posts: 3102

PostPosted: Tue Dec 21, 2021 10:13 am    Post subject: Reply with quote

Nice proof of concept, good work!
However, I am used to this one, here.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 50

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Tue Dec 21, 2021 11:35 am    Post subject: Reply with quote

Csimbi wrote:
Nice proof of concept, good work!
However, I am used to this one, here.


Yeah this one is a little overkill. It grew out of the idea to simplify my old one and just see if I could do it. Plus I disliked having so much of the formating setup outside of the template (like the nops and original code), like the older one I have based off the one you linked to. And I like having the templates as separate files so I get syntax highlighting, instead of all the templates being in multiline strings. Plus updates don't require you to re-add your templates, so long as the tag format stays the same you just update the modules and your templates stay the same. This also lets you customize a lot more. Try adding an input query or new variable to that one or my older one, you'd have to code it in the renderer itself. But with this new one you can do it in the settings file, or just add it directly to the template. Hell you can access the template engine so you could render a sub template directly in the template if you wanted, no idea why but it could be done. And I never really got the reason for the tags like:
Code:
<<INFO>>
<<INFO_END>>

<<ENABLE>>
<<ENABLE_END>>

<<DISABLE>>
<<DISABLE_END>>


I just think it's neat, and I like that if I want to add say "TimerInterval" to the template all it takes is something like this:
Code:
<% local TimerInterval = inputQuery('Timer Interval', 'Enter timer interval', '100') %>
<< TimerInterval >>


You can even add notes that don't end up in the rendered template, e.g.:
Code:
<% -- TODO: ??? %>


But yeah in the end it's really whatever works better for you that counts. The main problem I have with this one right now is the error messages if there is an error in the templates lua code, the line numbers are based on the render and not the template file. Forgot a "then" in one with 20 lines and had an error message saying it was on line 27.

_________________
Back to top
View user's profile Send private message Visit poster's website
DeRol
Newbie cheater
Reputation: 0

Joined: 26 Aug 2009
Posts: 18

PostPosted: Sun Mar 12, 2023 2:45 am    Post subject: Reply with quote

This looks very nice.

As I was tediously updating my copy of customAOBInjectionTemplates.lua and migrating over the myriad of templates, I was just thinking how nice it would be to have them as separate files for the reasons you've stated.

I'll have to wrap my head around this a bit more to figure out how to migrate my current templates over.

My dream setup would be to have a sort of template editor Form where it would show a live or generated preview as I made changes and moved variables around. Almost like a WYSIWYG. Way beyond me though.

edit:
Oooo. I like that I can edit the templates and use them right away without needing to restart Cheat Engine. Smile

@TheyCallMeTim13
A Question:
Does this allow organizing the templates it finds into submenus like you can with customAOBInjectionTemplates.lua ?
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 92

Joined: 14 Jul 2007
Posts: 3102

PostPosted: Sun Mar 12, 2023 7:06 am    Post subject: Reply with quote

DeRol wrote:

My dream setup would be to have a sort of template editor Form where it would show a live or generated preview as I made changes and moved variables around. Almost like a WYSIWYG. Way beyond me though.

There is no lack of requirements Wink
Back to top
View user's profile Send private message
DeRol
Newbie cheater
Reputation: 0

Joined: 26 Aug 2009
Posts: 18

PostPosted: Tue Mar 14, 2023 4:09 pm    Post subject: Reply with quote

Csimbi wrote:
DeRol wrote:

My dream setup would be to have a sort of template editor Form where it would show a live or generated preview as I made changes and moved variables around. Almost like a WYSIWYG. Way beyond me though.

There is no lack of requirements Wink


Lofty goals Very Happy

Right now, I'm using both extensions in tandem while I try to put together some sort of template for myself that I can run to remind me what variable names are what.

With this extension though, I almost don't need to since I can do something like:
Code:

<% cheatname=HookNameParsed %>
<< cheatname >>


Then I could use that name in my template. I could match it up to the other extension's var names with this method as well if I didn't want to rewrite.
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 92

Joined: 14 Jul 2007
Posts: 3102

PostPosted: Wed Mar 15, 2023 1:55 pm    Post subject: Reply with quote

That rewrite part is what's keeping me ...
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Extensions All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites