ScummVM API documentation
conversation.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 NANCY_ACTION_CONVERSATION_H
23 #define NANCY_ACTION_CONVERSATION_H
24 
25 #include "engines/nancy/action/actionrecord.h"
26 #include "engines/nancy/video.h"
27 
28 namespace Nancy {
29 namespace Action {
30 
31 // The base class for conversations, with no video data. Contains the following:
32 // - a base sound for the NPC's speech and its caption (mandatory)
33 // - a list of possible player responses, also with sounds and captions (optional)
34 // Captions are displayed in the Textbox, and player responses are also selectable there.
35 // Captions are hypertext; meaning, they contain extra data related to the text (see misc/hypertext.h)
36 // A conversation will auto-advance to a next scene when no responses are available; the next scene
37 // can either be described within the Conversation data, or can be whatever's pushed onto the scene "stack".
38 // Also supports branching scenes depending on a condition, though that is only used in older games.
39 // Player responses can also be conditional; the original engine had special-purpose "infocheck"
40 // functions, two per character ID, which were used to evaluate those conditions. We replace that with
41 // the data bundled inside nancy.dat (see devtools/create_nancy).
43 public:
45  virtual ~ConversationSound();
46 
47  void init() override;
48  void readData(Common::SeekableReadStream &stream) override;
49  void execute() override;
50 
51  virtual bool isVideoDonePlaying() { return true; }
52 
53 protected:
55  byte type;
56  FlagDescription flag;
57  byte orFlag;
58 
59  void read(Common::SeekableReadStream &stream);
60  bool isSatisfied() const;
61  void set() const;
62  };
63 
65  Common::Array<ConversationFlag> conditionFlags;
66 
67  void read(Common::SeekableReadStream &stream);
68  bool isSatisfied() const;
69  };
70 
71  struct ResponseStruct {
72  enum AddRule { kAddIfNotFound, kRemoveAndAddToEnd, kRemove };
73 
74  ConversationFlags conditionFlags;
75  Common::String text;
76  Common::String soundName;
77  byte addRule = kAddIfNotFound;
78  SceneChangeDescription sceneChange;
79  FlagDescription flagDesc;
80 
81  bool isOnScreen = false;
82  };
83 
84  struct FlagsStruct {
85  ConversationFlags conditions;
86  ConversationFlag flagToSet;
87  };
88 
90  ConversationFlags conditions;
91  SceneChangeDescription sceneChange;
92  };
93 
94  static const byte kDefaultNextSceneEnabled = 1;
95  static const byte kDefaultNextSceneDisabled = 2;
96 
97  static const byte kPopNextScene = 1;
98  static const byte kNoPopNextScene = 2;
99 
100  Common::String getRecordTypeName() const override { return "ConversationSound"; }
101  bool isViewportRelative() const override { return true; }
102 
103  // Functions for reading captions are virtual to allow easier support for the terse Conversation variants
104  virtual void readCaptionText(Common::SeekableReadStream &stream);
105  virtual void readResponseText(Common::SeekableReadStream &stream, ResponseStruct &response);
106 
107  // Used in subclasses
108  void readTerseData(Common::SeekableReadStream &stream);
109  void readTerseCaptionText(Common::SeekableReadStream &stream);
110  void readTerseResponseText(Common::SeekableReadStream &stream, ResponseStruct &response);
111 
112  // Functions for handling the built-in dialogue responses found in the executable
113  void addConditionalDialogue();
114  void addGoodbye();
115 
116  Common::String _text;
117 
118  SoundDescription _sound;
119  SoundDescription _responseGenericSound;
120 
121  byte _conditionalResponseCharacterID;
122  byte _goodbyeResponseCharacterID;
123  byte _defaultNextScene = kDefaultNextSceneEnabled;
124  byte _popNextScene = kNoPopNextScene;
125  SceneChangeDescription _sceneChange;
126 
128  Common::Array<FlagsStruct> _flagsStructs;
129  Common::Array<SceneBranchStruct> _sceneBranchStructs;
130 
131  bool _hasDrawnTextbox;
132  int16 _pickedResponse;
133 
134  const byte _noResponse;
135 };
136 
137 // Conversation with an AVF video. Originally called PlayPrimaryVideoChan0
139 public:
140  void init() override;
141  void updateGraphics() override;
142  void onPause(bool pause) override;
143 
144  void readData(Common::SeekableReadStream &stream) override;
145 
146  bool isVideoDonePlaying() override;
147 
148 protected:
149  Common::String getRecordTypeName() const override;
150 
151  Common::String _videoName;
152  Common::Path _paletteName;
153  uint _videoFormat = kLargeVideoFormat;
154  uint16 _firstFrame = 0;
155  int16 _lastFrame = 0;
156  AVFDecoder _decoder;
157 };
158 
159 class ConversationCelLoader;
160 
161 // Conversation with separate cels for the body and head of the character.
162 // Cels are separate images bundled inside a .cal file
164  friend class ConversationCelLoader;
165 public:
166  ConversationCel() {}
167  virtual ~ConversationCel();
168 
169  void init() override;
170  void registerGraphics() override;
171  void updateGraphics() override;
172 
173  void readData(Common::SeekableReadStream &stream) override;
174 
175 protected:
176  Common::String getRecordTypeName() const override { return "ConversationCel"; }
177 
178  struct Cel {
180  Common::Rect src;
181  Common::Rect dest;
182  };
183 
184  class RenderedCel : public RenderObject {
185  friend class ConversationCel;
186  public:
187  RenderedCel() : RenderObject(9) {}
188  bool isViewportRelative() const override { return true; }
189  };
190 
191  static const byte kCelOverrideTreeRectsOff = 1;
192  static const byte kCelOverrideTreeRectsOn = 2;
193 
194  bool isVideoDonePlaying() override;
195  Cel &loadCel(const Common::Path &name, const Common::String &treeName);
196 
197  void readXSheet(Common::SeekableReadStream &stream, const Common::String &xsheetName);
198 
201 
202  uint16 _frameTime = 0;
203  uint _videoFormat = kLargeVideoFormat;
204  uint16 _firstFrame = 0;
205  uint16 _lastFrame = 0;
206 
207  Common::Array<byte> _drawingOrder;
208  Common::Array<byte> _overrideTreeRects;
209 
210  Common::Array<Common::Rect> _overrideRectSrcs;
211  Common::Array<Common::Rect> _overrideRectDests;
212 
213  uint _curFrame = 0;
214  uint32 _nextFrameTime = 0;
215 
216  Common::Array<RenderedCel> _celRObjects;
217 
220 };
221 
222 // A ConversationSound without embedded text; uses the CONVO chunk instead
224 protected:
225  Common::String getRecordTypeName() const override { return "ConversationSoundT"; }
226 
227  void readCaptionText(Common::SeekableReadStream &stream) override { readTerseCaptionText(stream); }
228  void readResponseText(Common::SeekableReadStream &stream, ResponseStruct &response) override { readTerseResponseText(stream, response); }
229 };
230 
231 // A ConversationCel without embedded text; uses the CONVO chunk instead
233 protected:
234  Common::String getRecordTypeName() const override { return "ConversationCelT"; }
235 
236  void readCaptionText(Common::SeekableReadStream &stream) override { readTerseCaptionText(stream); }
237  void readResponseText(Common::SeekableReadStream &stream, ResponseStruct &response) override { readTerseResponseText(stream, response); }
238 };
239 
240 // A ConversationSound with a much smaller data footprint
242 public:
243  void readData(Common::SeekableReadStream &stream) override;
244 
245 protected:
246  Common::String getRecordTypeName() const override { return "ConversationSoundTerse"; }
247 };
248 
249 // A ConversationCel with a much smaller data footprint
251 public:
252  void readData(Common::SeekableReadStream &stream) override;
253 
254 protected:
255  Common::String getRecordTypeName() const override { return "ConversationCelTerse"; }
256 };
257 
258 } // End of namespace Action
259 } // End of namespace Nancy
260 
261 #endif // NANCY_ACTION_CONVERSATION_H
Definition: managed_surface.h:51
Definition: str.h:59
Definition: conversation.h:178
Definition: commontypes.h:151
Definition: array.h:52
Definition: conversation.h:138
Definition: rect.h:144
Definition: path.h:52
Definition: stream.h:745
Definition: conversation.h:42
Definition: actionrecord.h:149
Definition: renderobject.h:36
Definition: conversation.h:241
Definition: hashmap.h:85
Definition: conversation.h:250
Definition: video.h:41
Definition: conversation.h:163
Definition: conversation.h:184
Definition: commontypes.h:254
Definition: conversation.h:223
Definition: conversation.h:232
Definition: commontypes.h:166
Definition: actionmanager.h:32