ScummVM API documentation
scene.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 DGDS_SCENE_H
23 #define DGDS_SCENE_H
24 
25 #include "common/stream.h"
26 #include "common/array.h"
27 #include "common/serializer.h"
28 
29 #include "dgds/dialog.h"
30 #include "dgds/dgds_rect.h"
31 #include "dgds/minigames/shell_game.h"
32 
33 namespace Dgds {
34 
35 class ResourceManager;
36 class Decompressor;
37 class DgdsFont;
38 
39 enum SceneCondition {
40  kSceneCondNone = 0,
41  kSceneCondLessThan = 1,
42  kSceneCondEqual = 2,
43  kSceneCondNegate = 4,
44  kSceneCondAbsVal = 8,
45  kSceneCondOr = 0x10,
46  kSceneCondNeedItemSceneNum = 0x20,
47  kSceneCondNeedItemQuality = 0x40,
48  kSceneCondSceneState = 0x80
49 };
50 
52 public:
53  SceneConditions(uint16 num, SceneCondition cond, uint16 val) : _num(num), _flags(cond), _val(val) {}
54  Common::String dump(const Common::String &indent) const;
55 
56  uint16 getNum() const { return _num; }
57  SceneCondition getCond() const { return _flags; }
58  uint16 getVal() const { return _val; }
59 
60 private:
61  uint16 _num;
62  SceneCondition _flags; /* eg, see usage in FUN_1f1a_2106 */
63  uint16 _val;
64 };
65 
66 class HotArea {
67 public:
68  DgdsRect _rect;
69  uint16 _num; //
70  uint16 _cursorNum;
71 
72  // Used in Willy Beamish
73  uint16 _otherCursorNum;
74  uint16 _objInteractionRectNum;
75 
76  Common::Array<SceneConditions> enableConditions;
77  Common::Array<SceneOp> onRClickOps;
78  Common::Array<SceneOp> onLDownOps;
79  Common::Array<SceneOp> onLClickOps;
80 
81  virtual ~HotArea() {}
82 
83  virtual Common::String dump(const Common::String &indent) const;
84 };
85 
86 class DynamicRect {
87 public:
88  DynamicRect() : _num(0) {};
89  uint16 _num;
90  DgdsRect _rect;
91 };
92 
93 enum SceneOpCode {
94  kSceneOpNone = 0,
95  kSceneOpChangeScene = 1, // args: scene num
96  kSceneOpNoop = 2, // args: none. Maybe should close dialogue?
97  kSceneOpGlobal = 3, // args: array of uints
98  kSceneOpSegmentStateOps = 4, // args: array of uint pairs [op seg, op seg], term with 0,0 that modify segment states
99  kSceneOpSetItemAttr = 5, // args: [item num, item param 0x28, item param 0x2c]. set item attrs?
100  kSceneOpSetDragItem = 6, // args: item num. give item?
101  kSceneOpOpenInventory = 7, // args: none.
102  kSceneOpShowDlg = 8, // args: dialogue number.
103  kSceneOpShowInvButton = 9, // args: none.
104  kSceneOpHideInvButton = 10, // args: none.
105  kSceneOpEnableTrigger = 11, // args: trigger num
106  kSceneOpChangeSceneToStored = 12, // args: none. Change scene to stored number
107  kSceneOpAddFlagToDragItem = 13, // args: none.
108  kSceneOpOpenInventoryZoom = 14, // args: none.
109  kSceneOpMoveItemsBetweenScenes = 15, // args: none.
110  kSceneOpShowClock = 16, // args: none. set clock script-visible.
111  kSceneOpHideClock = 17, // args: none. set clock script-hidden.
112  kSceneOpShowMouse = 18, // args: none.
113  kSceneOpHideMouse = 19, // args: none.
114  // Op 20 onward are common, but not in dragon
115 
116  kSceneOpLoadTalkDataAndSetFlags = 20, // args: tdsnum to load, headnum
117  kSceneOpDrawVisibleTalkHeads = 21, // args: none
118  kSceneOpLoadTalkData = 22, // args: tds num to load
119  kSceneOpLoadDDSData = 24, // args: dds num to load
120  kSceneOpFreeDDSData = 25, // args: dds num to free
121  kSceneOpFreeTalkData = 26, // args: tds num to free
122 
123  // Dragon-specific opcodes
124  kSceneOpPasscode = 100, // args: none.
125  kSceneOpMeanwhile = 101, // args: none. Clears screen and displays "meanwhile".
126  kSceneOpOpenGameOverMenu = 102, // args: none.
127  kSceneOpTiredDialog = 103, // args: none. Something about "boy am I tired"?
128  kSceneOpArcadeTick = 104, // args: none. Called in arcade post-tick.
129  kSceneOpDrawDragonCountdown1 = 105, // args: none. Draw special countdown number at 141, 56
130  kSceneOpDrawDragonCountdown2 = 106, // args: none. Draw some number at 250, 42
131  kSceneOpOpenPlaySkipIntroMenu = 107, // args: none. DRAGON: Show menu 50, the "Play Introduction" / "Skip Introduction" menu.
132  kSceneOpOpenBetterSaveGameMenu = 108, // args: none. DRAGON: Show menu 46, the "Before arcade maybe you better save your game" menu.
133 
134  // China-specific opcodes
135  kSceneOpChinaTankInit = 100,
136  kSceneOpChinaTankEnd = 101,
137  kSceneOpChinaTankTick = 102,
138  kSceneOpChinaSetLanding = 103,
139  kSceneOpChinaScrollIntro = 104,
140  kSceneOpChinaScrollLeft = 105,
141  kSceneOpChinaScrollRight = 107,
142  kSceneOpShellGameInit = 108,
143  kSceneOpShellGameEnd = 109,
144  kSceneOpShellGameTick = 110,
145  kSceneOpChinaTrainInit = 111,
146  kSceneOpChinaTrainEnd = 112,
147  kSceneOpChinaTrainTick = 113,
148  kSceneOpChinaOpenGameOverMenu = 114, // args: none.
149  kSceneOpChinaOpenSkipCreditsMenu = 115, // args: none.
150  kSceneOpChinaOnIntroTick = 116, // args: none.
151  kSceneOpChinaOnIntroInit = 117, // args: none.
152  kSceneOpChinaOnIntroEnd = 118, // args: none.
153 
154  // Beamish-specific opcodes
155  kSceneOpOpenBeamishGameOverMenu = 100,
156  kSceneOpOpenBeamishOpenSkipCreditsMenu = 101,
157 
158  kSceneOpMaxCode = 255, // for checking file load
159 
160  kSceneOpHasConditionalOpsFlag = 0x8000,
161 };
162 
163 class SceneOp {
164 public:
165  Common::Array<SceneConditions> _conditionList;
166  Common::Array<uint16> _args;
167  SceneOpCode _opCode;
168 
169  Common::String dump(const Common::String &indent) const;
170 };
171 
173 public:
174  uint _opCode;
175  Common::Array<SceneConditions> _conditionList;
176  Common::Array<SceneOp> _opList;
177 
178  Common::String dump(const Common::String &indent) const;
179 };
180 
181 class GameItem : public HotArea {
182 public:
183  Common::Array<SceneOp> onDragFinishedOps;
184  Common::Array<SceneOp> onBothButtonsOps;
185  uint16 _altCursor;
186  uint16 _iconNum;
187 
188  // mutable values
189  uint16 _inSceneNum;
190  uint16 _flags;
191  uint16 _quality;
192 
193  Common::String dump(const Common::String &indent) const override;
194 };
195 
196 class MouseCursor {
197 public:
198  MouseCursor(uint16 hotX, uint16 hotY) : _hot(hotX, hotY) {}
199 
200  Common::String dump(const Common::String &indent) const;
201 
202  const Common::Point getHot() const { return _hot; }
203 
204 private:
205  Common::Point _hot;
206 };
207 
208 // Interactions between two objects when one is dropped on the other
210 public:
211  ObjectInteraction(uint16 dropped, uint16 target) : _droppedItemNum(dropped), _targetItemNum(target) {}
212 
213  Common::Array<SceneOp> opList;
214 
215  bool matches(uint16 droppedItemNum, uint16 targetItemNum) const {
216  return (_droppedItemNum == 0xFFFF || _droppedItemNum == droppedItemNum)
217  && _targetItemNum == targetItemNum;
218  }
219 
220  Common::String dump(const Common::String &indent) const;
221 
222 private:
223  uint16 _droppedItemNum;
224  uint16 _targetItemNum;
225 
226 };
227 
229 public:
230  SceneTrigger(uint16 num) : _num(num), _enabled(false), _timesToCheckBeforeRunning(0) {}
231  Common::String dump(const Common::String &indent) const;
232 
233  Common::Array<SceneConditions> conditionList;
234  Common::Array<SceneOp> sceneOpList;
235 
236  uint16 _timesToCheckBeforeRunning; // Only used in Beamish.
237  bool _enabled;
238  uint16 getNum() const { return _num; }
239 
240 private:
241  uint16 _num;
242 };
243 
244 /* A global value that only applies on a per-SDS-scene,
245  but stays with the GDS data as it sticks around during
246  the game */
248 public:
249  PerSceneGlobal(uint16 num, uint16 scene) : _num(num), _sceneNo(scene), _val(0) {}
250 
251  Common::String dump(const Common::String &indent) const;
252  bool matches(uint16 num, uint16 scene) const { return num == _num && (_sceneNo == 0 || _sceneNo == scene); }
253  bool numMatches(uint16 num) const { return num == _num; }
254 
255  int16 _val;
256 
257 private:
258  // Immutable, read from the data file
259  uint16 _num;
260  uint16 _sceneNo;
261 };
262 
263 
265 public:
266  TalkDataHeadFrame() : _xoff(0), _yoff(0), _frameNo(0), _flipFlags(0) {}
267  Common::String dump(const Common::String &indent) const;
268 
269  uint16 _frameNo;
270  int16 _xoff;
271  int16 _yoff;
272  uint16 _flipFlags;
273 };
274 
275 enum HeadFlags {
276  kHeadFlagNone = 0,
277  kHeadFlag1 = 1,
278  kHeadFlag2 = 2,
279  kHeadFlag4 = 4,
280  kHeadFlag8 = 8,
281  kHeadFlag10 = 0x10,
282  kHeadFlagVisible = 0x20,
283  kHeadFlag40 = 0x40,
284  kHeadFlag80 = 0x80,
285 };
286 
288 public:
289  TalkDataHead() : _num(0), _drawType(0), _drawCol(0), _flags(kHeadFlagNone) {}
290  Common::String dump(const Common::String &indent) const;
291 
292  uint16 _num;
293  uint16 _drawType;
294  uint16 _drawCol;
295  DgdsRect _rect;
297  Common::String _bmpFile;
298  HeadFlags _flags;
300 };
301 
302 class TalkData {
303 public:
304  TalkData() : _num(0), _val(0) {}
305  Common::String dump(const Common::String &indent) const;
306 
307  uint16 _num;
310  uint16 _val;
311  Common::String _bmpFile;
312 };
313 
314 
319 class Scene {
320 public:
321  Scene();
322  virtual ~Scene() {};
323 
324  virtual bool parse(Common::SeekableReadStream *s) = 0;
325 
326  bool isVersionOver(const char *version) const;
327  bool isVersionUnder(const char *version) const;
328 
329  uint32 getMagic() const { return _magic; }
330  const Common::String &getVersion() const { return _version; }
331 
332  bool runPreTickOps() { return runOps(_preTickOps); }
333  bool runPostTickOps() { return runOps(_postTickOps); }
334 
335  static bool runOps(const Common::Array<SceneOp> ops, int16 addMinutes = 0);
336 
337  virtual Common::Error syncState(Common::Serializer &s) = 0;
338 
339 protected:
340  bool readConditionList(Common::SeekableReadStream *s, Common::Array<SceneConditions> &list) const;
341  bool readHotArea(Common::SeekableReadStream *s, HotArea &dst) const;
342  bool readHotAreaList(Common::SeekableReadStream *s, Common::List<HotArea> &list) const;
343  bool readGameItemList(Common::SeekableReadStream *s, Common::Array<GameItem> &list) const;
344  bool readMouseHotspotList(Common::SeekableReadStream *s, Common::Array<MouseCursor> &list) const;
345  bool readObjInteractionList(Common::SeekableReadStream *s, Common::Array<ObjectInteraction> &list) const;
346  bool readOpList(Common::SeekableReadStream *s, Common::Array<SceneOp> &list) const;
347  bool readDialogList(Common::SeekableReadStream *s, Common::Array<Dialog> &list, int16 filenum = 0) const;
348  bool readTriggerList(Common::SeekableReadStream *s, Common::Array<SceneTrigger> &list) const;
349  bool readDialogActionList(Common::SeekableReadStream *s, Common::Array<DialogAction> &list) const;
350  bool readConditionalSceneOpList(Common::SeekableReadStream *s, Common::Array<ConditionalSceneOp> &list) const;
351 
352  static void segmentStateOps(const Common::Array<uint16> &args);
353  static void setItemAttrOp(const Common::Array<uint16> &args);
354  static void setDragItemOp(const Common::Array<uint16> &args);
355 
356  // These are all static as they are potentially run over scene changes.
357  static bool checkConditions(const Common::Array<SceneConditions> &cond);
358  static bool runSceneOp(const SceneOp &op);
359  static bool runDragonOp(const SceneOp &op);
360  static bool runChinaOp(const SceneOp &op);
361  static bool runBeamishOp(const SceneOp &op);
362 
363  uint32 _magic;
364  Common::String _version;
365 
366  Common::Array<SceneOp> _preTickOps;
367  Common::Array<SceneOp> _postTickOps;
368  Common::Array<ConditionalSceneOp> _conditionalOps; // Beamish only
369 };
370 
371 
372 class GDSScene : public Scene {
373 public:
374  GDSScene();
375 
376  bool load(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor);
377  bool loadRestart(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor);
378  bool parse(Common::SeekableReadStream *s) override;
379  bool parseInf(Common::SeekableReadStream *s);
380  const Common::String &getIconFile() const { return _iconFile; }
381  bool readPerSceneGlobals(Common::SeekableReadStream *s);
382 
383  Common::String dump(const Common::String &indent) const;
384 
385  void runStartGameOps() { runOps(_startGameOps); }
386  void runQuitGameOps() { runOps(_quitGameOps); }
387  void runChangeSceneOps() { runOps(_onChangeSceneOps); }
388  void globalOps(const Common::Array<uint16> &args);
389  int16 getGlobal(uint16 num);
390  int16 setGlobal(uint16 num, int16 val);
391 
392  const Common::Array<MouseCursor> &getCursorList() const { return _cursorList; }
393  void drawItems(Graphics::ManagedSurface &surf);
394  Common::Array<GameItem> &getGameItems() { return _gameItems; }
395  int countItemsInScene2() const;
396 
397  const Common::Array<ObjectInteraction> &getObjInteractions1() { return _objInteractions1; }
398  const Common::Array<ObjectInteraction> &getObjInteractions2() { return _objInteractions2; }
399 
400  Common::Error syncState(Common::Serializer &s) override;
401  void initIconSizes();
402  GameItem *getActiveItem();
403 
404  uint16 getDefaultMouseCursor() const { return _defaultMouseCursor; }
405  uint16 getInvIconNum() const { return _invIconNum; }
406  uint16 getInvIconMouseCursor() const { return _invIconMouseCursor; }
407 
408 private:
409  Common::String _iconFile;
410  Common::Array<GameItem> _gameItems;
411  Common::Array<SceneOp> _startGameOps;
412  Common::Array<SceneOp> _quitGameOps;
413  Common::Array<SceneOp> _onChangeSceneOps;
414  Common::Array<MouseCursor> _cursorList;
415  Common::Array<PerSceneGlobal> _perSceneGlobals;
416  Common::Array<ObjectInteraction> _objInteractions2;
417  Common::Array<ObjectInteraction> _objInteractions1;
418 
419  // Additional fields that appear in Willy Beamish (unused in others)
420  uint16 _defaultMouseCursor;
421  uint16 _field3a;
422  uint16 _invIconNum;
423  uint16 _invIconMouseCursor;
424  uint16 _field40;
425 };
426 
427 class SDSScene : public Scene {
428 public:
429  SDSScene();
430 
431  bool load(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor);
432  bool parse(Common::SeekableReadStream *s) override;
433  void unload();
434 
435  const Common::String &getAdsFile() const { return _adsFile; }
436  void runEnterSceneOps() { runOps(_enterSceneOps); }
437  void runLeaveSceneOps() { runOps(_leaveSceneOps); }
438  void checkTriggers();
439 
440  int getNum() const { return _num; }
441  Common::String dump(const Common::String &indent) const;
442 
443  bool checkDialogActive();
444  void drawActiveDialogBgs(Graphics::ManagedSurface *dst);
445  bool drawAndUpdateDialogs(Graphics::ManagedSurface *dst);
446  bool checkForClearedDialogs();
447 
448  void mouseMoved(const Common::Point &pt);
449  void mouseLDown(const Common::Point &pt);
450  void mouseLUp(const Common::Point &pt);
451  void mouseRDown(const Common::Point &pt);
452  void mouseRUp(const Common::Point &pt);
453 
454  void addInvButtonToHotAreaList();
455  void removeInvButtonFromHotAreaList();
456 
457  const Common::List<HotArea> &getHotAreas() const { return _hotAreaList; }
458 
459  const GameItem *getDragItem() const { return _dragItem; }
460  GameItem *getDragItem() { return _dragItem; }
461  void setDragItem(GameItem *item) { _dragItem = item; }
462 
463  const Common::Array<ObjectInteraction> &getObjInteractions1() { return _objInteractions1; }
464  const Common::Array<ObjectInteraction> &getObjInteractions2() { return _objInteractions2; }
465 
466  bool hasVisibleDialog();
467  bool hasVisibleOrOpeningDialog() const;
468 
469  Common::Error syncState(Common::Serializer &s) override;
470 
471  void onDragFinish(const Common::Point &pt);
472  void enableTrigger(uint16 num, bool enable = true);
473 
474  Dialog *loadDialogData(uint16 num);
475  void freeDialogData(uint16 num);
476  bool loadTalkData(uint16 num);
477  void freeTalkData(uint16 num);
478  void updateVisibleTalkers();
479  void loadTalkDataAndSetFlags(uint16 talknum, uint16 headnum);
480  void drawVisibleHeads(Graphics::ManagedSurface *dst);
481  bool hasVisibleHead() const;
482 
483  // dragon-specific scene ops
484  void addAndShowTiredDialog();
485 
486  void prevChoice();
487  void nextChoice();
488  void activateChoice();
489  bool isTriggerEnabled(uint16 num);
490  bool isLButtonDown() const { return _lbuttonDown; }
491  bool isRButtonDown() const { return _rbuttonDown; }
492  void showDialog(uint16 fileNum, uint16 dlgNum);
493  const Common::Array<ConditionalSceneOp> &getConditionalOps() { return _conditionalOps; }
494  void updateHotAreasFromDynamicRects();
495  void setDynamicSceneRect(int16 num, int16 x, int16 y, int16 width, int16 height);
496  void setSceneNum(int16 num) { _num = num; }
497 
498 protected:
499  HotArea *findAreaUnderMouse(const Common::Point &pt);
500 
501 private:
502  Dialog *getVisibleDialog();
503  bool readTalkData(Common::SeekableReadStream *s, TalkData &dst);
504  void updateHead(TalkDataHead &head);
505  void drawHead(Graphics::ManagedSurface *dst, const TalkData &data, const TalkDataHead &head);
506  void drawHeadType1(Graphics::ManagedSurface *dst, const TalkDataHead &head, const Image &img);
507  void drawHeadType2(Graphics::ManagedSurface *dst, const TalkDataHead &head, const Image &img);
508  void drawHeadType3(Graphics::ManagedSurface *dst, const TalkDataHead &head, const Image &img);
509  void drawHeadType3Beamish(Graphics::ManagedSurface *dst, const TalkData &data, const TalkDataHead &head);
510 
511  int _num;
512  Common::Array<SceneOp> _enterSceneOps;
513  Common::Array<SceneOp> _leaveSceneOps;
514  //uint _field5_0x12;
515  uint _field6_0x14;
516  Common::String _adsFile;
517  //uint _field8_0x23;
518  Common::List<HotArea> _hotAreaList;
519  Common::Array<ObjectInteraction> _objInteractions1;
520  Common::Array<ObjectInteraction> _objInteractions2;
521  Common::Array<DynamicRect> _dynamicRects; // Only used in Willy Beamish
522  //uint _field12_0x2b;
523  //uint _field15_0x33;
524 
525  Common::Array<TalkData> _talkData;
526 
527  // From here on is mutable stuff that might need saving
528  Common::Array<Dialog> _dialogs;
529  Common::Array<SceneTrigger> _triggers;
530 
531  GameItem *_dragItem;
532  bool _shouldClearDlg;
533  bool _ignoreMouseUp;
534  bool _lbuttonDown;
535  bool _rbuttonDown;
536 
537  static bool _dlgWithFlagLo8IsClosing;
538  static DialogFlags _sceneDialogFlags;
539 };
540 
541 } // End of namespace Dgds
542 
543 #endif // DGDS_SCENE_H
Definition: managed_surface.h:51
Definition: scene.h:66
Definition: str.h:59
Definition: error.h:84
Definition: dialog.h:101
Definition: array.h:52
Definition: scene.h:196
Definition: ads.h:28
Definition: list.h:44
Definition: stream.h:745
Definition: serializer.h:79
Definition: scene.h:51
Definition: scene.h:319
Definition: scene.h:264
Definition: scene.h:302
Definition: scene.h:172
Definition: scene.h:247
Definition: dgds_rect.h:32
Definition: scene.h:86
Definition: scene.h:427
Definition: scene.h:287
Definition: rect.h:45
Definition: scene.h:228
Definition: scene.h:209
Definition: scene.h:181
Definition: ptr.h:159
Definition: scene.h:372
Definition: movie_decoder.h:32
Definition: scene.h:163
Definition: decompress.h:67
Definition: resource.h:49