ScummVM API documentation
types.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#ifndef PELROCK_TYPES_H
22#define PELROCK_TYPES_H
23
24#include "common/rect.h"
25#include "common/system.h"
26
27namespace Pelrock {
28
32enum Cursor {
33 DEFAULT,
34 HOTSPOT,
35 EXIT,
36 ALFRED,
37 COMBINATION
38};
39
43const byte kActionMaskNone = 0;
44const byte kActionMaskOpen = 1;
45const byte kActionMaskClose = 2;
46const byte kActionMaskUnknown = 4;
47const byte kActionMaskPickup = 8;
48const byte kActionMaskTalk = 16;
49const byte kActionMaskPush = 32;
50const byte kActionMaskPull = 128;
51
52enum VerbIcon {
53 PICKUP,
54 TALK,
55 WALK,
56 LOOK,
57 PUSH,
58 PULL,
59 OPEN,
60 CLOSE,
61 ITEM,
62 UNKNOWN,
63 NO_ACTION
64};
65
66const int kCursorWidth = 16;
67const int kCursorHeight = 18;
68const int kCursorSize = 288; // 16 * 18
69
70const int kVerbIconWidth = 60;
71const int kVerbIconHeight = 60;
72const int kNumVerbIcons = 9;
73
74const int kBalloonWidth = 247;
75const int kBalloonHeight = 112;
76const int kBalloonFrames = 4;
77
78const int kAlfredFrameWidth = 51;
79const int kAlfredFrameHeight = 102;
80
81const int kTalkAnimationSpeed = 2; // Frames per update
82const int kAlfredAnimationSpeed = 2; // Frames per update
83
84const int kAlfredIdleAnimationFrameCount = 300; // comb animation plays every ~16 seconds of idle alfred
85const int kAlfredIdleScreenSaverFrameCount = 1090; // screen saver shows up after 60 seconds
86
87const int kInventoryPageSize = 10;
88
89const int kAlfredInitialPosX = 235;
90const int kAlfredInitialPosY = 279;
91
92// Direction flags (bit-packed)
93const byte kMoveRight = 0x01; // Move right (positive X)
94const byte kMoveLeft = 0x02; // Move left (negative X)
95const byte kMoveHoriz = 0x03; // Horizontal movement mask
96const byte kMoveDown = 0x04; // Move down (positive Y)
97const byte kMoveUp = 0x08; // Move up (negative Y)
98const byte kMoveVert = 0x0C; // Vertical movement mask
99const int kMaxPathLength = 100;
100const int kMaxMovementSteps = 100; // 500 bytes / 5 bytes per step
101const byte kPathEnd = 0xFF; // End of path marker
102
103const byte kAlfredColor = 0x0D;
104
105enum OverlayMode {
106 OVERLAY_NONE = 0,
107 OVERLAY_CHOICES = 1,
108 OVERLAY_PICKUP_ICON = 2,
109 OVERLAY_ACTION = 3
110};
111
112// Passerby direction constants
113const byte kPasserbyRight = 0;
114const byte kPasserbyLeft = 1;
115const byte kPasserbyDown = 2;
116
117const byte kIconBlinkPeriod = 4;
118
119enum AlfredAnimState {
120 ALFRED_IDLE,
121 ALFRED_WALKING,
122 ALFRED_TALKING,
123 ALFRED_INTERACTING,
124 ALFRED_COMB,
125 ALFRED_SPECIAL_ANIM,
126 ALFRED_SKIP_DRAWING
127};
128
129enum AlfredDirection {
130 ALFRED_RIGHT = 0,
131 ALFRED_LEFT = 1,
132 ALFRED_DOWN = 2,
133 ALFRED_UP = 3
134};
135
137 byte *animData = nullptr;
138 int w = 0;
139 int h = 0;
140 int numFrames = 0;
141 int loopCount = 0;
142 uint32 stride = 0;
143 int curFrame = 0;
144 int curLoop = 0;
145 uint32 size = 0;
146 int speed = 2;
147 AlfredSpecialAnim(int nF, int width, int height, int nBudas, uint32 off, int lCount, uint32 sz, int spd = 2)
148 : numFrames(nF), w(width), h(height), loopCount(lCount), size(sz), speed(spd) {
149 stride = w * h;
150 }
151
153 if (animData) {
154 delete[] animData;
155 animData = nullptr;
156 }
157 }
158};
159
161 bool isActive = false;
162 int curFrame = 0;
163 int x = 0;
164 int y = 0;
165 int displayTime = 0;
166 bool isAlfredUnder = false;
167};
168
170 bool isActive = false;
171 int invStartingPos = 0;
172 int flashingIconIndex = -1;
173 Common::Rect inventorySelectionArea = Common::Rect(0, 340, 640, 400);
174 Common::Rect ballonInventoryPath = Common::Rect(0, 0, kBalloonWidth, kBalloonHeight);
175 byte *arrows[2] = {nullptr, nullptr};
176
177 bool posInInventorySelectionArea(int x, int y) {
178 return inventorySelectionArea.contains(x, y);
179 }
180};
181
183 AlfredAnimState animState = ALFRED_IDLE;
184 AlfredDirection direction = ALFRED_DOWN;
185 int curFrame = 0;
186 uint16 movementSpeedX = 6; // pixels per frame
187 uint16 movementSpeedY = 5; // pixels per frame
188 uint16 x = kAlfredInitialPosX;
189 uint16 y = kAlfredInitialPosY;
190 byte w = kAlfredFrameWidth;
191 byte h = kAlfredFrameHeight;
192 int idleFrameCounter = 0;
193 int screenSaverFrameCounter = 0;
194 bool isWalkingCancelable = true;
195
196 void setState(AlfredAnimState nextState) {
197 animState = nextState;
198 curFrame = 0;
199 }
200
201 void resetIdles() {
202 idleFrameCounter = 0;
203 screenSaverFrameCounter = 0;
204 }
205};
206
208 bool enabled = false;
209 int shakeX = 0;
210 int shakeY = 0;
211
212 void enable() {
213 enabled = true;
214 }
215
216 void disable() {
217 enabled = false;
218 shakeX = 0;
219 shakeY = 0;
220 g_system->setShakePos(0, 0);
221 }
222};
223
225 byte flags; /* Direction flags (see kMove* constants) */
226 uint16 distanceX; // Horizontal distance to move
227 uint16 distanceY; // Vertical distance to move
228};
229
234 byte *pathBuffer; // Sequence of walkbox indices
235 MovementStep *movementBuffer; // Array of movement steps
236 uint16 pathLength;
237 uint16 movementCount;
238 uint16 compressed_length;
239};
240
242 uint32 offset;
243 uint32 paletteOffset;
244 byte numChunks;
245};
246
251 int numFrames;
252 int w;
253 int h;
254 int numBudas;
255 int numAlfred;
256 uint32 offset;
257 int loops;
258 int speed;
259 uint32 size; // 0 = compute from numFrames * w * h
260};
261
265struct Anim {
266 int nframes = 0;
267 int curFrame = 0;
268 int curLoop = 0;
269 byte **animData = nullptr;
270 byte loopCount = 0;
271 byte speed = 0;
272 byte elpapsedFrames = 0;
273 uint16 movementFlags = 0;
274};
275
276struct Exit {
277 byte index;
278 int16 x;
279 int16 y;
280 byte w;
281 byte h;
282 uint16 targetRoom;
283 int16 targetX;
284 int16 targetY;
285 AlfredDirection dir;
286 byte isEnabled;
287};
288
289struct Sprite {
290 byte index; // number of the animation in the rooms
291 int16 x; // 0
292 int16 y; // 2
293 int w; // 4
294 int h; // 5
295 uint16 stride; // 6-7
296 int numAnims; // 8
297 int curAnimIndex = 0;
298 byte zOrder; // byte at file offset 23
299 byte actionFlags; // 34
300 bool isHotspotDisabled; // 38
301 bool disableAfterSequence = false; // 39
302 bool isTalking = false;
303 byte talkingAnimIndex = 0;
304 Anim *animData;
305 int16 extra;
306};
307
308struct HotSpot {
309 byte index = 0;
310 byte innerIndex = 0;
311 int id = 0;
312 int16 x = 0;
313 int16 y = 0;
314 int w = 0;
315 int h = 0;
316 byte actionFlags = 0;
317 int16 extra = 0;
318 bool isEnabled = true;
319 bool isSprite = false;
320 byte zOrder = 0;
321};
322
324 uint32 spritePointer = 0;
325
326 byte unknown2[3];
327
328 int8 offsetXAnimA = 0;
329 int8 offsetYAnimA = 0;
330
331 byte wAnimA = 0;
332 byte hAnimA = 0;
333 byte unknown3[2];
334 byte numFramesAnimA = 0;
335 byte unknown4[4]; // slot 0 data pointer (unused in ScummVM)
336 byte speedByteA = 0; // slot 0 offset 0x12: controls NPC talk render rate (original: 2+speedByte ticks per render)
337
338 int8 offsetXAnimB = 0;
339 int8 offsetYAnimB = 0;
340
341 byte wAnimB = 0;
342 byte hAnimB = 0;
343 byte unknown5[2]; // slot 1 stride (unused in ScummVM)
344 byte numFramesAnimB = 0;
345 byte unknown7[4]; // slot 1 data pointer (unused in ScummVM)
346 byte speedByteB = 0; // slot 1 speed byte at file offset 30
347 byte unknown6[24]; // slots 2-3 (unused)
348
349 // Runtime fields (not read from file)
350 byte currentFrameAnimA = 0;
351 byte currentFrameAnimB = 0;
352
353 byte **animA = nullptr;
354 byte **animB = nullptr;
355};
356
358 byte itemId = 0;
359 byte index = 0;
360 bool isAction = false;
361 uint16 actionTrigger = 0;
362 Common::String text;
363};
364
365struct WalkBox {
366 byte index;
367 int16 x;
368 int16 y;
369 int16 w;
370 int16 h;
371 byte flags;
372};
373
375 VerbIcon verb;
376 int hotspotIndex;
377 bool isQueued; // Alfred is walking/interacting toward the target
378 bool readyToExecute; // Animation done - execute after the current renderScene
379};
380
382 int16 yThreshold;
383 byte scaleDivisor;
384 byte scaleMode;
385};
386
388 int scaledWidth;
389 int scaledHeight;
390 int scaleX; // Amount to subtract from width (was scaleUp)
391 int scaleY; // Amount to subtract from height (was scaleDown)
392};
393
394enum GameState {
395 GAME = 100,
396 CREDITS = 101,
397 SETTINGS = 102,
398 INTRO = 103,
399 COMPUTER = 104
400};
401
403 byte roomNumber;
404 byte spriteIndex;
405 byte zIndex;
406};
407
409 byte roomNumber;
410 byte hotspotIndex;
411 HotSpot hotspot;
412};
413
415 byte roomNumber;
416 byte exitIndex;
417 bool enabled;
418};
419
421 byte roomNumber;
422 byte walkboxIndex;
423 WalkBox walkbox;
424};
425
427 byte index;
428 Common::String description;
429 byte iconData[60 * 60];
430};
431
433 byte startIndex;
434 byte paletteMode;
435 byte currentR;
436 byte currentG;
437 byte currentB;
438 byte minR;
439 byte minG;
440 byte minB;
441 byte maxR;
442 byte maxG;
443 byte maxB;
444 byte speed;
445 bool downDirection;
446 byte curFrameCount = 0;
447};
448
449struct Sticker {
450 int stickerIndex;
451 uint16 x;
452 uint16 y;
453 byte w;
454 byte h;
455};
456
458 byte startIndex = 0;
459 byte paletteMode = 0;
460 byte unknown = 0;
461 byte delay = 0;
462 byte unknownBytes[7] = {0};
463 byte flags = 0;
464 byte curFrameCount = 0;
465};
466
468 byte startIndex = 0;
469 byte paletteMode = 0;
470 byte data[10] = {0}; // Based on mode its a rotate or fade
471 byte curFrame = 0;
472 byte tickCount = 0;
473};
474
476 uint32 frameTrigger = 0x3FF;
477 int16 startX;
478 int16 startY;
479 int16 resetCoord;
480 byte dir;
481 byte spriteIndex;
482 byte targetZIndex;
483
484 PasserByAnim() = default;
485 PasserByAnim(byte spriteIndex_, int16 startX_, int16 startY_, byte dir_, int16 resetCoord_, byte targetZIndex_, uint32 frameTrigger_)
486 : frameTrigger(frameTrigger_), startX(startX_), startY(startY_), resetCoord(resetCoord_), dir(dir_), spriteIndex(spriteIndex_), targetZIndex(targetZIndex_) {}
487};
488
490 byte roomNumber;
491 PasserByAnim passerByAnims[2];
492 byte currentAnimIndex = 0;
493 byte numAnims = 0;
494 bool latch = false;
495 RoomPasserBys(byte roomNum, byte nAnims) : roomNumber(roomNum), numAnims(nAnims) {}
496};
497
502 byte room = static_cast<byte>(-1);
503 int choiceIndex;
504 Common::String text;
505 uint32 dataOffset;
506 bool isDisabled = false;
507 bool shouldDisableOnSelect = false;
508 bool hasConversationEndMarker = false;
509 bool isTerminator = false;
510 uint charOffset = 0;
511
512 ChoiceOption() : choiceIndex(-1), dataOffset(0) {}
513};
514
516 uint16 room = 0;
517 uint16 offset = 0;
518 byte dataSize = 0;
519 byte *data = nullptr;
520};
521
522#define FLAG_BOSS_WIRED_MONEY 0
523#define FLAG_BOSS_IN_JAIL 1
524#define FLAG_SPICY_SAUCE_PLACED 2
525#define FLAG_BROKEN_GLASS 3
526#define FLAG_FIRST_TIME_IN_SHOP 4
527#define FLAG_ELECTROSHOCK 5
528#define FLAG_CABLES_PLACED 6
529#define FLAG_DOORMAN_BRIBED 7
530#define FLAG_BOOK_MEMORIZED 8
531#define FLAG_ALFRED_SMART 9
532#define FLAG_ALFRED_SPEAKS_EGYPTIAN 10
533#define FLAG_SALESMAN_LEAVES_ALFRED_ALONE 11
534#define FLAG_TRAVEL_TO_EGYPT 12
535#define FLAG_SOLVED_PARADOX 13
536#define FLAG_CROCODILE_ON 14
537#define FLAG_LOOKED_SYMBOL_MUSEUM_EXTERIOR 15
538#define FLAG_SECRET_DOOR_OPEN 16
539#define FLAG_STOLE_PRINCESS_HAIR 17
540#define FLAG_TO_JAIL 18
541#define FLAG_SAFE_COMBINATION 19
542#define FLAG_DOLL_PLACED 20
543#define FLAG_GUARD_WATER_DRINKED 21
544#define FLAG_GUARD_PEEING 22
545#define FLAG_PYRAMID_COLLAPSED 23
546#define FLAG_PYRAMID_COLLAPSED2 24
547#define FLAG_GUARD_HAVINGFUN 25
548#define FLAG_MAGIC_FORMULA 26
549#define FLAG_TIME_TRAVEL 27
550#define FLAG_EUNUCH_APPEARS 28
551#define FLAG_PHARAOH_VIEWING 29
552#define FLAG_TO_WORK 30
553#define FLAG_STONE_GIVEN 31
554#define FLAG_COLLECTED_STONES 32
555#define FLAG_DRUNK_GUARDS 33
556#define FLAG_FAKE_STONE_WET 34
557#define FLAG_CORRECT_DOOR 35
558#define FLAG_TRAPDOOR_OPEN 36
559#define FLAG_PRINCESS_ROOM 37
560#define FLAG_GET_THE_PRINCESS 38
561#define FLAG_GAME_RESTART 39
562#define FLAG_CORRIDORS 40
563#define FLAG_GODS_STANCES 41
564#define FLAG_END_OF_GAME 42
565#define FLAG_FROM_INTRO 43
566#define FLAG_STONE_THROWN 44
567#define FLAG_USED_WATER 45
568#define FLAG_OPEN_SHOP 46
569#define FLAG_DRINKS_NUMBER 47
570#define FLAG_COLLECTED_INGREDIENTS 48
571#define FLAG_GUARD_ASKS_FOR_STUFF 49
572#define FLAG_GUARD_ID_DELIVERED 50
573#define FLAG_TRAVELAGENCY_OPEN 51
574#define FLAG_MERCHANT_SLOGANS 52
575#define FLAG_HOOKER_250_TIMES 53
576#define FLAG_CORRECT_ANSWERS 54
577#define FLAG_CHEAT_CODE_ENABLED 55
578#define FLAG_RIDDLE_PRESENTED 56
579#define FLAG_SYMBOLS_PUSHED 57
580#define FLAG_MERCHANT_GIVENITEMS 58
581#define FLAG_CORRECT_DOOR_CHOSEN 59
582#define FLAG_SKELETON_RECOGNIZES 60
583#define FLAG_PIGEON_DEAD 61
584#define FLAG_RECIPE_TAKEN 62
585
586const int kNumGameFlags = 63;
587
589 byte flags[kNumGameFlags];
590
591 GameState stateGame = INTRO;
592
593 Common::Array<byte> inventoryItems;
594 int16 selectedInventoryItem = -1;
595
596 int libraryShelf = -1;
597 int selectedBookIndex = -1;
598 char bookLetter = '\0';
605
606 GameStateData() {
607 clear();
608 }
609
611 clearBranches();
612 delete[] conversationCurrentRoot;
613 conversationCurrentRoot = nullptr;
614 }
615
616 void clear() {
617 memset(conversationCurrentRoot, 0xFF, 112); // Initialize all to 0xFF (not set)
618 for (int i = 0; i < kNumGameFlags; i++)
619 flags[i] = 0;
620 flags[FLAG_FIRST_TIME_IN_SHOP] = true;
621 inventoryItems.clear();
622 stickersPerRoom.clear();
623 roomExitChanges.clear();
624 roomWalkBoxChanges.clear();
625 roomHotSpotChanges.clear();
626 spriteChanges.clear();
627 clearBranches();
628 libraryShelf = -1;
629 selectedBookIndex = -1;
630 bookLetter = '\0';
631 stateGame = GAME;
632 }
633
634 void clearBranches() {
635 for(auto &entry : disabledBranches) {
636 for (ResetEntry &resetEntry : entry._value) {
637 if (resetEntry.data) {
638 delete[] resetEntry.data;
639 resetEntry.data = nullptr;
640 }
641 }
642 }
643 disabledBranches.clear();
644 }
645
646 void addDisabledBranch(ResetEntry entry) {
647 disabledBranches[entry.room].push_back(entry);
648 }
649
650 byte getFlag(int flagIndex) const {
651 if (flagIndex < 0 || flagIndex >= kNumGameFlags)
652 return false;
653 return flags[flagIndex];
654 }
655
656 bool getBoolFlag(int flagIndex) const {
657 return getFlag(flagIndex) != 0;
658 }
659
660 void setFlag(int flagIndex, byte value) {
661 if (flagIndex < 0 || flagIndex >= kNumGameFlags)
662 return;
663 flags[flagIndex] = value;
664 }
665
666 void addInventoryItem(int id) {
667 inventoryItems.push_back(id);
668 }
669
670 void clearInventory() {
671 inventoryItems.clear();
672 selectedInventoryItem = -1;
673 }
674
675 void removeInventoryItem(int id) {
676 for (uint i = 0; i < inventoryItems.size(); i++) {
677 if (inventoryItems[i] == id) {
678 inventoryItems.remove_at(i);
679 break;
680 }
681 }
682 if (selectedInventoryItem == id) {
683 if (inventoryItems.size() > 0) {
684 selectedInventoryItem = inventoryItems[0];
685 } else {
686 selectedInventoryItem = -1;
687 }
688 }
689 }
690
691 bool hasInventoryItem(int id) const {
692 for (uint i = 0; i < inventoryItems.size(); i++) {
693 if (inventoryItems[i] == id) {
694 return true;
695 }
696 }
697 return false;
698 }
699
700 // Store current root index for each room (0xFF = not set, use findRoot logic)
701 byte *conversationCurrentRoot = new byte[112];
702
703 int getCurrentRoot(byte room, int npc) const {
704 if (room >= 56)
705 return -1;
706 return (conversationCurrentRoot[room * 2 + npc] == 0xFF) ? -1 : conversationCurrentRoot[room * 2 + npc];
707 }
708
709 void setCurrentRoot(byte room, int root, int npc) {
710 if (room >= 56)
711 return;
712 if (root < 0 || root > 254) {
713 conversationCurrentRoot[room * 2 + npc] = 0xFF; // Reset to auto-select
714 } else {
715 conversationCurrentRoot[room * 2 + npc] = (byte)root;
716 }
717 }
718
719 int findFirstBookIndex() {
720 for (uint i = 0; i < inventoryItems.size(); i++) {
721 int x = inventoryItems[i];
722 if ((x >= 11) && (x <= 58))
723 return x;
724 }
725 return -1;
726 }
727
728 int booksInInventory() {
729 int l = inventoryItems.size();
730 int count = 0;
731 for (int i = 0; i < l; i++) {
732 int x = inventoryItems[i];
733 if ((x >= 11) && (x <= 58))
734 count++;
735 }
736 return count;
737 }
738};
739
741 byte currentRoom = 0;
742 uint16 alfredX = 0;
743 uint16 alfredY = 0;
744 AlfredDirection alfredDir = ALFRED_DOWN;
745 GameStateData *gameState = nullptr;
746};
747
749 int roomNumber;
750 int spriteIdx;
751 int appearFrames;
752 int spellFrames;
753 int spellPage;
754};
755
756static const FightRoomCfg kFightRooms[] = {
757 {51, 1, 31, 17, 8}, // room 51
758 {52, 0, 30, 13, 4}, // room 52
759 {53, 1, 30, 13, 0}, // room 53
760 {54, 1, 38, 11, 2}, // room 54
761};
762
763} // End of namespace Pelrock
764
765#endif
T remove_at(size_type idx)
Definition: array.h:261
size_type size() const
Definition: array.h:316
void clear()
Definition: array.h:321
void push_back(const T &element)
Definition: array.h:181
Definition: hashmap.h:85
Definition: str.h:59
void clear(bool shrinkArray=0)
Definition: hashmap.h:431
virtual void setShakePos(int shakeXOffset, int shakeYOffset)=0
OSystem * g_system
bool contains(T x, T y) const
Definition: rect.h:246
Definition: rect.h:536
Definition: atari-cursor.h:35
Definition: types.h:160
Definition: types.h:136
Definition: types.h:250
Definition: types.h:182
Definition: types.h:265
Definition: types.h:501
Definition: types.h:357
Definition: types.h:414
Definition: types.h:276
Definition: types.h:241
Definition: types.h:748
Definition: types.h:588
Definition: types.h:408
Definition: types.h:308
Definition: types.h:426
Definition: types.h:169
Definition: types.h:224
Definition: types.h:432
Definition: types.h:467
Definition: types.h:457
Definition: types.h:475
Definition: types.h:233
Definition: types.h:374
Definition: types.h:515
Definition: types.h:489
Definition: types.h:740
Definition: types.h:387
Definition: types.h:381
Definition: types.h:207
Definition: types.h:402
Definition: types.h:289
Definition: types.h:449
Definition: types.h:323
Definition: types.h:420
Definition: types.h:365