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