ScummVM API documentation
game_state.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef AGS_ENGINE_AC_GAME_STATE_H
23 #define AGS_ENGINE_AC_GAME_STATE_H
24 
25 #include "common/std/memory.h"
26 #include "common/std/unordered_set.h"
27 #include "common/std/vector.h"
28 #include "ags/shared/ac/character_info.h"
29 #include "ags/shared/ac/keycode.h"
30 #include "ags/engine/ac/runtime_defines.h"
31 #include "ags/engine/ac/speech.h"
32 #include "ags/engine/ac/timer.h"
33 #include "ags/shared/game/room_struct.h"
34 #include "ags/engine/game/viewport.h"
35 #include "ags/engine/gfx/graphics_driver.h"
36 #include "ags/engine/media/audio/queued_audio_item.h"
37 #include "ags/shared/util/geometry.h"
38 #include "ags/shared/util/string_types.h"
39 #include "ags/shared/util/string.h"
40 
41 namespace AGS3 {
42 
43 // Forward declaration
44 namespace AGS {
45 namespace Shared {
46 class Bitmap;
47 class Stream;
48 typedef std::shared_ptr<Bitmap> PBitmap;
49 } // namespace Shared
50 
51 namespace Engine {
52 struct RestoredData;
53 } // namespace Engine
54 } // namespace AGS
55 
56 using namespace AGS; // FIXME later
57 struct ScriptViewport;
58 struct ScriptCamera;
59 struct ScriptOverlay;
60 
61 #define MAX_GAME_STATE_NAME_LENGTH 100
62 #define GAME_STATE_RESERVED_INTS 5
63 #define LEGACY_GAMESTATE_GAMENAMELENGTH 100
64 // This is a length limit for serialized field,
65 // not actual api input argument
66 #define PLAYMP3FILE_MAX_FILENAME_LEN 50
67 
68 // Savegame data format
69 enum GameStateSvgVersion {
70  kGSSvgVersion_OldFormat = -1, // TODO: remove after old save support is dropped
71  kGSSvgVersion_Initial = 0,
72  kGSSvgVersion_350 = 1,
73  kGSSvgVersion_350_9 = 2,
74  kGSSvgVersion_350_10 = 3,
75  kGSSvgVersion_361_14 = 4,
76 };
77 
78 
79 // Runtime game state
80 struct GameState {
81  // WARNING: following is a part of the script and plugin API
82  // (until further notice)
83  int score = 0; // player's current score
84  int usedmode = 0; // set by ProcessClick to last cursor mode used
85  int disabled_user_interface = 0; // >0 while in cutscene/etc
86  int gscript_timer = 0; // obsolete
87  int debug_mode = 0; // whether we're in debug mode
88  int32_t globalvars[MAXGLOBALVARS]{}; // obsolete
89  int messagetime = 0; // time left for auto-remove messages
90  int usedinv = 0; // inventory item last used
91  // Following inv_* variables are legacy variables controlling
92  // the single player's inventory (used prior to supporting custom InvWindow controls).
93  int inv_top = 0; // topmost index of displayed player's inventory
94  int inv_numdisp = 0; // number of player's items displayed at once
95  int inv_numorder = 0; // total number of player's items
96  int inv_numinline = 0; // number of items displayed on a single inventory row
97  int text_speed = 0; // how quickly text is removed
98  int sierra_inv_color = 0; // background used to paint defualt inv window
99  int talkanim_speed = 0; // animation speed of talking anims
100  int inv_item_wid = 0;
101  int inv_item_hit = 0; // set by SetInvDimensions
102  int speech_text_shadow = 0; // colour of outline fonts (default black)
103  int swap_portrait_side = 0; // sierra-style speech swap sides
104  int speech_textwindow_gui = 0; // textwindow used for sierra-style speech
105  int follow_change_room_timer = 0; // delay before moving following characters into new room
106  int totalscore = 0; // maximum possible score
107  int skip_display = 0; // how the user can skip normal Display windows
108  int no_multiloop_repeat = 0; // for backwards compatibility
109  int roomscript_finished = 0; // on_call finished in room
110  int used_inv_on = 0; // inv item they clicked on
111  int no_textbg_when_voice = 0; // no textwindow bgrnd when voice speech is used
112  int max_dialogoption_width = 0; // max width of dialog options text window
113  int no_hicolor_fadein = 0; // fade out but instant in for hi-color
114  int bgspeech_game_speed = 0; // is background speech relative to game speed
115  int bgspeech_stay_on_display = 0; // whether to remove bg speech when DisplaySpeech is used
116  int unfactor_speech_from_textlength = 0; // remove "&10" when calculating time for text to stay
117  int mp3_loop_before_end = 0; // (UNUSED!) loop this time before end of track (ms)
118  int speech_music_drop = 0; // how much to drop music volume by when speech is played
119  int in_cutscene = 0; // we are between a StartCutscene and EndCutscene
120  int fast_forward = 0; // player has elected to skip cutscene
121  int room_width = 0; // width of current room
122  int room_height = 0; // height of current room
123  // ** end of the part exposed to plugin API (script API continues)
124 
125  int game_speed_modifier = 0;
126  int score_sound = 0;
127  int takeover_data = 0; // value passed to RunAGSGame in previous game
128  int replay_hotkey_unused = 0; // (UNUSED!) StartRecording: not supported
129  int dialog_options_x = 0;
130  int dialog_options_y = 0;
131  int narrator_speech = 0;
132  int ambient_sounds_persist = 0;
133  int lipsync_speed = 0;
134  int close_mouth_speech_time = 0; // stop speech animation at (messagetime - close_mouth_speech_time)
135  // (this is designed to work in text-only mode)
136  int disable_antialiasing = 0;
137  int text_speed_modifier = 0;
138  HorAlignment text_align = kHAlignNone;
139  int speech_bubble_width = 0;
140  int min_dialogoption_width = 0;
141  int disable_dialog_parser = 0;
142  int anim_background_speed = 0; // the setting for this room
143  int top_bar_backcolor = 0;
144  int top_bar_textcolor = 0;
145  int top_bar_bordercolor = 0;
146  int top_bar_borderwidth = 0;
147  int top_bar_ypos = 0;
148  int screenshot_width = 0;
149  int screenshot_height = 0;
150  int top_bar_font = 0;
151  HorAlignment speech_text_align = kHAlignNone;
152  int auto_use_walkto_points = 0;
153  int inventory_greys_out = 0;
154  int skip_speech_specific_key = 0;
155  int abort_key = 0;
156  int fade_to_red = 0;
157  int fade_to_green = 0;
158  int fade_to_blue = 0;
159  int show_single_dialog_option = 0;
160  int keep_screen_during_instant_transition = 0;
161  int read_dialog_option_colour = 0;
162  int stop_dialog_at_end = 0;
163  int speech_portrait_placement = 0; // speech portrait placement mode (automatic/custom)
164  int speech_portrait_x = 0; // a speech portrait x offset from corresponding screen side
165  int speech_portrait_y = 0; // a speech portrait y offset
166  int speech_display_post_time_ms = 0; // keep speech text/portrait on screen after text/voice has finished playing = 0;
167  // no speech animation is supposed to be played at this time
168  int dialog_options_highlight_color = 0; // The colour used for highlighted (hovered over) text in dialog options
169  int32_t reserved[GAME_STATE_RESERVED_INTS]{}; // make sure if a future version adds a var, it doesn't mess anything up
170  // ** end of the part exposed to script API
171  //
172 
173  long randseed = 0; // random seed
174  int player_on_region = 0; // player's current region
175  int screen_is_faded_out = 0; // the screen is currently black
176  int check_interaction_only = 0;
177  int bg_frame = 0, bg_anim_delay = 0; // for animating backgrounds
178  int music_vol_was = 0; // before the volume drop
179  short wait_counter = 0;
180  int8 wait_skipped_by = 0; // tells how last blocking wait was skipped [not serialized]
181  int wait_skipped_by_data = 0; // extended data telling how last blocking wait was skipped [not serialized]
182  short mboundx1 = 0;
183  short mboundx2 = 0;
184  short mboundy1 = 0;
185  short mboundy2 = 0;
186  int fade_effect = 0;
187  int bg_frame_locked = 0;
188  int32_t globalscriptvars[MAXGSVALUES]{};
189  int cur_music_number = 0;
190  int music_repeat = 0;
191  int music_master_volume = 0;
192  int digital_master_volume = 0;
193  char walkable_areas_on[MAX_WALK_AREAS]{};
194  short screen_flipped = 0;
195  int entered_at_x = 0;
196  int entered_at_y = 0;
197  int entered_edge = 0;
198  bool voice_avail; // whether voice-over is available
199  SpeechMode speech_mode; // speech mode (text, voice, or both)
200  int speech_skip_style = 0;
201  int32_t script_timers[MAX_TIMERS]{};
202  int sound_volume = 0;
203  int speech_volume = 0;
204  int normal_font = 0;
205  int speech_font = 0;
206  int8 key_skip_wait = 0;
207  int swap_portrait_lastchar = 0;
208  int swap_portrait_lastlastchar = 0;
209  bool separate_music_lib = false;
210  int in_conversation = 0;
211  int screen_tint = 0;
212  int num_parsed_words = 0;
213  short parsed_words[MAX_PARSED_WORDS]{};
214  char bad_parsed_word[100]{};
215  int raw_color = 0;
216  int32_t raw_modified[MAX_ROOM_BGFRAMES]{};
217  Shared::PBitmap raw_drawing_surface = 0;
218  short filenumbers[MAXSAVEGAMES]{};
219  int room_changes = 0;
220  int mouse_cursor_hidden = 0;
221  int silent_midi = 0;
222  int silent_midi_channel = 0;
223  int current_music_repeating = 0; // remember what the loop flag was when this music started
224  unsigned long shakesc_delay = 0; // unsigned long to match _G(loopcounter)
225  int shakesc_amount = 0;
226  int shakesc_length = 0;
227  int rtint_red = 0;
228  int rtint_green = 0;
229  int rtint_blue = 0;
230  int rtint_level = 0;
231  int rtint_light = 0;
232  bool rtint_enabled = false;
233  int end_cutscene_music = 0;
234  int skip_until_char_stops = 0;
235  int get_loc_name_last_time = 0;
236  int get_loc_name_save_cursor = 0;
237  int restore_cursor_mode_to = 0;
238  int restore_cursor_image_to = 0;
239  short music_queue_size = 0;
240  short music_queue[MAX_QUEUED_MUSIC]{};
241  short new_music_queue_size = 0;
242  short crossfading_out_channel = 0;
243  short crossfade_step = 0;
244  short crossfade_out_volume_per_step = 0;
245  short crossfade_initial_volume_out = 0;
246  short crossfading_in_channel = 0;
247  short crossfade_in_volume_per_step = 0;
248  short crossfade_final_volume_in = 0;
249  QueuedAudioItem new_music_queue[MAX_QUEUED_MUSIC]{};
250  char takeover_from[50]{};
251  // Currently played external file; this is only for reference
252  AGS::Shared::String playmp3file_name;
253  char globalstrings[MAXGLOBALSTRINGS][MAX_MAXSTRLEN]{};
254  char lastParserEntry[MAX_MAXSTRLEN]{};
255  AGS::Shared::String game_name;
256  int ground_level_areas_disabled = 0;
257  int next_screen_transition = 0;
258  int gamma_adjustment = 0;
259  short temporarily_turned_off_character = 0; // Hide Player Charactr ticked
260  short inv_backwards_compatibility = 0; // tells to use legacy inv_* variables
261  std::vector<int> gui_draw_order; // used only for hit detection now
263  int text_min_display_time_ms = 0;
264  int ignore_user_input_after_text_timeout_ms = 0;
265  int32_t default_audio_type_volumes[MAX_AUDIO_TYPES]{};
266 
267  // Dynamic custom property values for characters and items
269  AGS::Shared::StringIMap invProps[MAX_INV];
270 
271  // Dynamic speech state
272  //
273  // Tells whether there is a voice-over played during current speech
274  bool speech_has_voice = false;
275  // Tells whether the voice was played in blocking mode;
276  // atm blocking speech handles itself, and we only need to finalize
277  // non-blocking voice speech during game update; speech refactor would be
278  // required to get rid of this rule.
279  bool speech_voice_blocking = false;
280  // Tells whether character speech stays on screen not animated for additional time
281  bool speech_in_post_state = false;
282 
283  // Special overlays
284  //
285  // Total number of existing overlays, only for the reference
286  int overlay_count = 0;
287  // Incrementing index of creation, assigned to overlays.
288  // Currently is used when resolving sorting conflicts with equal z-order.
289  // TODO: this method theoretically can overflow, but was added still as a quick fix;
290  // investigate better solutions later.
291  int overlay_creation_id = 0;
292  // Is there a QFG4-style dialog overlay on screen (contains overlay ID)
293  int complete_overlay_on = 0;
294  // Is there a blocking text overlay on screen (contains overlay ID)
295  int text_overlay_on = 0;
296  // Script overlay handles, because we must return same script objects
297  // whenever user script queries for them.
298  // Blocking speech overlay managed handle
299  int speech_text_schandle = 0;
300  // Speech portrait overlay managed handle
301  int speech_face_schandle = 0;
302 
303  // y offset of the shaking screen
304  int shake_screen_yoff = 0;
305 
306 
307  GameState();
308 
309  //
310  // Viewport and camera control.
311  // Viewports are positioned in game screen coordinates, related to the "game size",
312  // while cameras are positioned in room coordinates.
313  //
314  // Returns main (game's) viewport position on screen, this is the overall game view
315  const Rect &GetMainViewport() const;
316  // Returns UI viewport position on screen, within the main viewport
317  const Rect &GetUIViewport() const;
318  // Returns SpriteTransform corresponding to the global screen offsets
319  AGS::Engine::SpriteTransform GetGlobalTransform(bool full_frame_rend) const;
320  // Tells if the room viewport should be adjusted automatically each time a new room is loaded
321  bool IsAutoRoomViewport() const;
322  // Returns Room viewport object by it's main index
323  PViewport GetRoomViewport(int index) const;
324  // Returns Room viewport object by index in z-order
325  const std::vector<PViewport> &GetRoomViewportsZOrdered() const;
326  // Finds room viewport at the given screen coordinates; returns nullptr if non found
327  PViewport GetRoomViewportAt(int x, int y) const;
328  // Returns Room viewport position in absolute coordinates (with main viewport offset);
329  // this is a helper function, meant for peculiar cases.
330  Rect GetRoomViewportAbs(int index) const;
331  // Sets if the room viewport should be adjusted automatically each time a new room is loaded
332  void SetAutoRoomViewport(bool on);
333  // Main viewport defines the location of all things drawn and interactable on the game screen.
334  // Other viewports are defined relative to the main viewports.
335  void SetMainViewport(const Rect &viewport);
336  // UI viewport is a formal dummy viewport for GUI and Overlays (like speech).
337  void SetUIViewport(const Rect &viewport);
338  // Applies all the pending changes to viewports and cameras;
339  // NOTE: this function may be slow, thus recommended to be called only once
340  // and during the main game update.
341  void UpdateViewports();
342  // Notifies game state that viewports need z-order resorting upon next update.
343  void InvalidateViewportZOrder();
344  // Returns room camera object chosen by index
345  PCamera GetRoomCamera(int index) const;
346  // Runs cameras behaviors
347  void UpdateRoomCameras();
348  // Converts room coordinates to the game screen coordinates through the room viewport
349  // This group of functions always tries to pass a point through the **primary** room viewport
350  // TODO: also support using arbitrary viewport (for multiple viewports).
351  Point RoomToScreen(int roomx, int roomy);
352  int RoomToScreenX(int roomx);
353  int RoomToScreenY(int roomy);
354  // Converts game screen coordinates to the room coordinates through the room viewport
355  // This pair of functions tries to find if there is any viewport at the given coords.
356  // If "clip_viewport" parameter is true, then not finding a viewport results in failure,
357  // if it is false, proceeds converting through the primary viewport.
358  // TODO: find out if possible to refactor and get rid of "variadic" variants;
359  // usually this depends on how the arguments are created (whether they are in "variadic" or true coords)
360  VpPoint ScreenToRoom(int scrx, int scry, bool clip_viewport = true);
361  VpPoint ScreenToRoomDivDown(int scrx, int scry); // native "variadic" coords variant
362 
363  // Makes sure primary viewport and camera are created and linked together
364  void CreatePrimaryViewportAndCamera();
365  // Creates new room viewport
366  PViewport CreateRoomViewport();
367  // Register camera in the managed system; optionally links to existing handle
368  ScriptViewport *RegisterRoomViewport(int index, int32_t handle = 0);
369  // Deletes existing room viewport
370  void DeleteRoomViewport(int index);
371  // Get number of room viewports
372  int GetRoomViewportCount() const;
373  // Creates new room camera
374  PCamera CreateRoomCamera();
375  // Register camera in the managed system; optionally links to existing handle
376  ScriptCamera *RegisterRoomCamera(int index, int32_t handle = 0);
377  // Deletes existing room camera
378  void DeleteRoomCamera(int index);
379  // Get number of room cameras
380  int GetRoomCameraCount() const;
381  // Gets script viewport reference; does NOT increment refcount
382  // because script interpreter does this when acquiring managed pointer.
383  ScriptViewport *GetScriptViewport(int index);
384  // Gets script camera reference; does NOT increment refcount
385  // because script interpreter does this when acquiring managed pointer.
386  ScriptCamera *GetScriptCamera(int index);
387 
388  //
389  // User input management
390  //
391  // Tells if game should ignore user input right now. Note that some of the parent states
392  // may not ignore it at the same time, such as cutscene state, which may still be skipped
393  // with a key press or a mouse button.
394  bool IsIgnoringInput() const;
395  // Sets ignore input state, for the given time; if there's one already, chooses max timeout
396  void SetIgnoreInput(int timeout_ms);
397  // Clears ignore input state
398  void ClearIgnoreInput();
399 
400  // Set how the last blocking wait was skipped
401  void SetWaitSkipResult(int how, int data = 0);
402  void SetWaitKeySkip(const KeyInput &kp) {
403  SetWaitSkipResult(SKIP_KEYPRESS, AGSKeyToScriptKey(kp.Key) | kp.Mod);
404  }
405  // Returns the information about how the latest blocking wait was skipped.
406  // The information is packed into int32 value like this:
407  // | 0xFF | 0xFF | 0xF | 0xFFF |
408  // | eInputType | eKeyMod | reserved | eKeyCode, MouseButton etc |
409  int GetWaitSkipResult() const;
410 
411  //
412  // Voice speech management
413  //
414  // Tells if there's a blocking voice speech playing right now
415  bool IsBlockingVoiceSpeech() const;
416  // Tells whether we have to finalize voice speech when stopping or reusing the channel
417  bool IsNonBlockingVoiceSpeech() const;
418  // Speech helpers
419  bool ShouldPlayVoiceSpeech() const;
420 
421  //
422  // Serialization
423  //
424  void ReadCustomProperties_v340(Shared::Stream *in, GameDataVersion data_ver);
425  void WriteCustomProperties_v340(Shared::Stream *out, GameDataVersion data_ver) const;
426  void ReadFromSavegame(Shared::Stream *in, GameDataVersion data_ver, GameStateSvgVersion svg_ver, AGS::Engine::RestoredData &r_data);
427  void WriteForSavegame(Shared::Stream *out) const;
428  // This is required for freeing only particular parts when restoring the game;
429  // FIXME: investigate and refactor to be able to simply reset whole object
430  void FreeProperties();
431  void FreeViewportsAndCameras();
432 
433 private:
434  VpPoint ScreenToRoomImpl(int scrx, int scry, int view_index, bool clip_viewport, bool convert_cam_to_data);
435  void UpdateRoomCamera(int index);
436 
437  // Defines if the room viewport should be adjusted to the room size automatically.
438  bool _isAutoRoomViewport = true;
439  // Main viewport defines the rectangle of the drawn and interactable area;
440  // in the most basic case it will be equal to the game size.
441  Rect _mainViewport;
442  // UI viewport defines the render and interaction rectangle of game's UI,
443  // within the main game viewport.
444  Rect _uiViewport;
445  // Room viewports define place on screen where the room camera's
446  // contents are drawn.
447  std::vector<PViewport> _roomViewports;
448  // Vector of viewports sorted in z-order.
449  std::vector<PViewport> _roomViewportsSorted;
450  // Cameras defines the position of a "looking eye" inside the room.
451  std::vector<PCamera> _roomCameras;
452  // We keep handles to the script refs to viewports and cameras, so that we
453  // could address them and invalidate as the actual object gets destroyed.
454  std::vector<int32_t> _scViewportHandles;
455  std::vector<int32_t> _scCameraHandles;
456 
457  // Tells that the main viewport's position has changed since last game update
458  bool _mainViewportHasChanged = false;
459  // Tells that room viewports need z-order resort
460  bool _roomViewportZOrderChanged = false;
461 
462  AGS_Clock::time_point _ignoreUserInputUntilTime = 0;
463 };
464 
465 // Converts legacy alignment type used in script API
466 HorAlignment ConvertLegacyScriptAlignment(LegacyScriptAlignment align);
467 // Reads legacy alignment type from the value set in script depending on the
468 // current Script API level. This is made to make it possible to change
469 // Alignment constants in the Script API and still support old version.
470 HorAlignment ReadScriptAlignment(int32_t align);
471 
472 
473 
474 } // namespace AGS3
475 
476 #endif
Definition: achievements_tables.h:27
Definition: graphics_driver.h:70
Definition: savegame_internal.h:78
Definition: geometry.h:87
Definition: queued_audio_item.h:37
Definition: script_viewport.h:30
Definition: utility.h:39
Definition: geometry.h:219
Definition: script_camera.h:30
Definition: string.h:62
Definition: game_state.h:80
Definition: unordered_set.h:43
Definition: keycode.h:281
Definition: ptr.h:159
Definition: stream.h:52
Definition: engine.h:144
Definition: ags.h:40