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 


Free fly camera lag on calculations or timer?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Wed Feb 21, 2018 9:56 am    Post subject: Free fly camera lag on calculations or timer? Reply with quote

Hi!

With different implementations of free camera calculations i'm noticed tiny lags when i move camera, but i can't understand where exactly problem is. Those lags looks like this: when i press forward hotkey (or any other direction) it moving camera where it should be, but pretty often it making very tiny "jumps" mostly where camera should go, but sometimes it can make jumps to right, left or vice versa direction. Jumps are very tiny, but still noticeable and even if it looks good for just fly around and taking screenshots, for video recording it is bad and also i want to learn my mistake. It also looks like frame drops in video.

Here is basic code. I post just part of it, for moving to one direction, but in such case it cause lags too:
Code:

{$lua}

[ENABLE]

function checkKeys(timer)

local camx = readFloat("[[[Game.exe+4B18798]+A8]+0]+60") -- Camera X position
local camy = readFloat("[[[Game.exe+4B18798]+A8]+0]+64") -- Camera Y position
local radh = readFloat("[[[[Game.exe+4B18798]+A8]+0]+340]+C4") -- Camera horizontal rotations in rad

local sinh = math.sin(radh) -- calculate sin/cos of rotations
local cosh = math.cos(radh)


  if isKeyPressed(VK_W) then  -- move Forward
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+60", camx - (sinh * 0.15))
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+64", camy - (cosh * 0.15))
  elseif isKeyPressed(VK_S) then  -- move Back
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+60", camx + (sinh * 0.15))
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+64", camy + (cosh * 0.15))
  end

end

t=createTimer(nil)
timer_setInterval(t, 30)
timer_onTimer(t, checkKeys)
timer_setEnabled(t, true)

[DISABLE]

timer_setEnabled(t, false)


I think that timer, probably, is good here. Yes, i copy-pasted it from web, it have obsolete syntax, but in another game, where i made some kind of free camera by sending value for character speed by XYZ directions and with the same timer it no have any lags:

Code:

{$lua}

[ENABLE]

function checkKeys(timer)

  if isKeyPressed(VK_W) then
    writeFloat("[[anotherGame.exe+01E855C0]+E0]+150", 1) -- if W pressed, than send "1" to speed forward
  elseif isKeyPressed(VK_S) then
    writeFloat("[[anotherGame.exe+01E855C0]+E0]+150", -1) -- if S pressed, than send "-1" to speed forward
  else
    writeFloat("[[anotherGame.exe+01E855C0]+E0]+150", 0) -- if nothing pressed, send "0"
  end

end

t=createTimer(nil)
timer_setInterval(t, 50)
timer_onTimer(t, checkKeys)
timer_setEnabled(t, true)

[DISABLE]

timer_setEnabled(t, false)


And this code above for another game works pretty smooth. But if implement for that another game the same calculations and logic as in first game for moving camera by XYZ - in such case it have the same lags. Which is makes me think that problem not inside the game but in logic and/or calculations that i used in LUA.
If in problematic script i set timer interval to 50 or 100 or bigger - i start to see "steps" of moving and, by the way, even if i set interval to "100" - i still can see the same lags, but they are not so often, because of "steps". Less interval value, even for "1", no have any noticeable changes in lags.

So my guess that maybe problem is somewhere in calculations or i just use some kind of stupid logic? Here is what i already try to do to find where is problem could be:

- Collecting garbage and changing syntax of timer:
Code:

{$lua}

[ENABLE]

function checkKeys(timer)

local camx = readFloat("[[[Game.exe+4B18798]+A8]+0]+60") -- Camera X position
local camy = readFloat("[[[Game.exe+4B18798]+A8]+0]+64") -- Camera Y position
local radh = readFloat("[[[[Game.exe+4B18798]+A8]+0]+340]+C4") -- Camera horizontal rotations in rad

local sinh = math.sin(radh) -- calculate sin/cos of rotations
local cosh = math.cos(radh)


  if isKeyPressed(VK_W) then  -- move Forward
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+60", camx - (sinh * 0.15))
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+64", camy - (cosh * 0.15))
  elseif isKeyPressed(VK_S) then  -- move Back
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+60", camx + (sinh * 0.15))
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+64", camy + (cosh * 0.15))
  end

end

mytimer = createTimer()
mytimer.Interval = 30
mytimer.OnTimer = checkKeys
mytimer.Enabled = true
mytimer.onTimer = function(mytimer) checkKeys(); collectgarbage()  end

[DISABLE]

mytimer.Enabled = false



- Attempt to use it without of local's and with in-game sin/cos addresses (which is "Game.exe+51B38D4" and "Game.exe+51B38CC":
Code:

{$lua}

[ENABLE]

function checkKeys(timer)

  if isKeyPressed(VK_W) then
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+60", readFloat("[[[Game.exe+4B18798]+A8]+0]+60") - (readFloat("Game.exe+51B38D4") * 0.15))
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+64", readFloat("[[[Game.exe+4B18798]+A8]+0]+64") + (readFloat("Game.exe+51B38CC") * 0.15))
  end

end

t=createTimer(nil)
timer_setInterval(t, 30)
timer_onTimer(t, checkKeys)
timer_setEnabled(t, true)

[DISABLE]

timer_setEnabled(t, false)



- Attempt to use rounded calculations:
Code:

{$lua}

[ENABLE]

function checkKeys(timer)

local camx = readFloat("[[[Game.exe+4B18798]+A8]+0]+60") -- Camera X position
local camy = readFloat("[[[Game.exe+4B18798]+A8]+0]+64") -- Camera Y position
local radh = readFloat("[[[[Game.exe+4B18798]+A8]+0]+340]+C4") -- Camera horizontal rotations in rad

local sinh = string.format("%.3f", math.sin(radh)) -- here is the difference with the code from top
local cosh = string.format("%.3f", math.cos(radh)) -- here is the difference with the code from top


  if isKeyPressed(VK_W) then  -- move Forward
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+60", camx - (sinh * 0.15))
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+64", camy - (cosh * 0.15))
  elseif isKeyPressed(VK_S) then  -- move Back
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+60", camx + (sinh * 0.15))
    writeFloat("[[[Game.exe+4B18798]+A8]+0]+64", camy + (cosh * 0.15))
  end

end

t=createTimer(nil)
timer_setInterval(t, 30)
timer_onTimer(t, checkKeys)
timer_setEnabled(t, true)

[DISABLE]

timer_setEnabled(t, false)


Nothing of this changes affected lags behavior. So i'm just confused. Why the same timer in another game do not produce lags, but with even bit another calculations it's start lagging? Why if seems like it's all about calculations - any changes in script for main game do not affect lags? Maybe problem still in timer? Loop...

Sorry if i'm doing something pretty stupid. I'm noob and i learn this things by making my own mistakes, google another solution, see if it works and if yes - google why and used my own mistakes as good example for learning and for more experiments for better understanding of logic and the whole process. But here i'm stuck :/


Last edited by geesve on Wed Mar 07, 2018 9:40 am; edited 3 times in total
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Wed Feb 21, 2018 11:35 am    Post subject: This post has 1 review(s) Reply with quote

Your computer might not be good enough to play a resource-intensive game and record it without lag. Check how much system resources are being used.

There are a lot of calls to ReadProcessMemory in your script that could be mitigated by caching a node in the pointer path. Also, you're not destroying the timer when the script is disabled which causes memory leak.
Code:
{$lua}
if syntaxcheck then return end
if freeCamT then freeCamT.destroy(); freeCamT = nil end

[ENABLE]
freeCamT = createTimer(nil, true)
freeCamT.Interval = 30
freeCamT.OnTimer = function(t)
  local node = getAddress("[[[Game.exe+4B18798]+A8]+0]")

  local camx = readFloat(node + 0x60)
  local camy = readFloat(node + 0x64)
  local radh = readFloat(readPointer(node + 0x340) + 0xC4)

  local sinh = math.sin(radh)
  local cosh = math.cos(radh)

  if isKeyPressed(VK_W) then
    writeFloat(node + 0x60, camx - (sinh * 0.15))
    writeFloat(node + 0x64, camy - (cosh * 0.15))
  elseif isKeyPressed(VK_S) then
    writeFloat(node + 0x60, camx + (sinh * 0.15))
    writeFloat(node + 0x64, camy + (cosh * 0.15))
  end
end

[DISABLE]
-- destroying the timer is handled at the top


It would probably be better to use assembly instead, but do whatever works for you.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Wed Feb 21, 2018 12:42 pm    Post subject: Reply with quote

Quote:
Your computer might not be good enough to play a resource-intensive game and record it without lag. Check how much system resources are being used.

I can notice lags when i'm do not recording video as well and just flying around with the camera. Anyway, my first thought was that yes, probably my PC can't handle it, but even while i looking at by-core CPU and overall GPU and memory usage - i do not notice any difference when i enable the whole free cam script and while game actually does not eat all of resources (i run it on 980ti, 5820k and 32gb). However, i know that it might not mean anything and problem still can stay at PC performance.

Quote:
Also, you're not destroying the timer when the script is disabled which causes memory leak.

I thought that this code:
Code:

...
[DISABLE]
timer_setEnabled(t, false)

is actually destroying the timer, but seems like i'm misunderstood that and this just stop timer and i should use "freeCamT.destroy()" :)
At least, when i disable script, remap another hotkeys, enable it back - old hotkeys doesn't work anymore and if just disable script - it does not affect camera anymore too. And camera lags become right from the first seconds after activating script.

Thank you for you version of the script and node method! Looks better to use, but anyway still noticing the same issues.
I read before somewhere that creating free cam in ASM should give better performance, but ASM is my last resort, because this LUA code just easier for me to understand, change, experiment with... But seems like from now i really should try to make it all with ASM.

BTW, thank you ParkourPenguin for all your help that you give people here! While working on this code - i'm reading a lot of your suggestions and thoughts on that forum and it really help me to make this script work! Thank you!
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Wed Feb 21, 2018 2:22 pm    Post subject: Reply with quote

You can enable/disable a timer multiple times and it will still work. Destroying the timer will stop it and free the resources it was using. Any accesses to it after that point are in error, so the global name should also be set to nil if it's been destroyed.

I'd guess the calls to writeFloat are causing the lag. Maybe the game doesn't like it when those values are changed unexpectedly by CE and it sometimes has to do a lot of work to fix itself (e.g. redraw everything). If you hook an instruction that changes the camera's coordinates and modify the coordinates there, maybe it won't have to do that work.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Wed Feb 21, 2018 6:28 pm    Post subject: Reply with quote

Quote:
You can enable/disable a timer multiple times and it will still work. Destroying the timer will stop it and free the resources it was using. Any accesses to it after that point are in error, so the global name should also be set to nil if it's been destroyed.

Thank you, now i get it!

Quote:
If you hook an instruction that changes the camera's coordinates and modify the coordinates there, maybe it won't have to do that work.

Here is what is interesting in that task. Here is a lot (if i remember correct, something like ~300) of addresses that have the same value as, for example, Camera position by X (seems like it's still ok here to say which game is it? AC:O ). 3 or 4 of them actually can change camera position by X (if i freeze them all and try to move main character - that's how i find which is affected camera position), but 1 of them make it with so much terrible lags (if i hook his instruction)... Another one change with not so much lags, and 2 another seems done it almost without of lags, and from those last two addresses i decide to hook one which have "earlier" address number.

Actually, maybe it is good idea to check all again one more time... If at first attempts of search i found only that first one pretty laggy address and after that i do not make any other searches - probably i have the same thoughts, that with the game everything is OK, but problem is in the script.

Script also already have feature to move some kind of "render point" to camera position, so it makes game properly render all the stuff where camera is atm (except one rare condition check, which is hard to explain short). Also, if i use one of another "effective" addresses - than, for example, i will not see underwater visual effects, can't hear some sounds where camera is and so on... So maybe i'm actually miss one more "effective" address with better performance Rolling Eyes
Back to top
View user's profile Send private message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Tue Feb 27, 2018 5:14 am    Post subject: Reply with quote

ParkourPenguin, SunBeam port that LUA script into ASM and it works much more better, so this is just like one more proof for you and others that ASM with custom free camera works better than LUA. But i keep working on LUA just to learn it more and if there is still any chance to deal with that stuttering/lags.

Current LUA code have node (thanks again ParkourPenguin, with that thing code actually works better and it easier to read) and attempt to createThread, but that "thread" thing is something that i can't get... By google that, i found that here is probably no such simple solution, as it can be done in ASM ( stackoverflow. com/questions/40564344/how-to-call-lua-functions-with-c-thread-multiple-times ), but maybe it is still possible? With those "node" and createThread it seems like working better, but still stuttering.

Here is last iteration of the whole code. But i also tried to add inertia for free cam here and add slowly start moving. Those things works as expected, but maybe logic here are not great Rolling Eyes I keep working on that logic and it only like second iteration of inertia code, but maybe anyway could be useful for someone, because when i googled LUA free camera with inertia - i can't find anything:

Code:

globalalloc(cheaton,4)
cheaton:
dd 0

globalalloc(multFB,4)
multFB:
dd 0

globalalloc(multRL,4)
multRL:
dd 0

globalalloc(multUpDown,4)
multUpDown:
dd 0

{$lua}
if syntaxcheck then return end
[ENABLE]

createThread(function(timer)
sleep(200) -- delay for giving script time to write for "cheaton" proper value
while readFloat("cheaton") == 0 do -- while "cheaton" value equal "0" this cheat work
 sleep(10) -- like timer interval

local node = getAddress("[[[ACOrigins.exe+4B18798]+A8]+0]") -- create "node" for base cameraXYZ addresses

local multFB = readFloat("multFB")
local multRL = readFloat("multRL")
local multUpDown = readFloat("multUpDown")
writeFloat("multFB",multFB) -- send current multFB to in-table multFB address for debugging
writeFloat("multRL",multRL) -- send current multRL to in-table multRL address for debugging
writeFloat("multUpDown",multUpDown) -- send current multUpDown to in-table multUpDown address for debugging

local sinh = readFloat("ACOrigins.exe+51B38D4") -- in-game horizontal sine
local cosh = readFloat("ACOrigins.exe+51B38CC") -- in-game horizontal cosine

------------------ WASD MOVEMENTS

-- Forward/Back
  if isKeyPressed(VK_W) and readFloat("multFB") < 0.1 then -- start moving Forward
    writeFloat("multFB", readFloat("multFB") + 0.001) -- with slowly increasing speed
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  elseif isKeyPressed(VK_S) and readFloat("multFB") > -0.1 then -- start moving Back
    writeFloat("multFB", readFloat("multFB") - 0.001) -- with slowly decreasing speed
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  end
  if isKeyPressed(VK_W) and readFloat("multFB") < 0 then -- faster speed increase if cam mov back but need forward
    writeFloat("multFB", readFloat("multFB") + 0.005)
  elseif isKeyPressed(VK_S) and readFloat("multFB") > 0 then -- faster speed decrease if cam mov forward but need back
    writeFloat("multFB", readFloat("multFB") - 0.005)
  end

  if isKeyPressed(VK_W) and readFloat("multFB") > 0.1 then -- stop increasing speed when (multFB= 0.1)
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  elseif isKeyPressed(VK_S) and readFloat("multFB") < -0.1 then -- stop decreasing speed when (multFB= -0.1)
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  end

  if not isKeyPressed(VK_W) and not isKeyPressed(VK_S) and readFloat("multFB") > 0.0001 then -- slowly stop moving after release hotkey
    writeFloat("multFB", readFloat("multFB") - 0.001)
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  elseif not isKeyPressed(VK_S) and not isKeyPressed(VK_W) and readFloat("multFB") < -0.0001 then -- slowly stop moving after release hotkey
    writeFloat("multFB", readFloat("multFB") + 0.001)
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  end

-- Right/Left
  if isKeyPressed(VK_D) and readFloat("multRL") < 0.1 then -- start moving Right
    writeFloat("multRL", readFloat("multRL") + 0.001) -- with slowly increasing speed
    writeFloat(node + 0x60, readFloat(node + 0x60) + (cosh * multRL))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (sinh * multRL))
  elseif isKeyPressed(VK_A) and readFloat("multRL") > -0.1 then -- start moving Left
    writeFloat("multRL", readFloat("multRL") - 0.001) -- with slowly decreasing speed
    writeFloat(node + 0x60, readFloat(node + 0x60) + (cosh * multRL))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (sinh * multRL))
  end
  if isKeyPressed(VK_D) and readFloat("multRL") < 0 then -- faster speed increase if cam mov left but need right
    writeFloat("multRL", readFloat("multRL") + 0.005)
  elseif isKeyPressed(VK_A) and readFloat("multRL") > 0 then -- faster speed decrease if cam mov right but need left
    writeFloat("multRL", readFloat("multRL") - 0.005)
  end

  if isKeyPressed(VK_D) and readFloat("multRL") > 0.1 then -- stop increasing speed when (multRL= 0.1)
    writeFloat(node + 0x60, readFloat(node + 0x60) + (cosh * multRL))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (sinh * multRL))
  elseif isKeyPressed(VK_A) and readFloat("multRL") < -0.1 then -- stop decreasingspeed when (multRL= -0.1)
    writeFloat(node + 0x60, readFloat(node + 0x60) + (cosh * multRL))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (sinh * multRL))
  end

  if not isKeyPressed(VK_D) and not isKeyPressed(VK_A) and readFloat("multRL") > 0.0001 then -- slowly stop moving after release hotkey
    writeFloat("multRL", readFloat("multRL") - 0.001)
    writeFloat(node + 0x60, readFloat(node + 0x60) + (cosh * multRL))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (sinh * multRL))
  elseif not isKeyPressed(VK_A) and not isKeyPressed(VK_D) and readFloat("multRL") < -0.0001 then -- slowly stop moving after release hotkey
    writeFloat("multRL", readFloat("multRL") + 0.001)
    writeFloat(node + 0x60, readFloat(node + 0x60) + (cosh * multRL))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (sinh * multRL))
  end

-- Up/Down
  if isKeyPressed(VK_R) and readFloat("multUpDown") < 0.1 then -- start moving Up
   writeFloat("multUpDown", readFloat("multUpDown") + 0.001) -- with slowly increasing speed
   writeFloat(node + 0x68, readFloat(node + 0x68) + (multUpDown))
  elseif isKeyPressed(VK_F) and readFloat("multUpDown") > -0.1 then -- start moving Down
   writeFloat("multUpDown", readFloat("multUpDown") - 0.001) -- with slowly decreasingspeed
   writeFloat(node + 0x68, readFloat(node + 0x68) + (multUpDown))
  end
  if isKeyPressed(VK_R) and readFloat("multUpDown") < 0 then -- faster speed increase if cam mov down but need up
    writeFloat("multUpDown", readFloat("multUpDown") + 0.005)
  elseif isKeyPressed(VK_F) and readFloat("multUpDown") > 0 then -- faster speed decrease if cam mov up but need down
    writeFloat("multUpDown", readFloat("multUpDown") - 0.005)
  end

  if isKeyPressed(VK_R) and readFloat("multUpDown") > 0.1 then -- stop increasing speed when (multUp = 0.1)
   writeFloat(node + 0x68, readFloat(node + 0x68) + (multUpDown))
  elseif isKeyPressed(VK_F) and readFloat("multUpDown") < -0.1 then -- stop decreasingspeed when (multUp = -0.1)
   writeFloat(node + 0x68, readFloat(node + 0x68) + (multUpDown))
  end

  if not isKeyPressed(VK_R) and not isKeyPressed(VK_F) and readFloat("multUpDown") > 0.0001 then -- slowly stop moving after release hotkey
    writeFloat("multUpDown", readFloat("multUpDown") - 0.001)
    writeFloat(node + 0x68, readFloat(node + 0x68) + multUpDown)
  elseif not isKeyPressed(VK_F) and not isKeyPressed(VK_R) and readFloat("multUpDown") < -0.0001 then -- slowly stop moving after release hotkey
    writeFloat("multUpDown", readFloat("multUpDown") + 0.001)
    writeFloat(node + 0x68, readFloat(node + 0x68) + multUpDown)
  end

end
end)

[DISABLE]
{$asm}
cheaton: // give to "cheaton" any other value than "0" for stop thread from LUA
dd 1


So maybe someone have any ideas what here is could be possible to try or change for attempt to make it work without stuttering/lags, if it even possible?
There is maybe pretty interesting thing, that if i'm apply "createThread" for the simpler version of the code, which is without of inertia, than i'm actually can't notice any difference in performance.


Last edited by geesve on Tue Feb 27, 2018 5:37 am; edited 1 time in total
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

Joined: 09 May 2003
Posts: 25262
Location: The netherlands

PostPosted: Tue Feb 27, 2018 5:24 am    Post subject: Reply with quote

timers have a minimum delay. For smooth movement use threads (and try sleep(0))

what you can also do is group the float writes into bytetables, and when done write the bytetables all at once
(e.g node +0x60 to 0x68 can be written as a single 12 byte command, which will be a bit faster)


Also, you're doing isKeyPressed(VK_R) multiple times. It may be more efficient to just call it once and store the result in a local variable

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Wed Feb 28, 2018 1:03 pm    Post subject: Reply with quote

Thanks Dark Byte for your response!
However, i have only partial success.

Quote:
Also, you're doing isKeyPressed(VK_R) multiple times. It may be more efficient to just call it once and store the result in a local variable

If you mean about that:
Code:
...

local MoveForward = isKeyPressed(VK_W) -- local variable for move forward
local MoveBack = isKeyPressed(VK_S) -- local variable for move back

...

  if MoveForward then

... do calculations for moving forward ...

  if MoveBack then

... do calculations for moving backward ...

Than i get it right and yes, it is more easier to setup hotkeys and understand code Smile

Quote:
timers have a minimum delay. For smooth movement use threads (and try sleep(0))

sleep(0) or even deleting it makes movements very smooth, but it load up CPU up to ~10%, while if making sleep(1) or with usual timer it load up CPU up to ~0.5%.
I tried to setup separate threads for moving in different directions (actually, for tests i delete all but moving forward code), like
Code:
createThread(function(forward)
while MoveForward do
--or
createThread(function(forward)
while isKeyPressed(VK_W) do

with different sleep(x) values or even without sleep, but it load up CPU up to ~30% in such case and sometimes still affected movements even if key is not pressed or script disabled. Probably i just do not understand correctly what you mean here.

Quote:
what you can also do is group the float writes into bytetables, and when done write the bytetables all at once
(e.g node +0x60 to 0x68 can be written as a single 12 byte command, which will be a bit faster)

I make it partially working, but not really like you explain. I can't figure out or find how can i write 12 bytes at once. Here is the results that looks, probably, very close for what you mean:
Code:

-- seems like write correct values, but not at once
local tablX = floatToByteTable(readFloat(node + 0x60))
local tablY = floatToByteTable(readFloat(node + 0x64))
local tablZ = floatToByteTable(readFloat(node + 0x68))
writeBytes("address1", tablX)
writeBytes("address2", tablY)
writeBytes("address3", tablZ)


-- printed all required HEX values correctly, but write decimal(?) values
local bt1 = floatToByteTable(readFloat(node + 0x60))
local bt2 = floatToByteTable(readFloat(node + 0x64))
local bt3 = floatToByteTable(readFloat(node + 0x68))
local str1 = string.format("%02X%02X%02X%02X", unpack(bt1))
local str2 = string.format("%02X%02X%02X%02X", unpack(bt2))
local str3 = string.format("%02X%02X%02X%02X", unpack(bt3))
print(str1, str2, str3)
writeString("address", str1, str2, str3)


-- write HEX values correctly, but not at one time
local bt1 = floatToByteTable(readFloat(node + 0x60))
local bt2 = floatToByteTable(readFloat(node + 0x64))
local bt3 = floatToByteTable(readFloat(node + 0x68))
writeBytes("address", bt1)
writeBytes("address+4", bt2)
writeBytes("address+8", bt3)


-- write decimal values  ( screenshot of memory viewer https://imgur.com/a/1gtLM )
local t = {}
bt1 = floatToByteTable(readFloat(node + 0x60))
bt2 = floatToByteTable(readFloat(node + 0x64))
bt3 = floatToByteTable(readFloat(node + 0x68))
t[1] = string.format("%02X%02X%02X%02X", unpack(bt1))
t[2] = string.format("%02X%02X%02X%02X", unpack(bt2))
t[3] = string.format("%02X%02X%02X%02X", unpack(bt3))
local aaa = table.concat(t)
writeString("address", aaa)


-- same as one above, but shorter
local tabl1 = {}
tabl1[1] = string.format("%02X%02X%02X%02X", unpack(floatToByteTable(readFloat(node + 0x60))))
tabl1[2] = string.format("%02X%02X%02X%02X", unpack(floatToByteTable(readFloat(node + 0x64))))
tabl1[3] = string.format("%02X%02X%02X%02X", unpack(floatToByteTable(readFloat(node + 0x68))))
local a1 = table.concat(tabl1)
writeString("address", a1)


-- Error in native thread called Unnamed::Failure determining what 2E0654C4ADC8E0C457247843 means
-- "2E0654C4ADC8E0C457247843" is proper value actually
local t = {}
bt1 = floatToByteTable(readFloat(node + 0x60))
bt2 = floatToByteTable(readFloat(node + 0x64))
bt3 = floatToByteTable(readFloat(node + 0x68))
t[1] = string.format("%02X%02X%02X%02X", unpack(bt1))
t[2] = string.format("%02X%02X%02X%02X", unpack(bt2))
t[3] = string.format("%02X%02X%02X%02X", unpack(bt3))
local aaa = table.concat(t)
print(readBytes(aaa))


-- print all proper HEX, but write decimal values
local tabl1 = {}
tabl1[1] = string.format("%02X%02X%02X%02X", unpack(floatToByteTable(readFloat(node + 0x60))))
tabl1[2] = string.format("%02X%02X%02X%02X", unpack(floatToByteTable(readFloat(node + 0x64))))
tabl1[3] = string.format("%02X%02X%02X%02X", unpack(floatToByteTable(readFloat(node + 0x68))))
local a1 = table.concat(tabl1)
print(a1)
writeString("address", aaa)

So as you can see, i'm not lazy, just can't get it or even i tried something, that you do not really mean :/
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

Joined: 09 May 2003
Posts: 25262
Location: The netherlands

PostPosted: Wed Feb 28, 2018 1:27 pm    Post subject: Reply with quote

ok, so the solution of sleep(0) works.
that means that your issue us the interval that it is called, so optimizations won't do much

that the cpu goes up to 100% of the current cpu (i take it you have 4 cores) is a shame, but does the game really slow down?
sleep(0) triggers a context yield so other threads can run, so the sliwdown shouldn't be too bad.

anyhow, if you really care about cpu usage you can call your lua code right before the game accesses the variables each time.
look into call ce lua function template

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Thu Mar 01, 2018 11:13 am    Post subject: Reply with quote

Quote:
that the cpu goes up to 100% of the current cpu (i take it you have 4 cores) is a shame, but does the game really slow down?
sleep(0) triggers a context yield so other threads can run, so the sliwdown shouldn't be too bad.

No, not overall 100%, CE just start using 10% of CPU, while usually it's using not more than 0.5-2%. But after more tests i see that probably we can do not really care about that, while it doesn't really affect game/pc performance.

Quote:
ok, so the solution of sleep(0) works.
that means that your issue us the interval that it is called, so optimizations won't do much

Seems like optimizations are still matter. Your thoughts push me to check lua free cam in another game, that have timer and works smooth, but when i delete timer and add createThread with all the same settings ( sleep(0) i mean) - i'm noticing strong lags. After some investigation i figured out that the issue was in a lot of "if - elseif - else" compares and writeFloat things, as ParkourPenguin says before.
So, after moving back to ACO, adding just very few optimizations (part of the code with that optimizations in the end of that reply) makes camera moves 10(!) times faster, while speed settings are all the same o_O I just choose point A and point B on the map and with timer in my hand check how much time it required to move that distance with and without of that optimizations. Seems cool? Well, too much cool, actually :) Because in such case i need to decrease speed multipliers values even more for values like "0.0000001" and probably because of that i can noticing... For example camera moving to North-East or South-West, with such low multipliers values i can notice how it moving before to North direction and then to East, not to North-East at one time. So i guess, as you said before, there is still reason to try write cameraXYZ values as a single 12 byte command. But i still can't figure out logic of it with reading how to use writeBytes/writeString or find any examples that was used for making same thing in LUA. So if you or anyone else could provide any example or push in right direction - will be interesting to check how it works in such case. Oh and i checked if i move back sleep(1) - lags moved back in such case too.

I'm forget to mention one thing. Thanks to SunBeam, he agreed to test that LUA two times and he is noticing lags in any case, while ASM version works for him very stable. This is strange because currently, after your advise i change sleep(0) only - i'm already get nice and smooth camera, that works for me even better than ASM version. Maybe it depend from 4 cores vs. 6 cores CPU or anything else, but seems like that LUA solution with sleep(0) is not universal and performance very depend on particular system specs where it will be used. But at least it could be used just as reference of logic for ASM :)

Here is "too much" optimized version. I just moved above createThread some things and delete writeFloat("mult", ...) that was used before for debugging mult's values:
Code:
globalalloc(cheaton,4) // global variable for createThread on/off
cheaton:
dd 0

{$lua}

if syntaxcheck then return end

[ENABLE]

-------------------------------------
-- Speed and Multipliers variables --
-------------------------------------
local multFB = 0
local multRL = 0
local multUpDown = 0
local maxPosSpeed = 0.0005 -- maximum speed for Forward and Right movement
local maxNegSpeed = -0.0005 -- maximum speed for Back and Left movement
local SlowerMult = 0.0000001 -- how soon top speed will achieved when hotkey pressed and how soon camera stop if hotkey released
local FasterMult = 0.0000005 -- how fast speed decrease if movement goes vice versa (e.g. from right to left, while camera keeps going right)

-------------------------------------------------------------------------------------
-- Create "node" for base cameraXYZ addresses
local node = getAddress("[[[ACOrigins.exe+4B18798]+A8]+0]")
-- so after that, (node + 0x60) is the same as "[[[ACOrigins.exe+4B18798]+A8]+0]+60"
-------------------------------------------------------------------------------------

createThread(function(timer)
sleep(200) -- delay for giving script time to write for "cheaton" proper value
while readFloat("cheaton") == 0 do -- while "cheaton" value equal "0" this cheat work
sleep(0) -- like timer interval

-----------------------
-- sine/cosine block --
-----------------------
local sinh = readFloat("ACOrigins.exe+51B38D4") -- in-game horizontal sine
local cosh = readFloat("ACOrigins.exe+51B38CC") -- in-game horizontal cosine

-------------------------
-- Assign Hotkeys Here --
-------------------------
local MoveForward = isKeyPressed(VK_T) -- local variable for move forward
local MoveBack = isKeyPressed(VK_G) -- local variable for move back
local MoveLeft = isKeyPressed(VK_F) -- local variable for move left
local MoveRight = isKeyPressed(VK_H) -- local variable for move right
local MoveUp = isKeyPressed(VK_U) -- local variable for move up
local MoveDown = isKeyPressed(VK_J) -- local variable for move down

----------------------------
-- Movements calculations --
----------------------------

---- Forward/Back
  if MoveForward then -- start moving Forward
      if multFB < maxPosSpeed then -- if max speed not achieved
        multFB = multFB + SlowerMult -- slowly increasing to max speed
      end
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  elseif MoveBack then -- start moving Back
      if multFB > maxNegSpeed then -- if max speed not achieved
        multFB = multFB - SlowerMult -- slowly decreasing to max speed
      end
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  end
  -- when switch direction
  if MoveForward and multFB < 0 then -- faster speed increase if cam moving back and need forward
    multFB = multFB + FasterMult
  elseif MoveBack and multFB > 0 then -- faster speed decrease if cam moving forward and need back
    multFB = multFB - FasterMult
  end
  -- when hotkeys are released
  if not MoveForward and not MoveBack and multFB > 0.000001 then -- check if keys released and camera moves forward
    multFB = multFB - SlowerMult -- slowly stop moving forward
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  elseif not MoveBack and not MoveForward and multFB < -0.000001 then -- check if keys released and camera moves back
    multFB = multFB + SlowerMult -- slowly stop moving back
    writeFloat(node + 0x60, readFloat(node + 0x60) - (sinh * multFB))
    writeFloat(node + 0x64, readFloat(node + 0x64) + (cosh * multFB))
  end

---- Right/Left and so on
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 941

PostPosted: Thu Mar 01, 2018 1:28 pm    Post subject: This post has 1 review(s) Reply with quote

Here sample function to read/write multiple values in continued memory with one byteTable read/write.
Code:

function packWrite(addr, fms, ...)
  local packed = addr and string.pack(fms,...)
  if packed then return writeBytes(addr,{packed:byte(1,-1)}) end
end
function packRead(addr, fms)
  local sz = addr and string.packsize(fms)
  local bt = sz and readBytes(addr,sz,true)
  if bt and #bt == sz then
    return string.unpack(fms,byteTableToString(bt))
  end
end
--
eg.
-- read
local x,y = packRead(node+60,'ff') -- 'ff' means to 2x'float'
if x then -- x,y can be 'nil' (eg.unreadable memory), should check before further process
  -- update x,y
  x = x - (sinh * multFB)
  y = y + (cosh * multFB)
  -- write
  packWrite(node+60, 'ff', x, y)
end


Check Lua string.pack/unpack info

Updated: remove the init 'addr' check, if it is for performance, address check should be done before.

_________________
- Retarded.
Back to top
View user's profile Send private message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Sat Mar 03, 2018 7:27 pm    Post subject: Reply with quote

Thank you panraven for your example!

Unfortunately, it doesn't really help and while investigated it further in another game, i get interesting result.

Seems like i found condition when writeFloat command doesn't work, but maybe i trick myself somewhere? I have some suspicions that it can somehow correlate with the some of the issues described in this topic previously.

Video link:
https://youtu.be/KhkY2nYtv_Q

So i tried to send for Camera position by X new calculated value. But when in (sinh * 0.001) i get value lower than "0.000488" - it doesn't write it to global CameraX. Actually, not only when it lower than "0.000488", some others too, but i did not check another values because not sure that i'm just do not fool myself.
I tried to check everything that i can imagine and most obvious checks i showed in the video. Pay attention to "Cam 7 X" value, "LUA Engine" window (cam7x should changing when values are changing in lua engine window as well) and any of rotations or game window.

In the video i showing simple script with different variations and also "LUA Engine" window, where for being sure that calculations are works good i print the same calculations results. What i do not showing in the video but also tried, is that writeFloat doesn't work when i try to use "-" as well, but seems work when i try to use "/" or "*" ( * (sinh * 0.001), for example). For being sure, i also tried to define local variable (let's say newX) and this code:
Code:
  if MoveForward then -- start moving Forward
      newX = readFloat(node + 0xF0) + (sinh * 0.001)
      print(newX)
  end

And it printed proper new values, despite on angle of rotation. I'm can't find any correlations on what from it can depend or what can cause such behavior (it seems like pretty stable issue). I also tried to calculate sine value from rotations in degrees and in rads, changing sleep(100) values, using timer function instead of thread, as well as CE ver. 6.6 or 6.7. So i'm out of ideas what i can also try to check to see if that issue on my side?

Just in case the whole basic LUA code:
Code:
globalalloc(cheaton,4) // global variable for createThread on/off
cheaton:
dd 0

{$lua}

if syntaxcheck then return end

[ENABLE]

local node = getAddress("[[[theHunterCotW_F.exe+01D94868]+158]+468]")

createThread(function(timer)
sleep(200) -- delay for giving script time to write for "cheaton" proper value
while readFloat("cheaton") == 0 do -- while "cheaton" value equal "0" this cheat work
sleep(100) -- like timer interval

local sinh = readFloat("theHunterCotW_F.exe+1E6695C") -- in-game horizontal sine

local MoveForward = isKeyPressed(VK_H) -- local variable for move forward

---- Forward
  if MoveForward then -- start moving Forward
      writeFloat(node + 0xF0, readFloat(node + 0xF0) + (sinh * 0.001))
      local check = (sinh * 0.01) -- check value
      print(check)
  end

end
end)

[DISABLE]
{$asm}
cheaton:
dd 1 // give to "cheaton" any other value than "0" for stop thread from LUA


UPD:
Just noticed one more. In the very end of the video, when i stopped pressing forward hotkey at 3:59, it write to Cam 7 X -9825.075195 value, while in "LUA Engine" we can see that it should write -9825.076143.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Sat Mar 03, 2018 8:52 pm    Post subject: Reply with quote

Arithmetic operations on floating point numbers don't have to give mathematically correct results. In this case, the reason is that floating point numbers have finite precision. Single precision floats (aka float) have about 7.2 decimal digits of precision, while double precision floats (aka double) have about 16 decimal digits of precision. Any information that would extend beyond that precision is discarded.

You are adding the two numbers and writing the result to memory; it's just that one of the numbers is so much smaller than the other that the sum isn't any different than the larger number.

Lua uses doubles internally which have more precision than floats, but this behaviour can still be seen:
Code:
local num1 = 1.0e10
local num2 = 1.0e-10
local sum = num1 + num2

print(sum == math.max(num1,num2) and 'Insignificant calculation' or 'Good add')


So when you add the numbers in Lua, the sum is different from either number (as you have seen), but when it's converted back to a float, precision is lost and the new value isn't any different than what it read.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Sat Mar 03, 2018 9:28 pm    Post subject: Reply with quote

Interesting. Like i guess before, seems like it explain some of the issues.

Quote:
So when you add the numbers in Lua, the sum is different from either number (as you have seen), but when it's converted back to a float, precision is lost and the new value isn't any different than what it read.

So because of that even if i try:
Code:
local num1 = 0.0001
local num2 = 0.0001
local sum = num1 + num2

print(sum == math.max(num1,num2) and 'Insignificant calculation' or 'Good add')

it working good, receiving "Good add", but if i try in script:
Code:
writeFloat(node + 0xF0, readFloat(node + 0xF0) + 0.0001)

It doesn't work because precision was lost? It's still looks weird that only values bigger than 0.000488 are working well. Even... Just checked in the script from the video, value like 0.000488281250909494757 = 0, but 0.000488281250909494758 are working well.

And about UPD in the end of my previous reply, that was my misunderstand, everything fine here actually.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Sat Mar 03, 2018 10:32 pm    Post subject: Reply with quote

No. 0.0001 + 0.0001 will be about 0.0002 as a float; that's perfectly fine. I'm saying if one float is at least 2^24 (about 10^7.2) times bigger than another float, their sum will be equal to the bigger number.

In your case, 9825.060547 > 0.00048828125 * 2^24, so their sum will be equal to 9825.060547 (signs aren't terribly important so I've omitted them for simplicity).

Google "floating point arithmetic precision" or something like that and you'll find a lot of webpages describing how floating point numbers work.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
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 Lua Scripting All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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