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 


CE crashes when activating lua hotkey script with a hotkey

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
Punz1A4
Cheater
Reputation: 0

Joined: 10 Jun 2016
Posts: 25

PostPosted: Sat Jan 14, 2017 2:59 pm    Post subject: CE crashes when activating lua hotkey script with a hotkey Reply with quote

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
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 218

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sat Jan 14, 2017 4:13 pm    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
Punz1A4
Cheater
Reputation: 0

Joined: 10 Jun 2016
Posts: 25

PostPosted: Sat Jan 14, 2017 9:07 pm    Post subject: Reply with quote

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
View user's profile Send private message
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Sat Jan 14, 2017 9:49 pm    Post subject: Reply with quote

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
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 218

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sun Jan 15, 2017 6:36 am    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
Punz1A4
Cheater
Reputation: 0

Joined: 10 Jun 2016
Posts: 25

PostPosted: Sun Jan 15, 2017 12:09 pm    Post subject: Reply with quote

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 Very Happy

mgr.inz.Player wrote:
...

Thanks for taking the time and explaining stuff, really appreciate it Very Happy
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
View user's profile Send private message
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Sun Jan 15, 2017 12:56 pm    Post subject: Reply with quote

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
View user's profile Send private message
Punz1A4
Cheater
Reputation: 0

Joined: 10 Jun 2016
Posts: 25

PostPosted: Sun Jan 15, 2017 2:12 pm    Post subject: Reply with quote

Makes sense, thanks Smile
Back to top
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 218

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sun Jan 15, 2017 3:12 pm    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine 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