|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Punz1A4 Cheater Reputation: 0
Joined: 10 Jun 2016 Posts: 25
|
Posted: Sat Jan 14, 2017 2:59 pm Post subject: CE crashes when activating lua hotkey script with a hotkey |
|
|
The title may not make much sense because I didn't wanted to make it long.
When using the "Set hotkeys function" to set a hotkey for a AA script that has lua function, using that hotkey crashes CE when said lua function uses createHotkey function.
Two examples of different scripts that both crash CE when activating them via hotkey.
Code: |
[ENABLE]
alloc(giveItemID,1)
registersymbol(giveItemID)
giveItemID:
db 35 // initialized with Dark Metter ID (here in hex)
{$Lua}
function readShortInt(address)
return bAnd(0xFF,readInteger(address)) --bitwise and with 1111 1111 because readInteger reads from 4 bytes
end
function amountIncreaseHotkeyFunc(hk)
local x=readShortInt("FFX.exe+D30B5C")
if x then writeBytes("FFX.exe+D30B5C",x+10) end
end
function amountDescraseHotkeyFunc(hk)
local x=readShortInt("FFX.exe+D30B5C")
if x then writeBytes("FFX.exe+D30B5C",x-10) end
end
function maxAmountHotkeyFunc(hk)
--writeBytes("FFX.exe+D30B5C",99) --maxes only to the 1st slot
maxAllItemsInInv() --maxes amount of all items in inventory
end
function addItemHotkeyFunc(hk)
addItem(readBytes("giveItemID",1))
end
function addItem(itemID)
local offset1=0xD3095A
local offset2=0xD3095B
local quantityOffset=0xD30B5B
for i=0, 111 do
offset1=offset1+0x2
offset2=offset2+0x2
quantityOffset=quantityOffset+0x1
local str=string.format("FFX.exe+%X",offset1)
local str2=string.format("FFX.exe+%X",offset2)
local quantityStr=string.format("FFX.exe+%X",quantityOffset)
if (readBytes(str,1)==0xFF and readBytes(str2,1)==0x0) then writeBytes(str,itemID); writeBytes(str2,32); writeBytes(quantityStr,99); break end
end
end
function maxAllItemsInInv()
local offset1=0xD3095A
local offset2=0xD3095B
local quantityOffset=0xD30B5B
for i=0, 111 do
offset1=offset1+0x2
offset2=offset2+0x2
quantityOffset=quantityOffset+0x1
local str=string.format("FFX.exe+%X",offset1)
local str2=string.format("FFX.exe+%X",offset2)
local quantityStr=string.format("FFX.exe+%X",quantityOffset)
if (readBytes(str,1)~=0xFF and readBytes(str2,1)~=0x0) then writeBytes(quantityStr,99) end
end
end
--0x200
--0x1FF
amountIncreaseHotkey = createHotkey(amountIncreaseHotkeyFunc,VK_ADD)
amountIncreaseHotkey.DelayBetweenActivate = 200
amountDecraseHotkey = createHotkey(amountDescraseHotkeyFunc,VK_SUBTRACT)
amountDecraseHotkey.DelayBetweenActivate = 200
maxAmountHotkey = createHotkey(maxAmountHotkeyFunc,VK_MULTIPLY)
maxAmountHotkey.DelayBetweenActivate = 200
addItemHotkey = createHotkey(addItemHotkeyFunc,VK_DIVIDE)
addItemHotkey.DelayBetweenActivate = 200
{$asm}
[DISABLE]
dealloc(giveItemID)
unregistersymbol(giveItemID)
{$Lua}
if amountIncreaseHotkey~=nil then amountIncreaseHotkey.destroy(); amountIncreaseHotkey=nil end
if amountDecraseHotkey~=nil then amountDecraseHotkey.destroy(); amountDecraseHotkey=nil end
if maxAmountHotkey~=nil then maxAmountHotkey.destroy(); maxAmountHotkey=nil end
if addItemHotkey~=nil then addItemHotkey.destroy(); addItemHotkey=nil end
|
Code: | [ENABLE]
aobscanmodule(INJECT1,FFX.exe,8B 19 5F 5E 8B C3) // should be unique
alloc(newmem,$1000)
label(code)
label(return)
label(original_code)
alloc(time_address,4)
registersymbol(time_address)
time_address:
dd 0
newmem:
code:
cmp [ecx-B4],FFFFFFFF
jne @f
push eax
lea eax,[ecx+84]
mov [time_address],eax
pop eax
mov [ecx],#9999
{ mov [ecx-98],#99 //player stats during encounter (includes enemies)
mov [ecx-94],#99
mov [ecx-90],#99}
mov [ecx+20C],#99 //EN
mov [ecx+28C],#99 //PA
mov [ecx+30C],#99 //SH
mov [ecx+38C],#99 //BL
mov [ecx+44C],#100 //SPD
mov [ecx+18C],#99 //AT
@@:
cmp [ecx-B8],FFFFFFFF
jne @f
mov [ecx],#9999
mov [ecx+20C],#99
mov [ecx+28C],#99
mov [ecx+30C],#99
mov [ecx+38C],#99
mov [ecx+44C],#100
mov [ecx+18C],#99
@@:
cmp [ecx-BC],FFFFFFFF
jne @f
mov [ecx],#9999
mov [ecx+20C],#99
mov [ecx+28C],#99
mov [ecx+30C],#99
mov [ecx+38C],#99
mov [ecx+44C],#100
mov [ecx+18C],#99
@@:
cmp [ecx-C0],FFFFFFFF
jne @f
mov [ecx],#9999
mov [ecx+20C],#99
mov [ecx+28C],#99
mov [ecx+30C],#99
mov [ecx+38C],#99
mov [ecx+44C],#100
mov [ecx+18C],#99
@@:
cmp [ecx-C4],FFFFFFFF
jne @f
mov [ecx],#9999
mov [ecx+20C],#99
mov [ecx+28C],#99
mov [ecx+30C],#99
mov [ecx+38C],#99
mov [ecx+44C],#100
mov [ecx+18C],#99
@@:
cmp [ecx-C8],FFFFFFFF
jne original_code
mov [ecx+3CC],#99 //Goalkeeper's CAT
original_code:
mov ebx,[ecx]
pop edi
pop esi
mov eax,ebx
jmp return
INJECT1:
jmp newmem
nop
return:
registersymbol(INJECT1)
{$lua}
function halfTime(hk)
writeInteger("[time_address]",298)
end
halfTimeHotkey = createHotkey(halfTime,VK_0)
halfTimeHotkey.DelayBetweenActivate = 500
{$asm}
[DISABLE]
INJECT1:
db 8B 19 5F 5E 8B C3
unregistersymbol(time_address)
dealloc(time_address)
unregistersymbol(INJECT1)
dealloc(newmem)
{$lua}
if halfTimeHotkey~=nil then halfTimeHotkey.destroy(); halfTimeHotkey=nil end
{$asm}
{
// ORIGINAL CODE - INJECTION POINT: "FFX.exe"+46C71F
...} |
I'm using CE 6.6
|
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Sat Jan 14, 2017 4:13 pm Post subject: |
|
|
It is a known problem. You are creating a new hotkey while inside OnHotkey function of other hotkey.
Code: | function myTimerOnHotkey()
newHotkey = createHotkey(nil,nil)
end
myTimer = createHotkey(myTimerOnHotkey,VK_0)
|
You can execute above Lua script. Pressing 0 will freeze CE.
Workaround:
Code: | function myTimerOnHotkey()
createTimer(nil).OnTimer =
function(t) newHotkey = createHotkey(nil,nil) ; t.destroy() end
end
myTimer = createHotkey(myTimerOnHotkey,VK_0) |
_________________
|
|
Back to top |
|
|
Punz1A4 Cheater Reputation: 0
Joined: 10 Jun 2016 Posts: 25
|
Posted: Sat Jan 14, 2017 9:07 pm Post subject: |
|
|
Thanks, though I still have questions - since the newHotkey variable is within the scope of myTimerOnHotkey function, how can I deactivate the newHotkey via pressing '0' again (or any other button I'd assign for disabling)?
For example in the code below typeStr won't activate until I press '0' but afterwards typeStr will activate even if I manually deactivate the whole script because newHotkey still exists and trying to execute newHotkey.destroy() does nothing
Code: | {$lua}
[ENABLE]
function myTimerOnHotkey()
createTimer(nil).OnTimer =
function(t) newHotkey = createHotkey(typeStr,VK_T) ; t.destroy() end
end
function typeStr()
print("Wassup")
end
myTimer = createHotkey(myTimerOnHotkey,VK_0)
[DISABLE]
if myTimer~=nil then myTimer.destroy(); myTimer=nil end |
|
|
Back to top |
|
|
Zanzer I post too much Reputation: 126
Joined: 09 Jun 2013 Posts: 3278
|
Posted: Sat Jan 14, 2017 9:49 pm Post subject: |
|
|
No, "newHotkey" is declared global and is accessible from the [DISABLE] script.
Might I also suggest you simply add a new memory record to the table instead.
Give it the address "FFX.exe+D30B5C" and set your hotkeys directly on the record.
Give it the hotkey "+" and set it to "Increase value with:" and specify "10".
edit: Actually, you'll need to declare a new custom variable and use that in the memory record.
That way, when you disable the script and unregister the variable, the hotkeys simply won't work. Code: | [ENABLE]
label(myvar)
FFX.exe+D30B5C:
myvar:
registersymbol(myvar)
[DISABLE]
unregistersymbol(myvar) |
|
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Sun Jan 15, 2017 6:36 am Post subject: |
|
|
My example was written in Lua only. Just to give you the idea that creating hotkey while other hotkey is executing, is a bad idea.
If you have memory record (address list entry) with a hotkey (added via "set/change hotkey" window), and this memory record is AA script with embedded Lua script, you better do not create new hotkeys there. It will fail if you activate this memory record with a hotkey. You can activate it with mouse only (you can also highlight entry and press space).
To summarize:
- do not create a new hotkey inside OnHotkey function of other hotkey, it will fail - CE will freeze.
- do not create a new hotkey inside "AA script with embedded Lua script", it will fail if you activate it with a hotkey
- the same applies when destroying a hotkey
The workaround is to use a timer object.
Now, here example for AA script with embedded Lua script, plus workaround mentioned earlier:
Code: | [ENABLE]
// asm here
{$lua}
-- lua here
function typeStr()
print("Wassup")
end
createTimer(nil).OnTimer =
function(t) newHotkey = createHotkey(typeStr,VK_T) ; t.destroy() end
{$asm}
[DISABLE]
// asm here
{$lua}
-- lua here
createTimer(nil).OnTimer =
function(t) if newHotkey~=nil then newHotkey.destroy(); newHotkey=nil end ; t.destroy() end
{$asm}
|
Edit:
Code above (with workaround) has a downside, it uses default interval value (which is 1 second).
Here more advanced script (it creates timer object and reuses it):
Code: | [ENABLE]
{$Lua}
function amountIncreaseHotkeyFunc(hk)
--snip
end
function amountDescraseHotkeyFunc(hk)
--snip
end
function maxAmountHotkeyFunc(hk)
--snip
end
function addItemHotkeyFunc(hk)
--snip
end
-- use timerObjectUsedToCreateDestroyHotkeys only for this AA script
-- for other AA scripts use timerObjectUsedToCreateDestroyHotkeysOtherName
if timerObjectUsedToCreateDestroyHotkeys==nil then
timerObjectUsedToCreateDestroyHotkeys = createTimer(nil,false)
timerObjectUsedToCreateDestroyHotkeys.Interval=1
end
timerObjectUsedToCreateDestroyHotkeys.OnTimer = function (t)
t.Enabled = false
amountIncreaseHotkey = createHotkey(amountIncreaseHotkeyFunc,VK_ADD)
amountIncreaseHotkey.DelayBetweenActivate = 200
amountDecraseHotkey = createHotkey(amountDescraseHotkeyFunc,VK_SUBTRACT)
amountDecraseHotkey.DelayBetweenActivate = 200
maxAmountHotkey = createHotkey(maxAmountHotkeyFunc,VK_MULTIPLY)
maxAmountHotkey.DelayBetweenActivate = 200
addItemHotkey = createHotkey(addItemHotkeyFunc,VK_DIVIDE)
addItemHotkey.DelayBetweenActivate = 200
end
timerObjectUsedToCreateDestroyHotkeys.Enabled = true
{$Asm}
[DISABLE]
{$Lua}
timerObjectUsedToCreateDestroyHotkeys.OnTimer = function (t)
t.Enabled = false
if amountIncreaseHotkey~=nil then amountIncreaseHotkey.destroy(); amountIncreaseHotkey=nil end
if amountDecraseHotkey~=nil then amountDecraseHotkey.destroy(); amountDecraseHotkey=nil end
if maxAmountHotkey~=nil then maxAmountHotkey.destroy(); maxAmountHotkey=nil end
if addItemHotkey~=nil then addItemHotkey.destroy(); addItemHotkey=nil end
end
timerObjectUsedToCreateDestroyHotkeys.Enabled = true
{$Asm} |
PS:
Quote: | since the newHotkey variable is within the scope of myTimerOnHotkey function |
Code: | function test(a,b)
local c=12
d=34
end |
a and b are arguments
c is within the scope of test function
d is global
test function is global
_________________
|
|
Back to top |
|
|
Punz1A4 Cheater Reputation: 0
Joined: 10 Jun 2016 Posts: 25
|
Posted: Sun Jan 15, 2017 12:09 pm Post subject: |
|
|
Zanzer wrote: | No, "newHotkey" is declared global and is accessible from the [DISABLE] script. |
Right, at first I thought it wasn't because newHotkey.destroy() didn't work without wrapping it with Code: | createTimer(nil).OnTimer =
function(t) ... end |
Zanzer wrote: |
Might I also suggest you simply add a new memory record to the table instead.
Give it the address "FFX.exe+D30B5C" and set your hotkeys directly on the record.
Give it the hotkey "+" and set it to "Increase value with:" and specify "10".
edit: Actually, you'll need to declare a new custom variable and use that in the memory record.
That way, when you disable the script and unregister the variable, the hotkeys simply won't work. Code: | [ENABLE]
label(myvar)
FFX.exe+D30B5C:
myvar:
registersymbol(myvar)
[DISABLE]
unregistersymbol(myvar) |
|
Thanks for mentioning it, didn't know CE had this feature
mgr.inz.Player wrote: | ... |
Thanks for taking the time and explaining stuff, really appreciate it
Everything works fine with this implementation, though I don't quite understand what the 't' timer is (the thing you are disabling right after calling onTimer function)? If I understand correctly, the function(t) is called when t triggers but when/how does it happen since there is no 't' declared in the code?
|
|
Back to top |
|
|
Zanzer I post too much Reputation: 126
Joined: 09 Jun 2013 Posts: 3278
|
Posted: Sun Jan 15, 2017 12:56 pm Post subject: |
|
|
The variable "t" is defined as the first parameter to the OnTimer function.
When the timer triggers, it passes the timer object to the function.
So your variable "t" now contains the timer object itself.
|
|
Back to top |
|
|
Punz1A4 Cheater Reputation: 0
Joined: 10 Jun 2016 Posts: 25
|
Posted: Sun Jan 15, 2017 2:12 pm Post subject: |
|
|
Makes sense, thanks
|
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Sun Jan 15, 2017 3:12 pm Post subject: |
|
|
Indeed. What looks better, this:
Code: | timerObjectUsedToCreateDestroyHotkeys.OnTimer = function (t)
t.Enabled = false
...
end |
Or this:
Code: | timerObjectUsedToCreateDestroyHotkeys.OnTimer = function ()
timerObjectUsedToCreateDestroyHotkeys.Enabled = false
...
end |
_________________
|
|
Back to top |
|
|
|
|
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
|
|