Difference between revisions of "Advanced Engine Features"

Jump to navigation Jump to search
m
Fullpipe renamed to NGI.
m (Fullpipe renamed to NGI.)
 
(10 intermediate revisions by 3 users not shown)
Line 25: Line 25:


'''Implemented by:'''
'''Implemented by:'''
[[AGOS]], [[Draci]], [[Gob]], [[Kyra]], [[Lure]], [[Mohawk]], [[Mortevielle]], [[Parallaction]], [[Pegasus]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sword2]], [[Toon]], [[ZVision]]
[[AGOS]], [[Draci]], [[Gob]], [[Kyra]], [[Lure]], [[Mohawk]], [[Mortevielle]], [[Parallaction]], [[Pegasus]], [[SAGA]], [[SCI]], [[SCUMM]], [[Supernova]], [[Sword2]], [[Toon]], [[ZVision]]


'''Not implemented by:'''
'''Not implemented by:'''
[[AGI]], [[Avalanche]], [[CGE]], [[Cine]], [[Composer]], [[CruisE]], [[Drascula]], [[Dreamweb]], [[Fullpipe]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Lastexpress]], [[MADE]], [[Neverhood]], [[Queen]], [[Sky]], [[Sword1]], [[Sword25]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]]
[[AGI]], [[Avalanche]], [[CGE]], [[Cine]], [[Composer]], [[CruisE]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Lastexpress]], [[MADE]], [[Neverhood]], [[NGI]], [[Queen]], [[Sky]], [[Sword1]], [[Sword25]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]]


'''Support not necessary:'''  
'''Support not necessary:'''  
Line 38: Line 38:


'''How to implement it'''<br>
'''How to implement it'''<br>
You can implement this by checking for and honoring the EVENT_RTL event. A much easier way, which also gives you some other advantages (e.g. this also covers EVENT_QUIT), is to regularly poll the return value of Engine::shouldQuit(). If it returns true, you should break out from your main game loop and your Engine::run() method should return to the caller.  
You can implement this by checking for and honoring the EVENT_RETURN_TO_LAUNCHER event. A much easier way, which also gives you some other advantages (e.g. this also covers EVENT_QUIT), is to regularly poll the return value of Engine::shouldQuit(). If it returns true, you should break out from your main game loop and your Engine::run() method should return to the caller.  


'''Relevant Engine API'''
'''Relevant Engine API'''
Line 45: Line 45:
bool shouldQuit() const;
bool shouldQuit() const;


kSupportsRTL feature flag
kSupportsReturnToLauncher feature flag
</syntaxhighlight>
</syntaxhighlight>


'''Implemented by:'''
'''Implemented by:'''
[[AGI]], [[AGOS]], [[CGE]], [[Cine]], [[Composer]], [[CruisE]], [[Draci]], [[Drascula]], [[Gob]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lastexpress]], [[Lure]], [[MADE]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Sword1]], [[Sword2]], [[Sword25]], [[TeenAgent]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]
[[AGI]], [[AGOS]], [[CGE]], [[Cine]], [[Composer]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Gob]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lastexpress]], [[Lure]], [[MADE]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[NGI]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Supernova]], [[Sword1]], [[Sword2]], [[Sword25]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]


'''Not implemented by:''' [[Avalanche]], [[Dreamweb]], [[Fullpipe]], [[Tinsel]]
'''Not implemented by:''' [[Avalanche]]


===Global options dialog support===
===Global options dialog support===
Line 69: Line 69:


'''Not implemented by:'''
'''Not implemented by:'''
[[Avalanche]], [[CGE]], [[Composer]], [[Drascula]], [[Dreamweb]], [[Fullpipe]], [[Mohawk]], [[Neverhood]], [[Parallaction]], [[Pegasus]], [[Sword25]], [[Tucker]], [[Wintermute]]
[[Avalanche]], [[CGE]], [[Composer]], [[Drascula]], [[Dreamweb]], [[Mohawk]], [[Neverhood]], [[NGI]], [[Parallaction]], [[Pegasus]], [[Sword25]], [[Tucker]], [[Wintermute]]


'''Support not necessary:''' [[AGI]], [[Mortevielle]], [[TeenAgent]], [[Tinsel]], [[Toon]]
'''Support not necessary:''' [[AGI]], [[Mortevielle]], [[TeenAgent]], [[Tinsel]], [[Toon]]
Line 95: Line 95:


In this section, we present various MetaEngine and Engine APIs which greatly experience
In this section, we present various MetaEngine and Engine APIs which greatly experience
the user experience with regards to savestates.  
the user experience with regards to savestates. These days, the bulk of logic for listing, loading, saving, or deleting savegames is provided by the Engine class. As engine writers you only need to override loadGameStream & saveGameStream to read and write data from savefiles.




Line 114: Line 114:


'''How to implement it'''<br>
'''How to implement it'''<br>
You have to implement MetaEngine::listSaves(), which takes a parameter indicating the target for which the list of savestates is requested. From this, you can (using the config manager) determine the path to the game data, if necessary, or just directly compute all available savestates. Details necessarily depend on your Engine, but looking at existing implementations should give you a fairly good idea how to tackle this.
You probably don't. Newly created engines, which use loadGameStream & saveGameStream, automatically use the extended savegame format. With this, the Engine class already provides a default implementation of listSaves for you. However, if for some reason you want to override it, such as if you're providing your own custom savegame implementation from scratch, the method is passed a parameter indicating the target for which the list of savestates is requested. From this, you can (using the config manager) determine the path to the game data, if necessary, or just directly compute all available savestates. Details necessarily depend on your Engine, but looking at existing implementations should give you a fairly good idea how to tackle this.


Another requirement is MetaEngine::getMaximumSaveSlot, which returns the maximum save slot number supported by your engine. This is for example used by the GUI to show up empty slots correctly.
Another requirement is MetaEngine::getMaximumSaveSlot, which returns the maximum save slot number supported by your engine. This is for example used by the GUI to show up empty slots correctly.
Line 131: Line 131:


'''Implemented by:'''
'''Implemented by:'''
[[AGI]], [[AGOS]], [[Avalanche]], [[CGE]], [[Cine]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lure]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Sword1]], [[Sword2]], [[Sword25]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[Tucker]], [[Wintermute]], [[ZVision]]
[[AGI]], [[AGOS]], [[Avalanche]], [[CGE]], [[Cine]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lure]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Supernova]], [[Sword1]], [[Sword2]], [[Sword25]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[Tucker]], [[Wintermute]], [[ZVision]]


'''Not implemented by:'''
'''Not implemented by:'''
[[Composer]], [[Fullpipe]], [[Gob]], [[Lastexpress]], [[MADE]], [[TeenAgent]], [[TsAGE]]
[[Composer]], [[Gob]], [[Lastexpress]], [[MADE]], [[NGI]], [[TeenAgent]], [[TsAGE]]


===Loading savestates via command line or Launcher===
===Loading savestates via command line or Launcher===
Line 151: Line 151:


'''Implemented by:'''
'''Implemented by:'''
[[AGI]], [[Avalanche]], [[Cine]], [[CGE]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lure]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Sword1]], [[Sword2]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]
[[AGI]], [[Avalanche]], [[Cine]], [[CGE]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lure]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Supernova]], [[Sword1]], [[Sword2]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]


'''Not implemented by:'''
'''Not implemented by:'''
[[AGOS]], [[Composer]], [[Fullpipe]], [[Gob]], [[Lastexpress]], [[MADE]], [[Parallaction]], [[Sword25]]
[[AGOS]], [[Composer]], [[Gob]], [[Lastexpress]], [[MADE]], [[NGI]], [[Parallaction]], [[Sword25]]


===Deleting savestates via the Launcher and GMM===
===Deleting savestates via the Launcher and GMM===
Line 174: Line 174:


'''Implemented by:'''
'''Implemented by:'''
[[AGI]], [[Avalanche]], [[Cine]], [[CGE]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lure]], [[Mohawk]], [[Neverhood]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Sword1]], [[Sword2]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]
[[AGI]], [[Avalanche]], [[Cine]], [[CGE]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lure]], [[Mohawk]], [[Neverhood]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Supernova]], [[Sword1]], [[Sword2]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]


'''Not implemented by:'''
'''Not implemented by:'''
[[AGOS]], [[Composer]], [[Fullpipe]], [[Gob]], [[Lastexpress]], [[MADE]], [[Mortevielle]], [[Sword25]]
[[AGOS]], [[Composer]], [[Gob]], [[Lastexpress]], [[MADE]], [[Mortevielle]], [[NGI]], [[Sword25]]


===Savestate metadata support===
===Savestate metadata support===
Line 199: Line 199:


'''Implemented by:'''
'''Implemented by:'''
[[AGI]], [[Avalanche]], [[CGE]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Mortevielle]], [[Neverhood]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sword1]], [[TeenAgent]], [[Toltecs]], [[Tony]], [[Toon]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]
[[AGI]], [[Avalanche]], [[CGE]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Mortevielle]], [[Neverhood]], [[SAGA]], [[SCI]], [[SCUMM]], [[Supernova]], [[Sword1]], [[TeenAgent]], [[Toltecs]], [[Tony]], [[Toon]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]


'''Not implemented by:'''
'''Not implemented by:'''
[[AGOS]], [[Cine]], [[Composer]], [[Fullpipe]], [[Gob]], [[Lastexpress]], [[Lure]], [[Mohawk]], [[MADE]], [[Parallaction]], [[Pegasus]], [[Queen]], [[Sky]], [[Sword2]], [[Sword25]], [[Touche]], [[Tinsel]]
[[AGOS]], [[Cine]], [[Composer]], [[Gob]], [[Lastexpress]], [[Lure]], [[Mohawk]], [[MADE]], [[NGI]], [[Parallaction]], [[Pegasus]], [[Queen]], [[Sky]], [[Sword2]], [[Sword25]], [[Touche]], [[Tinsel]]


===Loading/Saving during run time===
===Loading/Saving during run time===
Line 214: Line 214:


Next, for each of the two, you have to implement two Engine methods (so up to four). We focus on adding loading support here: For that, first implement Engine::canLoadGameStateCurrently(). This method should only return true if loading a savestate is possible right now. If this is always possible, just always return true. But if loading is not possible at some points, say while a cutscene is playing, make it return false at these times.
Next, for each of the two, you have to implement two Engine methods (so up to four). We focus on adding loading support here: For that, first implement Engine::canLoadGameStateCurrently(). This method should only return true if loading a savestate is possible right now. If this is always possible, just always return true. But if loading is not possible at some points, say while a cutscene is playing, make it return false at these times.
Next,  the Engine::loadGameState() is used to request the loading of a specific saveslot. The GMM will invoke this method with a valid save slot, then hide itself. If there is an immediate error, you can indicate so with its return value (for details, refer to the doxygen comments), in which case the GMM will show an appropriate error dialog. You may delay the actual loading (that's what the SCUMM engine does, for example), but then you have to handle any occurring errors yourself (in particular, show an informative error dialog to the user).
Next,  the Engine::loadGameStream() is used to load save file data. Previously, this was loadGameState, but engines using it had to manually open the save files, so it's now deprecated. The GMM will invoke this method with a valid stream from an opened save file, allowing the engine to read from it. If there is an immediate error, you can indicate so with its return value (for details, refer to the doxygen comments), in which case the GMM will show an appropriate error dialog. In


'''Relevant Engine API'''
'''Relevant Engine API'''
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
virtual Common::Error loadGameState(int slot);
virtual Common::Error Engine::loadGameStream(Common::SeekableReadStream *stream);
virtual bool canLoadGameStateCurrently();
virtual bool canLoadGameStateCurrently();


Line 224: Line 224:
</syntaxhighlight>
</syntaxhighlight>


:'''Implemented by:''' [[AGI]], [[Avalanche]], [[Cine]], [[CGE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Pegasus]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Sword1]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]
Saving games is similar. Engines can override saveGameStream (rather than the now deprecated saveGameState). In this case, it gets passed in a write stream to a save file opened for saving. Additionally, it also gets passed a flag for whether an autosave is being created vs a save done by the user. Some engines may want to show a message or other indication in the UI after a save is done, but which shouldn't be done for regular autosaves.
 
:'''Not implemented by:''' [[AGOS]], [[Composer]], [[CruisE]], [[Fullpipe]], [[Gob]], [[Groovie]], [[Lastexpress]], [[Lure]], [[MADE]], [[Parallaction]], [[Queen]], [[Sword2]], [[Sword25]]


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
virtual Common::Error saveGameState(int slot, const Common::String &desc);
virtual Common::Error Engine::saveGameStream(Common::WriteStream *stream, bool isAutosave);
virtual bool canSaveGameStateCurrently();
virtual bool canSaveGameStateCurrently();


kSupportsSavingDuringRuntime feature flag
kSupportsSavingDuringRuntime feature flag
</syntaxhighlight>
</syntaxhighlight>
:'''Implemented by:''' [[AGI]], [[Avalanche]], [[Cine]], [[CGE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Pegasus]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Sword1]], [[TeenAgent]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]
:'''Not implemented by:''' [[AGOS]], [[Composer]], [[CruisE]], [[Fullpipe]], [[Gob]], [[Groovie]], [[Lastexpress]], [[Lure]], [[MADE]], [[Parallaction]], [[Queen]], [[Sword2]], [[Sword25]], [[Tinsel]]


==Misc==
==Misc==
Line 257: Line 251:
:'''Implemented by:''' [[SCUMM]]
:'''Implemented by:''' [[SCUMM]]


:'''Not implemented by:''' [[AGI]], [[AGOS]], [[Avalanche]], [[Cine]], [[CGE]], [[Composer]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Fullpipe]], [[Gob]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lastexpress]], [[Lure]], [[MADE]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[Sky]], [[Sword1]], [[Sword2]], [[Sword25]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]
:'''Not implemented by:''' [[AGI]], [[AGOS]], [[Avalanche]], [[Cine]], [[CGE]], [[Composer]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Gob]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lastexpress]], [[Lure]], [[MADE]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[NGI]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[Sky]], [[Sword1]], [[Sword2]], [[Sword25]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Tony]], [[Toon]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 263: Line 257:
</syntaxhighlight>
</syntaxhighlight>


:'''Implemented by:''' [[AGI]], [[AGOS]], [[Avalanche]], [[Cine]], [[CGE]], [[Composer]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Fullpipe]], [[Gob]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lastexpress]], [[Lure]], [[MADE]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Sword1]], [[Sword2]], [[Sword25]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Toon]], [[Tony]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]
:'''Implemented by:''' [[AGI]], [[AGOS]], [[Avalanche]], [[Cine]], [[CGE]], [[Composer]], [[CruisE]], [[Draci]], [[Drascula]], [[Dreamweb]], [[Gob]], [[Groovie]], [[Hopkins]], [[Hugo]], [[Kyra]], [[Lastexpress]], [[Lure]], [[MADE]], [[Mohawk]], [[Mortevielle]], [[Neverhood]], [[NGI]], [[Parallaction]], [[Pegasus]], [[Queen]], [[SAGA]], [[SCI]], [[SCUMM]], [[Sky]], [[Sword1]], [[Sword2]], [[Sword25]], [[TeenAgent]], [[Tinsel]], [[Toltecs]], [[Toon]], [[Tony]], [[Touche]], [[TsAGE]], [[Tucker]], [[Wintermute]], [[ZVision]]


:'''Not implemented by:'''
:'''Not implemented by:'''
736

edits

Navigation menu