This fixes severe issues with NPCs with the older ISoT fix.
The previous patch used to set the time speed to -2 to stop time
every 6 frames when it should have been done every 3 frames to get
a 1/3 ratio.
However, even with that fixed, scheduled NPCs were affected by a
serious problem: their animations would be very janky looking and
distracting. The reason the previous change broke NPCs is that they
internally use the time speed to determine their walking
animation speed.
The natural fix -- keeping a constant time speed but manually
decreasing the time variable every 3 frames -- does solve that issue,
but causes NPCs to reach their destination too fast and spend a lot
of time waiting in front of doors.
In order to avoid that problem, I hooked the function that is
responsible for moving scheduled NPCs based on the time speed and
manually applied the 1/3 slow time multiplier. Surprisingly, this was
enough to completely fix the waiting issue... and of course this also
introduced yet another glitch.
NPCs were now moving backwards and facing the wrong direction whenever
a loading zone was activated... After one day of debugging I eventually
figured out that this is because the schedule position variable is
truncated every time it is supposed to stop updating (whenever time
is frozen for instance). This would normally not be an issue -- as the
variable only used to store integer values -- but our ISoT fix requires
the use of non-integer speeds, so the truncation becomes an obstacle
to restoring the ISoT.
The fix -- or rather the hacky workaround -- is to try to detect
position truncation and restore the last known good value.
Pointers to positions are registered by the "move scheduled NPC" hook;
every tick our own code hopes that the pointers are still valid,
looks at the current values and overwrites them if needed.
Not proud of this solution, but I don't see a better way to do it
other than manually patching every single NPC actor (which I don't
want to do).
Fixes issue #4
This drops support for anything other than 1.0.0 for two reasons:
* It is annoying to have to port patches to two different versions.
* Adding support for the cartridge 1.1 executable would require
porting all of the patches to a third version, and further
increase the cost of making new code patches.
Instead, we now only provide an IPS patch for 1.0.0. For other versions
a BPS patch is used to transform the game executable into a patched
1.0.0 executable. The benefits are twofold: all versions are now
supported, but without increasing the maintenance cost!