| View previous topic :: View next topic |
| Author |
Message |
vve1der How do I cheat?
Reputation: 0
Joined: 23 Feb 2026 Posts: 3
|
Posted: Mon Feb 23, 2026 1:46 pm Post subject: onValueChange infinite loop |
|
|
Hi!
I am trying to add onValueChange callback to money, so that on each update it would add the same ammout if increased (double income) or decrease the original value (normal spending).
The code looks like this:
| Code: |
function onValueChange(memrec, oldvalue, newvalue)
local oldVal = tonumber(oldvalue)
local newVal = tonumber(newvalue)
local targetValue = nil
if newVal > oldVal then
targetValue = oldVal + (newVal - oldVal) * 2
end
if targetValue then
memrec.OnValueChanged = nil
memrec.Value = targetValue
memrec.OnValueChanged = onValueChange
end
end
|
However it just do not work, and when I try to print inside `if target` - it start spawn messages and finishes in stack overflow... Is it possible at all or is there some ways to overcome infinite loop?
Thanks!
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 153
Joined: 06 Jul 2014 Posts: 4740
|
Posted: Mon Feb 23, 2026 3:27 pm Post subject: |
|
|
I guess there's a problem with reentrancy, or maybe the memrec was initialized with an old implementation of that onValueChange function.
You shouldn't be using that in the first place. I'd assume onValueChange can only trigger at the rate CE updates the UI for the address list. This only works correctly if the game doesn't change the value too quickly. If it changes more than once between UI updates, this may not work correctly: e.g. +2, -5 should give -1 total (+2 * 2 - 5), but if both of those changes happened in the same interval between UI updates, CE would only see a change of -3 and leave it as that.
Code injection would be the first thing I'd turn to. See the CE tutorial. There's tons of videos going over it if you need help.
If the instruction that changes the value also accesses other addresses and you can't be bothered with finding a good filter (not everything is as simple as step 9 of the CE tutorial), you could use a break-on-write breakpoint with the Lua function debug_setBreakpoint to implement this correctly.
Since there's only 4 debug registers for hardware breakpoints, you can't do this for too many values at once. In general, you could inject code that checks the address against a "hard coded" address (CE can assemble whatever address you want at runtime). Conditionally run some code that CE can trigger a software breakpoint on, and run your code that modifies the value in there.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
vve1der How do I cheat?
Reputation: 0
Joined: 23 Feb 2026 Posts: 3
|
Posted: Tue Feb 24, 2026 12:01 am Post subject: |
|
|
| Found this page viewtopic.php?t=609107 and it seems to be working after some additions, but I just confused then about that method - looks like it is intended for something else... %)
|
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 472
Joined: 09 May 2003 Posts: 25880 Location: The netherlands
|
Posted: Tue Feb 24, 2026 12:31 am Post subject: |
|
|
not sure if works i'm on my phone but try adding
| Code: |
local lastvalue=memrec.Value
|
after memrec.Value=targetValue and before you restore the onValueChanged event
this way the lastknownvalue gets updated so next check it won't see that it has changed
and as ParkourPenguin mentioned keep in mind that you may have missed aeveral updates
_________________
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 |
|
 |
vve1der How do I cheat?
Reputation: 0
Joined: 23 Feb 2026 Posts: 3
|
Posted: Tue Feb 24, 2026 1:31 am Post subject: |
|
|
Thank you for your solutions!
Anyway - the solution from viewtopic.php?t=609107 is pretty solid for now.
Looks like this after a bit of optimization:
| Code: |
-- Double the income
local resources = {
{ desc = 'minerals', last = 0 },
{ desc = 'vespen', last = 0 }
}
for _, res in ipairs(resources) do
local mr = AddressList.getMemoryRecordByDescription(res.desc)
if mr then
res.last = tonumber(mr.Value) or 0
end
end
local t = createTimer()
t.Interval = 200
t.OnTimer = function(timer)
local foundCount = 0
for _, res in ipairs(resources) do
local mr = AddressList.getMemoryRecordByDescription(res.desc)
if mr then
foundCount = foundCount + 1
local current = tonumber(mr.Value) or 0
if current - res.last > 0 then
res.last = 2 * current - res.last
mr.Value = tostring(res.last)
elseif current - res.last < 0 then
res.last = current
end
end
end
if foundCount == 0 then
timer.destroy()
end
end
|
And even if it is not 100% accurate, it mosty solves my problem.
|
|
| Back to top |
|
 |
|