Hello World. First post here.
I just implemented a puzzle in an AGS game I'm working on that works like this:
A man is reading a book at a table in a cafe. You need that book. If you try to take it, he will shod you off. However, if you go over to the jukebox and change the song to something obnoxious, the guy will leave his table and book and head over to the jukebox to change back.
Of course, while he is away from his book, you can steal it.
I managed to get the puzzle working, but I feel like the code is a bit shoddy, and I'm wondering if there's a cleaner, better way than to solve it like this.
(I am using the SCUMM-like 9-verb GUI that came with the latest version of AGS, but I believe the principle would be the same no matter what GUI you use.)
Here is the code for when the player USES the jukebox:
function oJukebox_AnyClick()
{
if(UsedAction(eGA_Use)) {
player.Walk(224, 72, eBlock, eWalkableAreas);
player.FaceDirection(eDir_Up); // Player walks over to the jukebox and face it
SetGameOption(OPT_CROSSFADEMUSIC, 0); // I want abrubt change of music
aClub_Diver.Play(); // Play obnoxious song
Wait(40); // There needs to be a delay from when the music starts to when the guy leaves his table
SetGameOption(OPT_CROSSFADEMUSIC, 3); // In case the player leaves the room while the new music is playing
cBarPatron4.Walk(218, 73, eNoBlock, eAnywhere); // The Guy walks to the jukebox.
}
}
Then, in the room_RepExec function I put the following code:
if(cBarPatron4.x == 218 && cBarPatron4.y == 73 && jukebox_limiter == true) { // Repeatedly check if the NPC is at the location he was told to walk to.
jukebox_limiter = false; // This is here to stop the game from freezing when the NPC reaches his destination. It's a boolean, with a default value of "true".
SetGameOption(OPT_CROSSFADEMUSIC, 0); //I want abrubt change of music
aBass_Vibes.Play(); // Play the calm music again
cBarPatron4.Walk(68, 86, eNoBlock, eAnywhere); // The NPC heads back to his table
SetGameOption(OPT_CROSSFADEMUSIC, 3);
}
if(cBarPatron4.y == 74) { // Once the NPC is on his way back, it is possible to change the music again.
jukebox_limiter = true;
}
The code for picking up the book is a simple "if" checking if the NPCs x-coordinates are above a certain value.
Is this a good way of solving this? It feels a bit unelegant to do a constant check in the room_RepExec function to see if the NPC is at a given location. Is it possible to stop the game from running the next line of code in the function until the previous line has been completed? In this case, that would mean that the game would not change the music or send the NPC back to his original location before he reached the jukebox, even if I put all the code in a single function (all while the player is free to move and interact, so I can't use eBlock).
Tips and pointers greatly appreciated!
It looks like you're doing pretty much the right thing.
I would change it from detecting exact x,y coordinates for the character to instead use room regions. You just need one region placed at the jukebox.
Region *r = Region.GetAtRoomXY(cBarPatron4.x, cBarPatron4.y);
if (r == region[1])
{
if (jukebox_limiter == true)
{
// stuff
jukebox_limiter = false;
}
}
else
{
jukebox_limiter = true;
}