I hope you take no offense to this post, none was meant.
Just to be clear, I'm using AOB scans to locate ASM opcodes. I'm changing the code, not the stored memory values. For example, I'm not using the trainer to set scrap to a high number and then freezing it. I'm actually using a simple method where I change the code that displays the player's scrap to also write scrap to a high number. This write is NOT done by Cheat Engine. FTL itself now writes the value. This is actually a lame method that won't work for most games (see Shared Code), but it was quick and easy and works perfectly for FTL.
Finding pointers can be a time consuming process and usually must be done for each new version of a game (assuming the new version changes the code and not just graphics/sfx). I have often found a pointer I thought was stable, only to find that at a later date or on a different computer, the pointer was no longer valid. You sound like you found a stable one that works with many versions? If so, that is lucky, you don't find it often. Pointers are less useful then just changing the game rules themselves through opcode modifications. You can change or freeze values with pointers, but that doesn't let you do more advanced things. Freezing a memory address through a trainer has often given me mixed results in the past. Sometimes the freezes will slow the game down, especially on older machines, or machines that barely run the game in question. An outside process (the trainer) must constantly write the value into the game process, which as I mentioned can create unnecessary overhead. A small change to the games code directly is faster. An example of something that can't be done in some instances with pointers is an invulnerabiliy code. The player's health is read from memory, modified, checked, and then written back into memory. The modify and checked portions are what is important here.
The trainer has frozen the player's health through a pointer to 100. The opcodes read that value into a CPU register (outside a pointers influence). The value is dropped to zero by incoming damage calculations by the opcodes (once again, in the CPU registers, not memory). Then the opcodes check to see if the health (in the CPU register) is 0 or lower. If it is, the player has died. The code would also write this new health back into memory for display purposes (the HUD). As you can see, it's too late to save the player. The pointer freeze would, of course, write 100 back over the 0, but it's still too late. The game code has already decided the player is dead and has taken action accordingly.
This is not to say pointers are useless. Sometimes it's difficult or impossible to change opcodes in a useful way.
Still, I try to use them sparingly and only when I can't find another way.
About the pointer address you mentioned. "FTLGame.exe+0x00300000" is a relative response for 0x00700000
Applications usually start at 0x00400000.
So FTLGame.exe = 0x00400000.
The pointer you found is 0x00300000 away from that.
So 0x00400000+0x00300000 = 0x00700000 or...
If FTLGame.exe had started at 0x00200000 instead, then "FTLGame.exe+0x00300000" would still be valid, whereas 0x00700000 would not! (It would be at 0x00500000)
"FTLGame.exe+0x00300000" would now represent 0x00500000
The trainer table is here:
The trainer only uses Cheat Engine's Auto Assemble functions to modify opcodes. It can be confusing to read if you don't know what it is doing. If you have any questions, just let me know.FTLTrainerCT.zip