 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
nexnex Newbie cheater
Reputation: 0
Joined: 22 Jun 2019 Posts: 13
|
Posted: Thu Jul 25, 2019 7:00 am Post subject: memrec.DontSave still triggers "Save changes" dial |
|
|
When I create a MemoryRecord with DontSave property and try to close CE, it still shows me "You haven't saved your last changes yet. Save Now?" dialog.
Needless to say there are no changes and the saved file is exactly the same as it was before.
Is it intended behavior and I'm missing something?
It's a bit scary when it tells "there are changes" when there aren't.
Here a example table file. Steps to reproduce:
- open the table
- activate "add memrec" script
- deactivate "add memrec" script
- close CE
It will show "Save now?" dialog.
Code: | <?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="28">
<CheatEntries>
<CheatEntry>
<ID>0</ID>
<Description>"add memrec"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>{$lua}
[ENABLE]
local m = getAddressList().createMemoryRecord()
m.DontSave = true
m.Description = "added"
[DISABLE]
</AssemblerScript>
</CheatEntry>
</CheatEntries>
<UserdefinedSymbols/>
</CheatTable> |
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25806 Location: The netherlands
|
Posted: Thu Jul 25, 2019 7:36 am Post subject: |
|
|
The change detection isn't advanced. It just checks if the 'hasBeenChanged' flag has been set in the addresslist object.
In this case it first creates the record, so flags the addresslist that changes have been made
then it sets the don't save field
_________________
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 |
|
 |
paul44 Expert Cheater
Reputation: 2
Joined: 20 Jul 2017 Posts: 206
|
Posted: Tue Oct 27, 2020 12:24 pm Post subject: hasBeenChanged flag set? |
|
|
^ are you sure this flag is actually set? Or is some other flag set instead...?
Did following test:
a. inserted print(tostring(al.hasBeenChanged)) prior to adding the mem_records
b. same thing AFTER they were added
c. and again after they were removed
in all cases, it returns 'nil'. and just to be sure, did also:
al.List.hasBeenChanged (or al.Control[0].hasBeenChanged)
al.Parent.hasBeenChanged
al.Parent.Parent.hasBeenChanged
al.Parent.Parent.Parent.hasBeenChanged (not sure about this one; I had already removed them lines)
anyways: i was kinda hoping I could set that 'flag = false'
I have several tables doing this stuff; a little annoyance but it would be great to have a workaround...
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4704
|
Posted: Tue Oct 27, 2020 1:03 pm Post subject: |
|
|
hasBeenChanged isn't a property of anything in CE.
The editedsincelastsave property of the main form isn't exposed to Lua, which I find to be a good thing. The majority of people aren't smart enough to use it correctly. Even ignoring the possibility of race conditions, they'd do something stupid like set it to false, lose their work, and complain.
False positives aren't good, but false negatives would be worse IMO.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
paul44 Expert Cheater
Reputation: 2
Joined: 20 Jul 2017 Posts: 206
|
Posted: Thu Oct 29, 2020 1:37 am Post subject: force save...? |
|
|
^ I got the initial impression - based on #Dark Byte's feedback - that there is/was such a flag; either called as such or otherwise...
That said: the property/method you are referring is to, is not what I have in mind (nor the original poster's intention either, I think).
To give an example: I have several AC tables that build an overview of all ships in vicinity (~ mr's added); and these records are removed again upon disabling the script. From a user's point of view, nothing has changed basically. But upon quiting CE, s/he gets the [Save]prompt...
Bottomline: whatever the flag is called - that is set as such - can it be altered?! (which would be done in the 'ship' script)
But: no matter if that flag is set or not, one must always be able to save (using File option) !
ps: meanwhile, I got the idea 'why not force save after removing the mr's' in the script itself. I think I already found the method(s) for that; still need to test it... (the user will not notice this at all, and logically should not get 'save'- prompted later on)
-EDIT-
I just did some testing:
1. saveOpenedFile(): has no "effect"; still getting prompt ?
(perhaps not using this correctly ? true/false as param maybe... or as method linked to some objectname)
2. saveTable('ACBF_Varia_3.9e.CT'): works as expected, but not practical as I need to fill in the table's name (if user renames it...). would be ok if I can collect the 'currentlyOpenedTablename'.
* I can not use any function that collects from 'currDir' as one can have multiple CTs in that directory (and I am one of those...).
* I did some quick perusing to see if a property/method exists, but did not find one (yet). Perhaps there exists a system_var (like 'process') ?
* I also can find the tablename; attaching 'running ce process'. multiple entries but none return "active code"...
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4704
|
Posted: Thu Oct 29, 2020 10:17 am Post subject: |
|
|
paul44 wrote: | whatever the flag is called - that is set as such - can it be altered?! | No. As I said: ParkourPenguin wrote: | The editedsincelastsave property of the main form isn't exposed to Lua... | Look at CE's source code for more information.
paul44 wrote: | ps: meanwhile, I got the idea 'why not force save after removing the mr's' in the script itself. | This is a bad idea and an example of why users shouldn't be trusted with write access to that flag.
The "correct" way of doing this would be to get rid of that flag and check if the script actually changed. If table serialization to .CT files is sufficiently reproducible, that would probably be the most straightforward way. If it's not fast enough, using checksums and/or hashes would be a far better heuristic.
Exposing that flag to Lua would be far easier to implement but is effectively pushing the burden of correctness onto users, most of whom aren't smart enough to do that correctly. (if DB does decide to do it correctly in the future, backwards compatibility might be of concern too)
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
paul44 Expert Cheater
Reputation: 2
Joined: 20 Jul 2017 Posts: 206
|
Posted: Thu Oct 29, 2020 11:54 am Post subject: some clarification then... |
|
|
I think we are not on the same wavelength here; so some pics will clarify far better what i'm doing in my table: see here [ https://imgur.com/a/okmbd1b ].
Upon enabling the script, the "ship records" get collected and 'shown' on screen. upon disabling the script, those mem_records are removed. So from a user's point of view, the table has not changed... but s/he gets confronted with a 'Would you like to save' prompt when quiting CE.
(btw: in my readme, i explain them to ignore the save prompt)
This midday, I tested both 'save' functions; results recapped in my prev post.
Now, unless you tell me that I should not use those 2 particular functions (in any way), my question is now:
1. how can I use 'saveOpenedFile()' property as it is not working for me (?) at the moment.
(ps: just tried setting it "true", but no cigar)
2. is there a way to collect the currently loaded CT_table's filename (without getting it via a "directory lookup", like 'getFileList') ? as stated earlier, this fn does the job - like one would have saved manually - and no save_prompt upon quiting.
ps: i assume that both functions basically 'represent' the [File ~ Save] menu_item (which saves "directly" without the 'fileOpenDialog'...
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4704
|
Posted: Thu Oct 29, 2020 4:27 pm Post subject: |
|
|
I understand the problem you're facing, and I'm saying the solutions you propose are worse than the problem. Writing false to the editedsincelastsave property is bad because you have no information on whether or not something else changed between creating and deleting those records, and unconditionally saving with no user input like you seem to be trying to do is even worse than a false negative since users could make a change they don't want saved but you saved anyway.
As for saveOpenedFile, look at CE's source. saveOpenedFile indirectly calls TMemorystream.SaveToFile. It doesn't access editedsincelastsave.
The saveTable function will set editedsincelastsave to false; however, you should not overwrite the same table the user just launched for the reason already stated.
The correct solution/workaround in your case (and perhaps OP's) is to not add/remove memory records dynamically. Instead, use registersymbol to change memory records' addresses dynamically, and TMemrecOptions to show/hide children as needed.
You're trying to implement a workaround for a workaround for a problem that could've been avoided had you done what the majority of other people already do. It's not even that big of a problem to begin with compared to the problems associated with your workarounds.
As far as CE is concerned, this is a bug for which there are 2 possible solutions:
- Make DontSave a parameter to TAddresslist.addaddress and conditionally set editedsincelastsave. (should also set editedsincelastsave to true if DontSave is later set to true)
- Correctly check if the user has any unsaved data.
(the first being a workaround for the second)
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25806 Location: The netherlands
|
Posted: Thu Oct 29, 2020 5:12 pm Post subject: |
|
|
Add this to your code:
Code: |
MainForm.OnCloseQuery=function()
messageDialog('Throw away all your unsaved changes?', mtConfirmation, mbYes, mbYesToAll)
return true
end
|
(Perhaps remove the messageDialog for a smoother less infuriating close)
_________________
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 |
|
 |
paul44 Expert Cheater
Reputation: 2
Joined: 20 Jul 2017 Posts: 206
|
Posted: Sat Oct 31, 2020 3:28 am Post subject: mem_record 'placeholders'... |
|
|
@Dark Byte: works, and thx for that.
@ParkourPenguin: for argument's sake, let's say I follow your suggestion. If I understood correctly, one creates an x number of mem_records in advance (as part of the CT design), and use those as 'placeholders' for "them ship records". Doable, and probably even easier to implement since 'no mr management'... I haven't tried this out yet, but I see 2 issues coming up: (I refer back to my linked example in my prev post)
say, the script finds 13 ships in vicinity (never really counted them during my testing, but 20+ records will probably be exceptional); and I have foreseen - let's say - 30 'mr placeholders', then:
1. how can one hide the remaining 17 'placeholders' in the sublist.
You suggest to make use of 'TMemrecOptions' (which - I take - are those 'parent' flags ~ moHideChildren), but as far as I know/researched, these only apply to (all) children, linked to that parent?!
(I did do some research on this particular issue - hiding individual mem_records - recently; trying out '.Visible', color transparency, andwhatnot... still trying though...)
2. if individual (sub)mr-s can be shown/hidden on-the fly, will that not set the "save" flag as well... ? Iow: upon quiting CE, one still gets the 'save'-prompt? Do not get me wrong: I will still try out/apply this technique, even it is just for experience sake.
ps: forgive my lack of experience if i'm misinterpreting your suggestion "use registersymbol to change memory records' addresses" completely. if you happen to know of a table or 2 using that technique, let me know... and I'll figure it out myself eventually.
ps2: re your suggestion "look at CE's source": this is actually not the 1st time I asked somebody this question, so: there are a ton of (code) files there: how would one go about and find any/all reference(s) to - for example - 'saveOpenedFile' ?
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4704
|
Posted: Sat Oct 31, 2020 11:58 am Post subject: |
|
|
I never thought about OnCloseQuery. I still think disregarding save confirmation isn't a good thing, but perhaps people that don't make tables would be fine with it.
Presenting a dynamically changing collection of elements to the user is more challenging. I still think adding/removing records is bad in this case since settings defined by users on these records (e.g. freeze value, hotkeys) would be lost. You could create another header under the main header and hide all the currently invalid records under that one.
(the best way of going about this is to make your own gui, but that takes more effort)
TMemoryRecord.appendToEntry doesn't access editedsincelastsave as far as I can tell. If that doesn't, I can't imagine reordering elements would either.
The visible property of memory records isn't accessible to Lua. (published properties generally are; public/private generally aren't)
Look up "injection copy" for examples of tables that change memory records' addresses through registered symbols.
There's a search bar on github. Search for saveOpenedFile in the CE repository, and two files with matches will come up: "Cheat Engine/bin/celua.txt" (documentation), and "Cheat Engine/LuaHandler.pas" (definition):
Code: | lua_register(L, 'saveOpenedFile', lua_saveOpenedFile);
// further up:
function lua_saveOpenedFile(L: Plua_State): integer; cdecl;
begin
if lua_gettop(L)>=1 then
filehandler.commitchanges(Lua_ToString(L,1))
else
Filehandler.commitChanges;
result:=0;
end;
|
The next clue is "Filehandler.commitChanges". If I was more familiar with Pascal I'd be able to track this down faster, but with a little searching you'll find the file "Cheat Engine/Filehandler.pas":
Code: | procedure CommitChanges(fn: string='');
begin
if filedata<>nil then
begin
if fn='' then
fn:=filename;
filedata.SaveToFile(fn);
end;
end;
// further up:
var filename: string;
filedata: TMemorystream;
... | TMemorystream belongs to Pascal's Run-Time Library and certainly won't set editedsincelastsave to false. Hence, calling saveOpenedFile in Lua won't prevent the confirmation dialog from being shown.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
paul44 Expert Cheater
Reputation: 2
Joined: 20 Jul 2017 Posts: 206
|
Posted: Sun Nov 01, 2020 9:48 am Post subject: Some feedback & closing "my request" |
|
|
@ParkourPenguin: thx for that guidance on locating that info. one still needs to know a particular fn_name to get there, but this will already get me going. in fact, will be trying this out on another idea
Recap:
1. "people that don't make tables would be fine with it": you nailed it right there and then. I don't think I'm far of target to state that 80+% of people using a cheat table even care/bother how this works; as long as it does what it claims.
In my particular case f.e.: 'ship records' "die" within minutes - even if one sticks around - and principly not important to the gamer once it did "its thing". As for those who know their way around: either they'll come back to you and ask why the table did not detect any change, or they figured it out themselves, or - as I do myself - they save regularly
On that note: when I use a table (mine or from others) during gameplay, I consider myself part of that 80+% (just saying)
2. as for "not saving": setting the 'OnCloseQuery' property will "remove" the 'save'-prompt, but one can still manually (force) save (and that definitely needs to stay that way). Also: once set it will apply apply for the duration of that CE session (ps: do not set to 'false' as you can no longer quit ~ 'end task' )
with that said: even if somebody happened to screw up a table completely, they can always download it again, right ?
3. "create another header": I actually gave this one some thought already; and figured I could use my 'comments' header to "hide" them 'unused placeholders' there (set to 'always hide children)'... (see my prev post link)
4. "visible property of memory records isn't accessible to Lua": that is truly a bummer, and I tell you why: [ https://imgur.com/a/AdTfr59 ].
Basically: this is a settings page for that particular table. I have been figuring out for some time now what would be the best solution. Btw: this page feature started with the 'Browser Info' button, but then I figured that I could do far more with this...
Based on your feedback, the best I can do is make use of the 'always hide children' option; as shown in the link. Again: them 80% would/could care less how this works (but it would be neater if the option only showed up when 'active')
I can't say this enough, but thx again for helping out here, folks.
Closed on my part.
ps: just to be clear: by no means anyone should feel offended by my '80%' remark. it is not meant to be offensive nor degrading in any way/sense.
|
|
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
|
|