diff options
Diffstat (limited to 'engines/sherlock/objects.h')
-rw-r--r-- | engines/sherlock/objects.h | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h new file mode 100644 index 0000000000..996054be43 --- /dev/null +++ b/engines/sherlock/objects.h @@ -0,0 +1,478 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_OBJECTS_H +#define SHERLOCK_OBJECTS_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "common/str-array.h" +#include "common/str.h" +#include "sherlock/image_file.h" +#include "sherlock/fixed_text.h" +#include "sherlock/saveload.h" + +namespace Sherlock { + +class SherlockEngine; + +enum ObjectAllow { + ALLOW_MOVE = 1, ALLOW_OPEN = 2, ALLOW_CLOSE = 4 +}; + +enum SpriteType { + INVALID = 0, + CHARACTER = 1, + CURSOR = 2, + STATIC_BG_SHAPE = 3, // Background shape that doesn't animate + ACTIVE_BG_SHAPE = 4, // Background shape that animates + REMOVE = 5, // Object should be removed next frame + NO_SHAPE = 6, // Background object with no shape + HIDDEN = 7, // Hidden backgruond object + HIDE_SHAPE = 8, // Object needs to be hidden + + // Rose Tattoo + HIDDEN_CHARACTER = 128 +}; + +enum AType { + OBJECT = 0, + PERSON = 1, + SOLID = 2, + TALK = 3, // Standard talk zone + FLAG_SET = 4, + DELTA = 5, + WALK_AROUND = 6, + TALK_EVERY = 7, // Talk zone that turns on every room visit + TALK_MOVE = 8, // Talk zone that only activates when Holmes moves + PAL_CHANGE = 9, // Changes the palette down so that it gets darker + PAL_CHANGE2 = 10, // Same as PAL_CHANGE, except that it goes up + SCRIPT_ZONE = 11, // If this is clicked in, it is activated + BLANK_ZONE = 12, // This masks out other objects when entered + NOWALK_ZONE = 13 // Player cannot walk here +}; + +// Different levels for sprites to be at +enum { + BEHIND = 0, NORMAL_BEHIND = 1, NORMAL_FORWARD = 2, FORWARD = 3 +}; + +#define MAX_HOLMES_SEQUENCE 16 +#define MAX_FRAME 30 +#define FIXED_INT_MULTIPLIER 1000 + +// code put into sequences to defines 1-10 type seqs +#define SEQ_TO_CODE 67 +#define FLIP_CODE (64 + 128) +#define SOUND_CODE (34 + 128) +#define HIDE_CODE (7+128) // Code for hiding/unhiding an object from a Sequence +#define CALL_TALK_CODE (8+128) // Code for call a Talk File from a Sequence +#define TELEPORT_CODE (9+128) // Code for setting Teleport Data (X,Y) +#define MOVE_CODE (10+128) // Code for setting Movement Delta (X,Y) + +#define GOTO_CODE 228 +#define TALK_SEQ_CODE 252 // Code specifying start of talk sequence frames in a Sequence +#define TALK_LISTEN_CODE 251 // Code specifying start of talk listen frames in a Sequence +#define ALLOW_TALK_CODE 250 + +#define UPPER_LIMIT 0 +#define LOWER_LIMIT (IS_SERRATED_SCALPEL ? CONTROLS_Y : SHERLOCK_SCREEN_HEIGHT) +#define LEFT_LIMIT 0 +#define RIGHT_LIMIT SHERLOCK_SCREEN_WIDTH + +class Point32 { +public: + int x; + int y; + + Point32() : x(0), y(0) {} + Point32(int x1, int y1) : x(x1), y(y1) {} + Point32(const Common::Point &pt) : x(pt.x), y(pt.y) {} + + bool operator==(const Point32 &p) const { return x == p.x && y == p.y; } + bool operator!=(const Point32 &p) const { return x != p.x || y != p.y; } + Point32 operator+(const Point32 &delta) const { return Point32(x + delta.x, y + delta.y); } + Point32 operator-(const Point32 &delta) const { return Point32(x - delta.x, y - delta.y); } + operator Common::Point() { return Common::Point(x, y); } + + void operator+=(const Point32 &delta) { x += delta.x; y += delta.y; } + void operator-=(const Point32 &delta) { x -= delta.x; y -= delta.y; } +}; + +class PositionFacing : public Point32 { +public: + int _facing; + + PositionFacing() : Point32(), _facing(0) {} + PositionFacing(int xp, int yp, int theFacing) : Point32(xp, yp), _facing(theFacing) {} + PositionFacing &operator=(const Point32 &pt) { + x = pt.x; y = pt.y; + return *this; + } +}; + +struct WalkSequence { + Common::String _vgsName; + bool _horizFlip; + Common::Array<byte> _sequences; + + WalkSequence() : _horizFlip(false) {} + const byte &operator[](int idx) { return _sequences[idx]; } + + /** + * Load data for the sequence from a stream + */ + void load(Common::SeekableReadStream &s); +}; + +class WalkSequences : public Common::Array < WalkSequence > { +public: + WalkSequences &operator=(const WalkSequences &src); +}; + +enum { REVERSE_DIRECTION = 0x80 }; +#define NAMES_COUNT 4 + +struct ActionType { + int _cAnimNum; + int _cAnimSpeed; + Common::String _names[NAMES_COUNT]; + int _useFlag; // Which flag USE will set (if any) + + ActionType(); + + /** + * Load the data for the action + */ + void load(Common::SeekableReadStream &s); +}; + +struct UseType: public ActionType { + Common::String _target; + Common::String _verb; + + UseType(); + + /** + * Load the data for the UseType + */ + void load(Common::SeekableReadStream &s, bool isRoseTattoo); + void load3DO(Common::SeekableReadStream &s); + + /** + * Synchronize the data for a savegame + */ + void synchronize(Serializer &s); +}; + +class BaseObject { +protected: + static SherlockEngine *_vm; +protected: + /** + * This will check to see if the object has reached the end of a sequence. + * If it has, it switch to whichever next sequence should be started. + * @returns true if the end of a sequence was reached + */ + bool checkEndOfSequence(); + + /** + * Scans through the sequences array and finds the designated sequence. + * It then sets the frame number of the start of that sequence + */ + void setObjSequence(int seq, bool wait); +public: + static bool _countCAnimFrames; +public: + SpriteType _type; // Type of object/sprite + Common::String _description; // Description lines + byte *_sequences; // Holds animation sequences + ImageFile *_images; // Sprite images + ImageFrame *_imageFrame; // Pointer to shape in the images + int _walkCount; // Walk counter + int _allow; // Allowed UI commands + int _frameNumber; // Frame number in rame sequence to draw + Point32 _position; // Current position + Point32 _delta; // Momvement amount + Common::Point _oldPosition; // Old position + Common::Point _oldSize; // Image's old size + Point32 _goto; // Walk destination + + int _lookFlag; // Which flag LOOK will set (if any) + int _requiredFlag[2]; // Object will be hidden if not set + Common::Point _noShapeSize; // Size of a NO_SHAPE + int _status; // Status (open/closed, moved/not) + int8 _misc; // Misc field -- use varies with type + int _maxFrames; // Number of frames + int _flags; // Tells if object can be walked behind + AType _aType; // Tells if this is an object, person, talk, etc. + int _lookFrames; // How many frames to play of the look anim before pausing + int _seqCounter; // How many times this sequence has been executed + PositionFacing _lookPosition; // Where to walk when examining object + int _lookcAnim; + int _seqStack; // Allows gosubs to return to calling frame + int _seqTo; // Allows 1-5, 8-3 type sequences encoded in 2 bytes + uint _descOffset; // Tells where description starts in DescText + int _seqCounter2; // Counter of calling frame sequence + uint _seqSize; // Tells where description starts + UseType _use[6]; // Serrated Scalpel uses 4, Rose Tattoo 6 + int _quickDraw; // Flag telling whether to use quick draw routine or not + int _scaleVal; // Tells how to scale the sprite + int _gotoSeq; // Used by Talk to tell which sequence to goto when able + int _talkSeq; // Tells which talk sequence currently in use (Talk or Listen) + int _restoreSlot; // Used when talk returns to the previous sequence +public: + BaseObject(); + virtual ~BaseObject() {} + static void setVm(SherlockEngine *vm); + + /** + * Returns true if the the object has an Allow Talk Code in the sequence that it's + * currently running, specified by the _talkSeq field of the object. If it's 0, + * then it's a regular sequence. If it's not 0 but below 128, then it's a Talk Sequence. + * If it's above 128, then it's one of the Listen sequences. + */ + bool hasAborts() const; + + /** + * Check the state of the object + */ + void checkObject(); + + /** + * Checks for codes + * @param name The name to check for codes + * @param messages Provides a lookup list of messages that can be printed + * @returns 0 if no codes are found, 1 if codes were found + */ + int checkNameForCodes(const Common::String &name, FixedTextActionId fixedTextActionId = kFixedTextAction_Invalid); + + /** + * Adjusts the frame and sequence variables of a sprite that corresponds to the current speaker + * so that it points to the beginning of the sequence number's talk sequence in the object's + * sequence buffer + * @param seq Which sequence to use (if there's more than 1) + * @remarks 1: First talk seq, 2: second talk seq, etc. + */ + virtual void setObjTalkSequence(int seq) {} +}; + +class Sprite: public BaseObject { +public: + Common::String _name; + Common::String _examine; // Examine in-depth description + Common::String _pickUp; // Message for if you can't pick up object + + WalkSequences _walkSequences; // Holds animation sequences + int _sequenceNumber; // Sequence being used + Common::Point _noShapeSize; // Size of a NO_SHAPE + int _status; // Status: open/closed, moved/not moved + int8 _misc; // Miscellaneous use + + // Rose Tattoo fields + int _startSeq; // Frame sequence starts at + ImageFrame *_stopFrames[8]; // Stop/rest frame for each direction + ImageFile *_altImages; // Images used for alternate NPC sequences + int _altSeq; // Which of the sequences the alt graphics apply to (0: main, 1=NPC seq) + int _centerWalk; // Flag telling the walk code to offset the walk destination + Common::Point _adjust; // Fine tuning adjustment to position when drawn + int _oldWalkSequence; +public: + Sprite(): BaseObject() { clear(); } + virtual ~Sprite() {} + + static void setVm(SherlockEngine *vm) { _vm = vm; } + + /** + * Reset the data for the sprite + */ + void clear(); + + /** + * Updates the image frame poiner for the sprite + */ + void setImageFrame(); + + /** + * Checks the sprite's position to see if it's collided with any special objects + */ + void checkSprite(); + + /** + * Adjusts the frame and sequence variables of a sprite that corresponds to the current speaker + * so that it points to the beginning of the sequence number's talk sequence in the object's + * sequence buffer + * @param seq Which sequence to use (if there's more than 1) + * @remarks 1: First talk seq, 2: second talk seq, etc. + */ + virtual void setObjTalkSequence(int seq) {} + + /** + * Return frame width + */ + int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; } + + /** + * Return frame height + */ + int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; } + + /** + * Returns the old bounsd for the sprite from the previous frame + */ + const Common::Rect getOldBounds() const; + + /** + * This adjusts the sprites position, as well as it's animation sequence: + */ + virtual void adjustSprite() = 0; + + /** + * Bring a moving character using the sprite to a standing position + */ + virtual void gotoStand() = 0; + + /** + * Set the variables for moving a character from one poisition to another + * in a straight line + */ + virtual void setWalking() = 0; +}; + +enum { OBJ_BEHIND = 1, OBJ_FLIPPED = 2, OBJ_FORWARD = 4, TURNON_OBJ = 0x20, TURNOFF_OBJ = 0x40 }; +#define USE_COUNT 4 + +class Object: public BaseObject { +public: + Common::String _name; // Name + Common::String _examine; // Examine in-depth description + int _sequenceNumber; + int _sequenceOffset; + int _pickup; + int _defaultCommand; // Default right-click command + + // Serrated Scalpel fields + int _pickupFlag; // Which flag PICKUP will set (if any) + ActionType _aOpen; // Holds data for moving object + ActionType _aClose; + ActionType _aMove; + + Object(); + virtual ~Object() {} + + /** + * Load the data for the object + */ + void load(Common::SeekableReadStream &s, bool isRoseTattoo); + void load3DO(Common::SeekableReadStream &s); + + /** + * Toggle the type of an object between hidden and active + */ + void toggleHidden(); + + /** + * Handle setting any flags associated with the object + */ + void setFlagsAndToggles(); + + /** + * Adjusts the sprite's position and animation sequence, advancing by 1 frame. + * If the end of the sequence is reached, the appropriate action is taken. + */ + void adjustObject(); + + /** + * Handles trying to pick up an object. If allowed, plays an y necessary animation for picking + * up the item, and then adds it to the player's inventory + */ + int pickUpObject(FixedTextActionId fixedTextActionId = kFixedTextAction_Invalid); + + /** + * Return the frame width + */ + int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; } + + /** + * Return the frame height + */ + int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; } + + /** + * Returns the current bounds for the sprite + */ + const Common::Rect getNewBounds() const; + + /** + * Returns the bounds for a sprite without a shape + */ + const Common::Rect getNoShapeBounds() const; + + /** + * Returns the old bounsd for the sprite from the previous frame + */ + const Common::Rect getOldBounds() const; + + /** + * Adjusts the frame and sequence variables of a sprite that corresponds to the current speaker + * so that it points to the beginning of the sequence number's talk sequence in the object's + * sequence buffer + * @param seq Which sequence to use (if there's more than 1) + * @remarks 1: First talk seq, 2: second talk seq, etc. + */ + virtual void setObjTalkSequence(int seq); +}; + +struct CAnim { + Common::String _name; // Name + Common::Point _position; // Position + int _dataSize; // Size of uncompressed animation data + uint32 _dataOffset; // offset within room file of animation data + int _flags; // Tells if can be walked behind + PositionFacing _goto[2]; // Position Holmes (and NPC in Rose Tattoo) should walk to before anim starts + PositionFacing _teleport[2]; // Location Holmes (and NPC) shoul teleport to after playing canim + + // Scalpel specific + byte _sequences[MAX_FRAME]; // Animation sequences + SpriteType _type; + + // Rose Tattoo specific + int _scaleVal; // How much the canim is scaled + + /** + * Load the data for the animation + */ + void load(Common::SeekableReadStream &s, bool isRoseTattoo, uint32 dataOffset); + void load3DO(Common::SeekableReadStream &s, uint32 dataOffset); +}; + +struct SceneImage { + ImageFile *_images; // Object images + int _maxFrames; // How many frames in object + int _filesize; // File size + + SceneImage(); +} ; + +} // End of namespace Sherlock + +#endif |