Because autosave can be triggered at any time, there may be empty lists present
in the engine. Avoid crashing if the UCList is empty. Should fix bug #13852.
Previously we used the Ultima 8 behavior of not terminating any obj id 0
processes on level change, but that occasionally left never ending "alarm has
been activated" background audio and similar problems.
This changes so that all but the "persistent" processes are terminated.
At the same time, also correctly clean up the snap egg and target lists when
changing maps - previously these were left sitting around.
The original game resets this flag when 'g' or 's' buttons are pressed. I
assume this was a workaround in the original for the same problem we see in bug
13381. Reproduce the hack from the original game.
After inspecting the usecode, this flag seems to only be set and cleared on
teleport events. It has no real effect on the behavior of the C code but it's
nice to name it correctly.
This might help with bug #12182 where the comment suggests there is a problem
with loading the treasure data. To make sure it loads properly, added a lot
more error checking and error messages, and created unit tests for the same.
On death, the original game only destroys the contents for actors who are
marked as FAST_ONLY, so important NPCs should not lose their contents.
This should improve the behavior a bit and might help to fix bug #12504 (where
malchir should drop a book) - but it does not totally fix that problem so there
is still something else that needs fixing.
In cbcebce55d, I changed the meaning of the flag from "force" to
"move_if_blocked" to fix Crusader's spider bombs. However, with bug #13359
and re-reading the disassembly, true meaning of the flag is more like the
opposite, "abort_if_blocked".
* If the flag is set and the move is blocked, it should not do the move at all.
* If the flag is clear, it should move as far as the blocker.
The return value is 1 if the move completed with no blockers - always 0 if
there was a blocker, even if a partial move was done.
This fixes#13359, and spider bombs still work. Probably fixes some other
weird behavior too.
The engine code would move the camera to the remote viewing location, but the
snap process pulled it back to the player. Fix by disabling snap-to-player if
the avatar is in stasis.
This fixes#13360
In No Regret, there are some areas with a certain invalid shape. Avoid spamming
the log with warnings on every frame in this case.
Also correct variable naming - frame is a local not a member.
I spent all day looking at decompilation and I still don't understand why these
items are not destroyed in the original game, but they shouldn't be destroyed.
Previously x/y values were being divided and multiplied to get the right values
in Crusader with no explanation why. Add a small wrapper function to make it
explicit what is happening.
Also replace unused intrinsic variables with ARG_NULL to avoid unused variable
warnings in some newer gcc versions.
The original multiplies the direction value by 2 on load.
This and the previous fix to Pace Process fixes the first NPC guard in No
Remorse difficulty level so he now behaves almost identical to the original
game, yay!
Previously we were not waiting for the correct anim process in the turn, which
caused frequent ANIM_LOCK warnings and the actors did not turn to the correct
final direction.
This fixes pace so they now correctly pace back and forth.
There are some rare cases where modals can stack (eg, credits playing on top of
menu). In this case we want to close the credits first, then the menu.
Add a little hack to ensure the order is right.
This also fixes#12995.
A followup to bug #13176.
One of the problems in the savegame on the bug is trying to pop items to
containers that don't exist. This maybe never happens in the original, but if
it does the item will be popped off the ethereal list and discarded anyway,
which we were previously not doing.
This mistake meant there were objects left over on the ethereal list which
shouldn't be there. They could probably get mixed up with other items by game
scripts, which is possibly the cause of the original bug.
In investigating, I also discovered that if a non-container is passed to the
original games the object will still be popped to the location of the
"container". I'm not sure if this behavior is ever needed, but implemented in
case.
Somehow the avatar got added to the ethereal list, but the ethereal flag isn't
set on the actor and avatar shouldn't be ethereal at this point. Just drop
them from the ethereal list.
I tried working out how it got into this state but can't see any sensible path
that could cause it other than maybe a corrupted save? For now just do a
workaround.