ScummVM API documentation
game.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 DRACI_GAME_H
23 #define DRACI_GAME_H
24 
25 #include "common/str.h"
26 #include "draci/script.h"
27 #include "draci/walking.h"
28 
29 namespace Common {
30 class Serializer;
31 }
32 
33 namespace Draci {
34 
35 class BArchive;
36 class DraciEngine;
37 
38 enum {
39  kDragonObject = 0
40 };
41 
42 enum {
43  kDialogueLines = 4
44 };
45 
46 enum {
47  kBlackPalette = -1
48 };
49 
50 enum {
51  kMouseEnableSwitching = -1,
52  kMouseDoNotSwitch = -2
53 };
54 
55 // Constants tuned such that with ScummVM's default talkspeed kStandardSpeed, the speed
56 // computed by equation (kBaseSpeechDuration + kSpeechTimeUnit * #characters) /
57 // talkspeed is equal to the original game.
58 enum SpeechConstants {
59  kBaseSpeechDuration = 12000,
60  kSpeechTimeUnit = 2640,
61  kStandardSpeed = 60
62 };
63 
64 enum FadeConstants {
65  // One fading phase called from the game scripts is 50ms.
66  kFadingTimeUnit = 50,
67  // Fading in/out when entering/leaving a location takes 15 iterations of (at least) 7ms each.
68  kBlackFadingIterations = 15,
69  kBlackFadingTimeUnit = 7
70 };
71 
72 enum AnimationConstants {
73  kTimeUnit = 20
74 };
75 
78  kInventoryItemWidth = 25,
79  kInventoryItemHeight = 25,
80  kInventoryColumns = 7,
81  kInventoryLines = 5,
82  kInventoryX = 70,
83  kInventoryY = 30,
84  kInventorySlots = kInventoryLines * kInventoryColumns,
85  kStatusChangeTimeout = 500
86 };
87 
88 static const int kCreditsMapID = 46;
89 
90 class GameObject {
91 public:
92  int _absNum;
93  uint _init, _look, _use, _canUse;
94  bool _imInit, _imLook, _imUse;
95  int _walkDir;
96  byte _z;
97  uint _lookX, _lookY, _useX, _useY;
98  SightDirection _lookDir, _useDir;
99  GPL2Program _program;
100  Common::String _title;
101  int _location;
102  bool _visible;
103 
105  int _playingAnim;
106 
107  int getAnim(int animID) const;
108  int addAnim(Animation *anim);
109  int playingAnim() const { return _playingAnim; }
110  void playAnim(int i);
111  void stopAnim();
112  void deleteAnims();
113  void deleteAnimsFrom(int index);
114  void load(uint objNum, BArchive *archive);
115 };
116 
117 struct GameInfo {
118  int _startRoom;
119  int _mapRoom;
120  uint _numObjects;
121  uint _numItems;
122  byte _numVariables;
123  byte _numPersons;
124  byte _numDialogues;
125  uint _maxItemWidth, _maxItemHeight;
126  uint _musicLength;
127  uint _crc[4];
128  uint _numDialogueBlocks;
129 };
130 
131 class GameItem {
132 public:
133  int _absNum;
134  uint _init, _look, _use, _canUse;
135  bool _imInit, _imLook, _imUse;
136  GPL2Program _program;
137  Common::String _title;
138 
139  Animation *_anim;
140 
141  void load(int itemID, BArchive *archive);
142 };
143 
144 struct Person {
145  uint _x, _y;
146  byte _fontColor;
147 };
148 
149 struct Dialogue {
150  int _canLen;
151  byte *_canBlock;
152  Common::String _title;
153  GPL2Program _program;
154 };
155 
156 class Room {
157 public:
158  int _roomNum;
159  byte _music;
160  int _mapID;
161  int _palette;
162  int _numOverlays;
163  int _init, _look, _use, _canUse;
164  bool _imInit, _imLook, _imUse;
165  bool _mouseOn, _heroOn;
166  double _pers0, _persStep;
167  int _escRoom;
168  byte _numGates;
169  Common::Array<int> _gates;
170  GPL2Program _program;
171 
172  void load(int roomNum, BArchive *archive);
173 };
174 
175 enum LoopStatus {
176  kStatusOrdinary, // normal game-play: everything allowed
177  kStatusGate, // during running init-scripts when entering a room: disable interactivity
178  kStatusInventory, // inventory is open: cannot change the room or go to map
179  kStatusDialogue // during a dialogue: cannot change the room, go to inventory
180 };
181 
182 enum LoopSubstatus {
183  kOuterLoop, // outer loop: everything is allowed
184  kInnerWhileTalk, // playing a voice: inner loop will exit afterwards
185  kInnerWhileFade, // fading a palette: inner loop will exit when done
186  kInnerDuringDialogue, // selecting continuation block: inner block will exit afterwards
187  kInnerUntilExit // other inner loop: either immediately exiting or waiting for an animation to end (whose callback ends the loop)
188 };
189 
190 class Game {
191 public:
192  Game(DraciEngine *vm);
193  ~Game();
194 
195  void init();
196  void start();
197  void loop(LoopSubstatus substatus, bool shouldExit);
198 
199  // HACK: this is only for testing
200  int nextRoomNum() const {
201  int n = _currentRoom._roomNum;
202  n = n < 37 ? n+1 : n;
203  return n;
204  }
205 
206  // HACK: same as above
207  int prevRoomNum() const {
208  int n = _currentRoom._roomNum;
209  n = n > 0 ? n-1 : n;
210  return n;
211  }
212 
213  Common::Point findNearestWalkable(int x, int y) const { return _walkingMap.findNearestWalkable(x, y); }
214  void heroAnimationFinished() { _walkingState.heroAnimationFinished(); }
215  void stopWalking() { _walkingState.stopWalking(); } // and clear callback
216  void walkHero(int x, int y, SightDirection dir); // start walking and leave callback as is
217  void setHeroPosition(const Common::Point &p);
218  const Common::Point &getHeroPosition() const { return _hero; }
219  const Common::Point &getHeroLoadingPosition() const { return _heroLoading; }
220  void positionAnimAsHero(Animation *anim);
221  void positionHeroAsAnim(Animation *anim);
222 
223  // Makes sure animation anim_index plays on the hero. If the hero's
224  // position has changed, it updates the animation position. If the new
225  // animation is different, it stops the old one and starts the new one,
226  // otherwise it just marks dirty rectangles for moving the position.
227  // Returns the current animation phase of the new animation (usually 0
228  // unless the animation hasn't changed).
229  int playHeroAnimation(int anim_index);
230 
231  void loadOverlays();
232  void loadWalkingMap(int mapID); // but leaves _currentRoom._mapID untouched
233  void switchWalkingAnimations(bool enabled);
234 
235  uint getNumObjects() const { return _info._numObjects; }
236  GameObject *getObject(uint objNum) { return _objects + objNum; }
237  const GameObject *getObjectWithAnimation(const Animation *anim) const;
238  void deleteObjectAnimations();
239  void deleteAnimationsAfterIndex(int lastAnimIndex);
240 
241  int getVariable(int varNum) const { return _variables[varNum]; }
242  void setVariable(int varNum, int value) { _variables[varNum] = value; }
243 
244  const Person *getPerson(int personID) const { return &_persons[personID]; }
245 
246  int getRoomNum() const { return _currentRoom._roomNum; }
247  void setRoomNum(int num) { _currentRoom._roomNum = num; }
248  int getPreviousRoomNum() const { return _previousRoom; }
249  void rememberRoomNumAsPrevious() { _previousRoom = getRoomNum(); }
250  void scheduleEnteringRoomUsingGate(int room, int gate) { _newRoom = room; _newGate = gate; }
251  void pushNewRoom();
252  void popNewRoom();
253 
254  double getPers0() const { return _currentRoom._pers0; }
255  double getPersStep() const { return _currentRoom._persStep; }
256  int getMusicTrack() const { return _currentRoom._music; }
257  void setMusicTrack(int num) { _currentRoom._music = num; }
258 
259  int getItemStatus(int itemID) const { return _itemStatus[itemID]; }
260  void setItemStatus(int itemID, int status) { _itemStatus[itemID] = status; }
261  GameItem *getItem(int id) { return id >= 0 && id < (int)_info._numItems ? &_items[id] : NULL; }
262  GameItem *getCurrentItem() const { return _currentItem; }
263  void setCurrentItem(GameItem *item) { _currentItem = item; }
264  int getPreviousItemPosition() const { return _previousItemPosition; }
265  void setPreviousItemPosition(int pos) { _previousItemPosition = pos; }
266  void removeItem(GameItem *item);
267  void loadItemAnimation(GameItem *item);
268  void putItem(GameItem *item, int position);
269  void addItem(int itemID);
270 
271  int getEscRoom() const { return _currentRoom._escRoom; }
272  int getMapRoom() const { return _info._mapRoom; }
273  int getMapID() const { return _currentRoom._mapID; }
274 
281  int getMarkedAnimationIndex() const { return _markedAnimationIndex; }
282  void setMarkedAnimationIndex(int index) { _markedAnimationIndex = index; }
283 
284  void setLoopStatus(LoopStatus status) { _loopStatus = status; }
285  void setLoopSubstatus(LoopSubstatus status) { _loopSubstatus = status; }
286  LoopStatus getLoopStatus() const { return _loopStatus; }
287  LoopSubstatus getLoopSubstatus() const { return _loopSubstatus; }
288 
289  bool gameShouldQuit() const { return _shouldQuit; }
290  void setQuit(bool quit) { _shouldQuit = quit; }
291  bool shouldExitLoop() const { return _shouldExitLoop; }
292  void setExitLoop(bool exit) { _shouldExitLoop = exit; }
293  bool isReloaded() const { return _isReloaded; }
294  void setIsReloaded(bool value) { _isReloaded = value; }
295  bool isPositionLoaded() { return _isPositionLoaded; }
296  void setPositionLoaded(bool value) { _isPositionLoaded = value; }
297 
298  void setSpeechTiming(uint tick, uint duration);
299  void shiftSpeechAndFadeTick(int delta);
300 
301  void inventoryInit();
302  void inventoryDraw();
303  void inventoryDone();
304  void inventoryReload();
305  void inventorySwitch(int action);
306 
307  void dialogueMenu(int dialogueID);
308  int dialogueDraw();
309  void dialogueInit(int dialogID);
310  void dialogueDone();
311 
312  bool isDialogueBegin() const { return _dialogueBegin; }
313  bool shouldExitDialogue() const { return _dialogueExit; }
314  void setDialogueExit(bool exit) { _dialogueExit = exit; }
315  int getDialogueBlockNum() const { return _blockNum; }
316  int getDialogueVar(int dialogueID) const { return _dialogueVars[dialogueID]; }
317  void setDialogueVar(int dialogueID, int value) { _dialogueVars[dialogueID] = value; }
318  int getCurrentDialogue() const { return _currentDialogue; }
319  int getDialogueCurrentBlock() const { return _currentBlock; }
320  int getDialogueLastBlock() const { return _lastBlock; }
321  int getDialogueLinesNum() const { return _dialogueLinesNum; }
322  int getCurrentDialogueOffset() const { return _dialogueOffsets[_currentDialogue]; }
323 
324  void schedulePalette(int paletteID) { _scheduledPalette = paletteID; }
325  int getScheduledPalette() const { return _scheduledPalette; }
326  void initializeFading(int phases);
327  void setEnableQuickHero(bool value) { _enableQuickHero = value; }
328  bool getEnableQuickHero() const { return _enableQuickHero; }
329  void setWantQuickHero(bool value) { _wantQuickHero = value; }
330  bool getWantQuickHero() const { return _wantQuickHero; }
331  void setEnableSpeedText(bool value) { _enableSpeedText = value; }
332  bool getEnableSpeedText() const { return _enableSpeedText; }
333 
334  void synchronize(Common::Serializer &s, uint8 saveVersion);
335 
336 private:
337  void updateOrdinaryCursor();
338  void updateInventoryCursor();
339  int inventoryPositionFromMouse() const;
340  void handleOrdinaryLoop(int x, int y);
341  void handleInventoryLoop();
342  void handleDialogueLoop();
343  void updateTitle(int x, int y);
344  void updateCursor();
345  void fadePalette(bool fading_out);
346  void advanceAnimationsAndTestLoopExit();
347  void handleStatusChangeByMouse();
348 
349  void enterNewRoom();
350  void initWalkingOverlays();
351  void loadRoomObjects();
352  void redrawWalkingPath(Animation *anim, byte color, const WalkingPath &path);
353 
354  DraciEngine *_vm;
355 
356  GameInfo _info;
357 
358  Common::Point _hero;
359  Common::Point _heroLoading;
360  Common::Point _lastTarget;
361 
362  int *_variables;
363  Person *_persons;
364  GameObject *_objects;
365 
366  byte *_itemStatus;
367  GameItem *_items;
368  GameItem *_currentItem;
369  GameItem *_itemUnderCursor;
370 
371  // Last position in the inventory of the item currently in the hands, resp. of the item that
372  // was last in our hands.
373  int _previousItemPosition;
374 
375  GameItem *_inventory[kInventorySlots];
376 
377  Room _currentRoom;
378  int _newRoom;
379  int _newGate;
380  int _previousRoom;
381  int _pushedNewRoom; // used in GPL programs
382  int _pushedNewGate;
383 
384  uint *_dialogueOffsets;
385  int _currentDialogue;
386  int *_dialogueVars;
387  BArchive *_dialogueArchive;
388  Dialogue *_dialogueBlocks;
389  bool _dialogueBegin;
390  bool _dialogueExit;
391  int _currentBlock;
392  int _lastBlock;
393  int _dialogueLinesNum;
394  int _blockNum;
395  int _lines[kDialogueLines];
396  Animation *_dialogueAnims[kDialogueLines];
397 
398  LoopStatus _loopStatus;
399  LoopSubstatus _loopSubstatus;
400 
401  bool _shouldQuit;
402  bool _shouldExitLoop;
403  bool _isReloaded;
404  bool _isPositionLoaded;
405 
406  uint _speechTick;
407  uint _speechDuration;
408 
409  const GameObject *_objUnderCursor;
410  const Animation *_animUnderCursor;
411 
412  int _markedAnimationIndex;
413 
414  int _scheduledPalette;
415  int _fadePhases;
416  int _fadePhase;
417  uint _fadeTick;
418  bool _isFadeOut;
419  int _mouseChangeTick;
420 
421  bool _enableQuickHero;
422  bool _wantQuickHero;
423  bool _enableSpeedText;
424 
425  WalkingMap _walkingMap;
426  WalkingState _walkingState;
427 
428  Animation *_titleAnim;
429  Animation *_inventoryAnim;
430  Animation *_walkingMapOverlay;
431  Animation *_walkingShortestPathOverlay;
432  Animation *_walkingObliquePathOverlay;
433 };
434 
435 } // End of namespace Draci
436 
437 #endif // DRACI_GAME_H
Definition: game.h:131
Definition: walking.h:103
Definition: draci.h:122
Definition: str.h:59
Definition: animation.h:59
Definition: game.h:144
Definition: array.h:52
Definition: walking.h:34
int getMarkedAnimationIndex() const
Definition: game.h:281
InventoryConstants
Definition: game.h:77
Definition: game.h:149
Definition: serializer.h:79
Used for positioning of the inventory sprite on the X axis.
Definition: game.h:82
Definition: game.h:90
Definition: algorithm.h:29
Definition: rect.h:144
Definition: barchive.h:48
Definition: game.h:190
Definition: animation.h:30
Definition: game.h:117
Definition: script.h:83
Used for positioning of the inventory sprite on the Y axis.
Definition: game.h:83
Definition: game.h:156