Good morning/afternoon/evening. With saves implemented and most warnings dealt with we’re one step closer to the final stage. The game is should be mostly playable at the moment, but the only way to verify that is to actually test it.
Debug Commands
In order to facilitate our endeavors, it is useful to create lots of debug commands (I’ve explained how to implement them in the last post).
Here is the full list of commands added so far:
// Input: <None>. Kills the center actor
bool cmdKillProtag(int argc, const char **argv);
// Input: <Actor ID>. Kills an actor
bool cmdKill(int argc, const char **argv);
// Input: <Object ID>. Prints an object's name
bool cmdObjName(int argc, const char **argv);
// Input: <Name Index>. Prints an ObjectID corresponding to the name index.
bool cmdObjNameIndexToID(int argc, const char **argv);
// Input: <Object Name>. Prints a list of objects containing the string in their name
bool cmdSearchObj(int argc, const char **argv);
// Input: <Object ID>. Adds the object to the center actor's inventory.
bool cmdAddObj(int argc, const char **argv);
// Input: <1/0>. Sets godmode
bool cmdGodmode(int argc, const char **argv);
// Input: <1/0>. Sets whether the position coordinates show
bool cmdPosition(int argc, const char **argv);
// Input: <1/0>. Sets whether an item's stats show when holding it
bool cmdStats(int argc, const char **argv);
// Input: <1/0>. Sets whether you can teleport by clicking on the screen
bool cmdTeleportOnClick(int argc, const char **argv);
// Input: <u> <v> <z>. Teleports the center character to the given position
bool cmdTeleport(int argc, const char **argv);
// Input: <Actor ID>. Teleports the character to the npc
bool cmdTeleportToNPC(int argc, const char **argv);
// Input: <Actor ID> <u> <v> <z>. Teleports the npc to the given coordinate
bool cmdTeleportNPC(int argc, const char **argv);
// Input: <Actor ID>. Teleports the npc to the center actor
bool cmdTeleportNPCHere(int argc, const char **argv);
// Input: <None>. Saves the current location in a variable
bool cmdSaveLoc(int argc, const char **argv);
// Input: <None>. Teleports the center actor to the saved location
bool cmdLoadLoc(int argc, const char **argv);
// Input: <Place ID>. Teleports to the given place
bool cmdGotoPlace(int argc, const char **argv);
// Input: <None>. Lists all of the place names along with their IDs
bool cmdListPlaces(int argc, const char **argv);
// Input: <Map Scale Multiplier>. Dumps the map into a png.
bool cmdDumpMap(int argc, const char **argv);
Method
I’ve used the playlist by Sinatar as a basis of what a normal gameplay would look like (also helps me keep track of the normal course of the story). With that open, I proceed along the gameplay with ScummVM and if there’s something specific I wish to check, I open DOSBox and compare the two. Having backwards compatible saves here helps a lot.
One of the first things I wished to check was whether I could reach an ending. I did some research and took notice that I needed three Golden Apples to open the passage to the underworld.
Once there we can teleport the final boss, Sariloth to us with teleport_npc_here 32977
.
Defeating Sariloth on DOSBox caused one of the endings to play, but here on ScummVM it only made the New Game dialog pop up.
Comparing the source code for playing the endings we can see that some code got lost in the reformatting.
tromode.cpp:
void setLostroMode(void) {
allPlayerActorsDead = false;
if (GameMode::newmodeFlag)
GameMode::update();
if (!abortFlag) {
...
original/tromode.cpp
void setLostroMode( void )
{
waitForVideoFile( "INTRO.SMK");
allPlayerActorsDead = FALSE;
if (GameMode::newmodeFlag)
GameMode::update();
if (!abortFlag)
{
...
abortFlag
is set to false
inside of waitForVideoFile
, so we fix that by adding a abortFlag = false;
at the top of setLostroMode
(this code is candidate for some more code reformatting, though).
Bugs
Other than that, by following the walkthrough I took notice of some lesser bugs as well. Here is a list of the bugs I’ve annotated so far:
Bug | Steps to reproduce | Explanation |
Speech is too quiet (compared to music/sound effects) | ||
Music does not loop when it finishes | It loops periodically on the original | |
Music does not disappear completely when volume is set to zero | Set the music to zero | You can hear it faintly even when the slider is fully on the left |
Music does not restart | After setting the music to zero, raise it once again | It should restart on the original |
Music Volume not reflected to what is on the config when the game starts | Set the volume to 0, restart game | The volume will be at 0 in the options but music will be blasting at full volume |
Arrow sprite not changing when reading scroll | Open the scroll in the Padavis Inn | The arrow sprite should change to an up arrow when hovering on the upper part and vice-versa for the lower part on the original |
Close parchment button not working | Open the parchments on the notices board in Padavis Inn | The close button does not work (although clicking outside the parchment closes it) |
Speech not finishing before dialog to buy beer starts | Pavilion Bar – buy beer with Riddenbutter | On the original, the buy dialog should appear after the speech ends |
Crash on reading Kaidar’s book | cmd: add_obj 274 and read book in chest | The book is readable on the original |
Crash on saving/loading when spells are present | Go to the Underworld and save when the Wraiths are casting spells, then load the save | |
Crash on Credits (options menu) | Click on the credits button | |
Fade-in not working when loading a world with WorldID > 0 from the launcher | Load a save from the Underworld from the launcher | The screen flickers and the fade-in does work properly |
From now on the development will consist mostly of playtesting and solving bugs. After that I suspect refactoring, solving warnings on other platforms and creating documentation may become of more importance. Thankfully I only have two weeks of school left, so in the worst case scenario I still have plenty of time after that. Let’s hope this project ends in success!
Leave a Reply