AbstractAGS allows one game to activate another game via the RunAGSGame() script function. This is useful in implementing arcade sequences and other game-within-a-game type things. These can be called Mini Games and designed to be run stand-alone or from within another game.
This module provides an easy method of calling and returning from mini games and an easy method of passing data back and forth. Examples illustrating the use of these functions are presented in subsequent sections of this document.
Download:MiniGame-M0100 (module only) (http://demo.agspace.ws/project/archive/MiniGame-M0100.zip)
MiniGame-T0100 (template example) (http://demo.agspace.ws/project/archive/MiniGame-T0100.zip)
or DemoQuest GiP Thread (http://www.adventuregamestudio.co.uk/yabb/index.php?topic=34048.0)
DescriptionWhat does this module do that RunAGSGame doesn't do? If you were just going to activate the games from the very beginning each time then this module wouldn't be necessary. However, the usual scenario is that the player wants to return to the previous game and game state from where he left. For example if the player plays an arcade game in a pub, when he quits playing he ought to find himself in the same spot in the same pub where he was standing just before activating the arcade game. The MiniGame module makes this as easy as pie.
Game RequirementsThe main game and each mini game it calls must have been created with the same AGS version, color depth, and resolution. All game files must be kept in the same folder. The main game and all the mini games must use the same version of MiniGame and have Room0.crm be a black/blank room.
Passing DataWhen a mini game is called it is often desired to pass data to it. For example, in some situations it would be desireable to use the player's money to make wagers in the mini game and then return the resulting winings or losses. The MiniGame module uses a data dictionary to pass data to and from mini games. Each data point is associated with a unique name. Data can be either a string or an integer and is accessed through the following functions.
MiniGame.sSet(String name, string value)
MiniGame.iSet(String name, int value)
MiniGame.sGet(String name)
MiniGame.iGet(String name)
Calling a Mini GameMini games are called using the MiniGame.Call() function below. The parameter
FILENAME specifies the name of the game file to be called. It may or may not include file extensions of ".exe" or ".ags".
// Call a mini game (from a room script or the global script)
miniGame.iSet("Money",player.InventoryQuanity[iMone.ID]);
MiniGame.Call("DemoCycle");
In this example, the amount of money in the player's inventory is passed to the mini game. The amount of money is stored in the data dictionary with a key of "Money". Next "minigame.exe" is called, when it terminates it will return to "mainagame.exe".
Starting the Mini GameThe mini game will be loaded and then started as a result of the above MiniGame.Call(). The next thing to do is to determine if the game has been started from the operating system or if it has been called. The function MiniGame.IsCalled() provids for this. A value of true is returned if called from another game and returns false otherwise. This function is normally used in Global Script's game start event handler, game_start().
// Mini Game Global Script
function game_start() {
// Mini Game startup script
if (MiniGame.IsCalled()) { // Read data dictionary
Money = MiniGame.iGet("Money"); Passed from caller
}
else { // Run from OS
Money = 10; // Give default amount
}
}
In the example above a global variable, Money, is set to the value stored in the data dictionary under a key "Money" if the game has been called. It is set to a value of 10 if the game was started from the OS.
Quitting a Mini GameIf the mini game has been called then data must be saved in the data dictionary and the calling game re-activated. If the game has been run directly from the OS it can simply quit in the normal way using the QuitGame() function. The preferred method of doing this is to create a global function in the global script similar to the example below. This function is then called from any interaction functions designated as game exit or quit.
// Mini Game Global Script
function ExitGame(int ask_first) {
MiniGame.iSet("Money",Money); // Save data and ...
MiniGame.Return(ask_first); // return to caller
}
In the example above the global variable Money is saved in the data dictionary via MiniGame.iSet(). Next the MiniGame.Return() function determines if the game was called or run from the operating system. If the game was called then the calling game is re-activated and the data in the data dictionary is passed back. If the game was run from the operating system then it's terminated normally using the AGS QuitGame() function.
Saving a Mini GameThe MiniGame module makes a call to the Game.SetSaveDirectory(). The specified directory name is formed by extracting the extension from the Game. FileName string.If this extraction does not result in a useable string then "SaveGames" is used instead. The success or failure of the Game.SetSaveDirectory() call should be checked before executing SaveGameSlot(), RestoreGameSlot(), DeleteSavSlot(), as follows..
// Save the Game
if (MiniGame.SaveAllowed()) {
SaveGameSlot(slot);
}
else {
Display("Error saving game, save directory not found");
}
Perhaps a better approach is to simply remove the Save functions from the Gui at start up using Gui control prperties.
// Remove save functions if not allowed
if (!MiniGame.SaveAllowed()) {
gOptionsSave.Visible = false; // Disable the Save button
gOptionsRestore.Visible = false; // Disable the Load button
}
Returning from a Mini GameWhen returning from a mini game, any data it passes back must be read from the data dictionary. This is done with a series of "if, else-if" statements in the Global Script's repeatedly_execute() event handler function. The MiniGame.IsReturningFrom() function is used in the conditional expression to determine which if any mini game has returned.
// Main Game Global or Room Script
function repeatedly_execute() {
// Script to return from mini game
if (MiniGame.IsReturningFrom("minigame.exe")) {
Read data dictionary returned by mini game
player.InventoryQuantity[iMone.Id] = MiniGame.iGet("Money");
}
else if (MiniGame.IsReturningFrom("anotherminigame.exe")) {
Read data dictionary returned by another mini game
}
}
Any data returned by the mini game can be retrieved and copied to the appropiate game variables using the MiniGame.iGet() and the MiniGame.sGet() functions as shown above.
Note: THIS MUST BE DONE IN THE REPEATEDLY EXECUTE HANDLER and not in the start game event handler because when returning from a mini game a RestoreGameSlot() operation is performed to return to the point in the game from where the mini game was launched. This will overwrite all game variables, so the data dictionary must be read after this occurs. The MiniGame.IsReturningFrom() function will return true only after the restore opertion is complete.
Known IssuesThe following issues are known to the author, who can be contacted by posting on the AGS tech forum or by sending PM correspondance.
- Double Screen Transitions - As of this writing it is not possible to execute RestoreGameSlot() before the first screen is displayed. This was briefly mentioned above. So instead of returning to the screen from which the mini
game was launched directly, it returns to ROOM0 whoose background is momentarily displayed before the desired screen is finally displayed as a result of RestoreGameSlot()'s execution. To make this less noticable, ROOM0's background image is a single color of black and contains no script or interactions. So when running directly from the OS ROOM0 is skipped and the game starts in another room as designated by the player character. When the game starts after returning from a call the GUI and mouse are turned off and the player is left waiting in a black room.When the RestoreGameSlot() executes the palyer is transported to the room from where he called the mini game.
Nested Calls
Nested MiniGame.Call()s are supported but have not been thourghly tested as of this release. Should someone try to do nested calls it is likely that it would work and that some issues would come to light.
API Documentation
A summary of this module's functions an Properties is given below. There are three categories of functions as follows:
- Functions used in the calling game
- MiniGame.Call()
- MiniGame.IsReturningFrom()
- Functions used in the called game
- MiniGame.Return()
- MiniGame.IsCalled()
- MiniGame.SaveSlot()
- Functions that are used in both
- MiniGame.iGet()
- MiniGame.iSet()
- MiniGame.sGet()
- MiniGame.sSet()
static function MiniGame::Call(String filename)
This function calls a mini game. The file containing the mini game must be in the same directory as the main game. It must also have the same resolution and color depth as the calling game. The file name of the mini game is given by the FILENAME parameter.
Save slots are numbered from 0 to 999. The game restart function uses slot 999 so it is reserved. The call stack uses utilizes save slots 998 to 998 - MiniGame_STACKSIZE.
In debug mode error messages are displayed if the specified game files do not exist or if the call operation cannot be completed. When debug is disabled these messages are surpressed. In either case the following error status is returned as follows.
Return:
eMiniGame_Ok - call complete successfully
eMiniGame_MiniFilenameErr - game file doesn't exist
eMiniGame_MiniGameDatErr - can't write to minigame.dat file
static function MiniGame::IsReturningFrom(String filename)
This function returns true if the game is starting up as result or returning from a previously called mini game. This fuinction is to be called from the repeatedly_execute() function of the calling game to know when to copy data from the memory buffer to game variables.
Return:
true - just returned from specified game
false - did not return from specified game
static function MiniGame::Return(int ask_first)
This function is called from any interaction or custom function to return to the calling game or to quit if the game was started from the operating system.
static function MiniGame::IsCalled()
This function returns true if the game was started from the OS and returns false if it was called by another game or is returning from a called game.
Return:
false - game was started directly from OS
true - game was called from another game
static function MiniGame::SaveAllowed()
This function returns true if a save directory was setup correctly. It returns false otherwise, in which case the main game and the mini games share the same save game space and would interfere with each other. In this case the mini game should be prevented from executing SaveGameSlot() operations.
Return:
false - prevent mini games from being saved
true - allow mini games to be saved
static function MiniGame::iGet(String name)
This function returns the integer value corresponding to NAME. If NAME doesn't exist an error mesage is generated.
static function MiniGame::iSet(String name, int value)
This function modifies value corresponding to NAME as specified by the VALUE integer parameter. If NAME doesn't exist the name-vale pair is appended to the end of the memory buffer. If there is no more room and error message is generated.
static String MiniGame::sGet(String name)
This function returns the string value corresponding to NAME. If NAME doesn't exist an error mesage is generated and a null string is returned.
static function MiniGame::sSet(String name, String value)
This function modifies value corresponding to NAME as specified by the VALUE string parameter. If NAME doesn't exist the name-vale pair is appended to the end of the memory buffer. If there is no more room and error message is generated.
Good stuff Rick, looking good!
Although, I haven't yet managed to win on the slot machine, it must be rigged >:(
;D
Good work! :)
The site is down at the moment but I'm looking forward to finally download and try this out.
The gaia-spa website should be back up tomorrow morning or sooner. The domain name expired and needed to be renewed. I am going to post a new version tomorrow so you all may as well wait for that anyway.
Cheers.
I am using a slightly modified SlotMachine script.
Lately I cannot save anymore, because of an error:
Type Mismatch, cannot convert const string to string.
The code is:
function GameQuit() {
//
// This function is called to terminate the game.
//-------------------------------------------------------------------
// Mini Game quit Script
MiniGame.iSet("Credits",GmCredits); // so save data and ...
MiniGame.iSet("HighScore",GmHighScore); // so save data and ...
MiniGame.Return(false); // return to main game
}
GmCredit is defined as integer.
I cannot understand why this used to work fine before, and now this error.
Any suggestions?
I am sorry to tell that I cannot access the links to download the scripts.
I did so before but lately errors come up in the MiniGame.ISet function (see my previous post).
Martijn
I don't believe that the files have been updated yet to work with AGS 2.71, which will probably be the cause of your problem.
Thanks. Is there a way I can update them myself?
If not, who could help me? Is Rick the great genious behind this?
Martijn
Generally the problem you're having is that now AGS won't let you try to change old-style strings if they are constants.
In order to fix the error, you have to go to the place where the MiniGame.iSet() function is declared and defined and change its first parameter type from string to const string.
There other functions may have the same problem.
Just don't change all of the functions, only those causing the error.
But yeah, ultimately it would be cool to update the script to support new-style strings.
would that be in some dll or so?
(sorry, I start to know the ags scripting language reasonably well, but I still am not an expert on programming :-()
It's a script module, just open the module manager (Main menu -> Script -> Module manager...).
Then choose the MiniGame module in the list.
Click Edit header, then find and change the function declaration there, as I described above (look into struct MiniGame for import function iSet(...)).
The exit&save and click Edit script, then find and change the function definition there too (look for something like MiniGame::iSet).
Hi Martijn,
Hehe, it's funny you ask about this as I am currently working on this (http://www.adventuregamestudio.co.uk/yabb/index.php?topic=24866.0). If you can wait a few days I should have the entire demo up to AGS V2.72 compatibility.
Also for general info the main game and all mini games must re-import the updated minigame module.
CJ, to update a module it's currently necessary to remove the module and then import it again. Would it be possible to just display a warning dialog and give the user the choice of ovewrwriting or aborting?
Thanks for helping.
The errors are solved. Something seems to have gone wrong in the main code though. My version does not reach the GameState = START anymore.
Can I download the original code somewhere? The link mentioned above:
http://www.gaia-spa.com/project/demo/Archive/DQSLOT-S000-001.zip
is dead.
regards,
Martijn
Links to the latest version of Demo Quest are maintained in the "Games in Produiction" forum in this thread:
http://www.adventuregamestudio.co.uk/yabb/index.php?topic=23083.0
Let me know if you have any trouble with them. Also keep in mind there will soon be another update for V2.72 compatibility.
Hi Rick,
Nice to work with you again!
I downloaded the beta-versions, but the DQcycle game does not run.
I repaired the const string definitions, but I still cannot run the game.
I do not reahc the gamestate start.
Any suggestions?
Martijn
What vesion of AGS are you using? The links I gave you only work with AGS 2.70. I will have a new version of everything in a couple of days that works with V2.72.
Quote from: RickJ on Thu 02/02/2006 02:41:32
CJ, to update a module it's currently necessary to remove the module and then import it again. Would it be possible to just display a warning dialog and give the user the choice of ovewrwriting or aborting?
Interesting point, that's something that could perhaps be improved.
Quote from: RickJ on Thu 02/02/2006 14:19:39
What vesion of AGS are you using?Ã, The links I gave you only work with AGS 2.70.Ã, I will have a new version of everything in a couple of days that works with V2.72.
Rick, thanks for answering. I use AGS 2.71.
The reason i am eager to adjust this version is that I already impoterd many sprites, changed obejct and character interactions, and created many new functions to work in the script.
I would love to make this "newly adjusted old version" work with AGS27.1.
If it is not possible, I'll have to look into the new code and redo the work,
martijn
Is it due to the restartgame(); problem, mentioned by largopredator elsewhere in this forum?
I'll publish a new version of the module this weekend, probably Sunday. It don't think it uses any of 2.72 features and so should be compatible with 2.71.
Edit:
Thanks monkey for the correction.
Quote from: spook1 on Fri 03/02/2006 17:59:58
Is it due to the restartgame(); problem, mentioned by largopredator elsewhere in this forum?
Martijn, I wasn't sure what you are referring to but I checked it out and found that it was related to my suggestions. Thanks.
Monkey, thanks for the correction.
Rick,
I am not sure that I have understood all discussions on this topic. Is there a workaround now for this MiniGame problem, that I can implement?
Regards, Martijn
Here is a snap shot of the MoiniGame module that you can probably use for your purposes Martijm. I will post newer versions as they become available. Let me know if you have any p[roblems with this.
MiniGame_V102.scm (http://www.gaia-spa.com/project/ags/modules/MiniGame_V102.scm)
Rick,
I imported the module version102. Still I cannot start the game.
I get an introsequence, after that the display: "Press enter to start the game. " But pressing enter does not result in any game starting.
Nothing happens...
any suggestions?
Have you imported the module into both games? Have you tried upgrading to AGS 2.71 or V2.72? I have seen this behavior recently while I was changing the module. I didn't try to find out exactly what was happening because I knew I had things out of sync. The problem eventually went away. If importing the module into both games doesn't fix the problem let me know and I'll upload the current DemoQuestand DQCycle games for you.
I did not import the module in the maingame (my maingame is named SpaceSpy). I run the minigame as standalone for the time being. Implementing in the main game is planned later, when the minigame is finished so to say.
Won't the module work as standalone anymore?
I am sorry to confess that I do not understand the module completely :-(
regards,
Martijn
Upload your game somewhere and I'll take a look at it. I PM'ed you the FTP info for my site if you wish to upload there.
Let me know what version of AGS you are currently using and the URL where I can get the game and I'll have a look.
Quote
I am sorry to confess that I do not understand the module completely :-(
It's a diffcult module to understand because of the way Save/Restore game functions work and from where they can and can't be executed. What happens is that the actual operations are not performed where the instruction appears in the code but after after that particular script is completed. So instructions that appear after the Save/Restore instructions in the script are actually executed before the Save/Restore operations are performed.
In addition, the Restore operation overwrites all the variables so if you want to set a flag or other variables to remember what the module is doing you have to play some tricks, like saving/restoring some data in a text file and taking advantage of the RunAGSGame() data parameter.
So don't feel too bad about not understanding it fully. For the same reasons I am not yet happy with the scripting of this module and aI am currently trying to make it a little les convoluted.
Just wanted to bump the thread and announce a new version. It requires AGS V2.72 so if you are using an earluer version of the module with an earlier version of AGS just stay with what you got. Cheers.
Does anyone know what happened to minigame? It looks like exactly what I need, but none of the links on this page seem to work.
Edit: ah, it appears that the demoquest game has it all.