/* 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. * * $URL$ * $Id$ * */ #ifndef M4_MADS_VIEWS_H #define M4_MADS_VIEWS_H #include "m4/gui.h" #include "m4/viewmgr.h" #include "common/rect.h" #include "common/list.h" #include "common/ptr.h" namespace M4 { #define MADS_SURFACE_HEIGHT 156 #define MADS_SCREEN_HEIGHT 200 #define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2) class MadsView; enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2}; class MadsSpriteSlot { public: int spriteId; int timerIndex; int spriteListIndex; int frameNumber; int xp; int yp; int depth; int scale; MadsSpriteSlot() { } }; #define SPRITE_SLOTS_SIZE 50 typedef Common::Array > SpriteList; class MadsSpriteSlots { private: Common::Array _entries; SpriteList _sprites; public: int startIndex; MadsSpriteSlots(); MadsSpriteSlot &operator[](int idx) { assert(idx < SPRITE_SLOTS_SIZE); return _entries[idx]; } SpriteAsset &getSprite(int idx) { assert(idx < (int)_sprites.size()); return *_sprites[idx].get(); } int getIndex(); int addSprites(const char *resName); void clear() { startIndex = 0; _sprites.clear(); } void deleteTimer(int timerIndex); void draw(View *view); void cleanUp(); }; class MadsTextDisplayEntry { public: bool active; int expire; int spacing; Common::Rect bounds; uint8 colour1; uint8 colour2; Font *font; const char *msg; MadsTextDisplayEntry() { active = false; } }; #define TEXT_DISPLAY_SIZE 40 class MadsTextDisplay { private: Common::Array _entries; public: MadsTextDisplay(); MadsTextDisplayEntry &operator[](int idx) { assert(idx < TEXT_DISPLAY_SIZE); return _entries[idx]; } void expire(int idx) { assert(idx < TEXT_DISPLAY_SIZE); _entries[idx].expire = -1; } int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font); void clear(); void draw(View *view); void cleanUp(); }; #define TIMED_TEXT_SIZE 10 #define TEXT_4A_SIZE 30 enum KernelMessageFlags {KMSG_1 = 1, KMSG_2 = 2, KMSG_4 = 4, KMSG_8 = 8, KMSG_20 = 0x20, KMSG_40 = 0x40, KMSG_ACTIVE = 0x80}; class MadsKernelMessageListEntry { public: uint8 flags; int sequenceIndex; char asciiChar; char asciiChar2; int colour1; int colour2; Common::Point position; int textDisplayIndex; int msgOffset; int field_E; uint32 frameTimer2; uint32 frameTimer; uint32 timeout; bool field_1C; AbortTimerMode abortMode; uint16 actionNouns[3]; const char *msg; }; class MadsKernelMessageList { private: MadsView &_owner; Common::Array _entries; Font *_talkFont; public: MadsKernelMessageList(MadsView &owner); void clear(); int add(const Common::Point &pt, uint fontColour, uint8 flags, uint8 v2, uint32 timeout, const char *msg); int addQuote(int quoteId, int v2, uint32 timeout); void unk1(int msgIndex, int v1, int v2); void setSeqIndex(int msgIndex, int seqIndex); void remove(int msgIndex); void reset(); }; class ScreenObjectEntry { public: Common::Rect bounds; int category; int index; int layer; bool active; ScreenObjectEntry() { active = false; } }; class ScreenObjects { private: Common::Array _entries; public: ScreenObjects() {} ScreenObjectEntry &operator[](uint idx) { assert(idx <= _entries.size()); return _entries[idx - 1]; } void clear(); void add(const Common::Rect &bounds, int layer, int idx, int category); void draw(View *view); int scan(int xp, int yp, int layer); int scanBackwards(int xp, int yp, int layer); void setActive(int category, int idx, bool active); }; class DynamicHotspot { public: bool active; int timerIndex; Common::Rect bounds; Common::Point pos; int facing; int descId; int field_14; int articleNumber; int field_17; DynamicHotspot() { active = false; } }; #define DYNAMIC_HOTSPOTS_SIZE 8 class MadsDynamicHotspots { private: MadsView &_owner; Common::Array _entries; int _count; public: bool _flag; public: MadsDynamicHotspots(MadsView &owner); DynamicHotspot &operator[](uint idx) { return _entries[idx]; } int add(int descId, int field14, int timerIndex, const Common::Rect &bounds); int setPosition(int index, int xp, int yp, int facing); int set17(int index, int v); void remove(int index); void reset(); }; enum SpriteAnimType {ANIMTYPE_SINGLE_DIRECTION = 1, ANIMTYPE_CYCLED = 2}; enum SequenceSubEntryMode {SM_0 = 0, SM_1 = 1, SM_FRAME_INDEX = 2}; #define TIMER_ENTRY_SUBSET_MAX 5 struct MadsSequenceSubEntries { int count; SequenceSubEntryMode mode[TIMER_ENTRY_SUBSET_MAX]; int16 frameIndex[TIMER_ENTRY_SUBSET_MAX]; int8 abortVal[TIMER_ENTRY_SUBSET_MAX]; }; struct MadsSequenceEntry { int8 active; int8 spriteListIndex; int field_2; int frameIndex; int frameStart; int numSprites; SpriteAnimType animType; int frameInc; int depth; int scale; int dynamicHotspotIndex; int field_12; int field_13; int width; int height; int field_24; int field_25; MadsSequenceSubEntries entries; AbortTimerMode abortMode; uint16 actionNouns[3]; int numTicks; int extraTicks; uint32 timeout; }; #define TIMER_LIST_SIZE 30 class MadsSequenceList { private: MadsView &_owner; Common::Array _entries; public: MadsSequenceList(MadsView &owner); MadsSequenceEntry &operator[](int index) { return _entries[index]; } void clear(); bool addSubEntry(int index, SequenceSubEntryMode mode, int frameIndex, int abortVal); int add(int spriteListIndex, int v0, int v1, char field_24, int timeoutTicks, int extraTicks, int numTicks, int height, int width, char field_12, char scale, uint8 depth, int frameInc, SpriteAnimType animType, int numSprites, int frameStart); void remove(int timerIndex); void setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot); bool loadSprites(int timerIndex); void tick(); void delay(uint32 v1, uint32 v2); }; class MadsView { private: View *_view; public: MadsSpriteSlots _spriteSlots; MadsTextDisplay _textDisplay; MadsKernelMessageList _kernelMessages; ScreenObjects _screenObjects; MadsDynamicHotspots _dynamicHotspots; MadsSequenceList _sequenceList; int _textSpacing; int _ticksAmount; uint32 _newTimeout; int _abortTimers; int8 _abortTimers2; AbortTimerMode _abortTimersMode; AbortTimerMode _abortTimersMode2; public: MadsView(View *view); void refresh(); }; #define CHEAT_SEQUENCE_MAX 8 class IntegerList : public Common::Array { public: int indexOf(int v) { for (uint i = 0; i < size(); ++i) if (operator [](i) == v) return i; return -1; } }; enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED}; enum InterfaceObjects {ACTIONS_START = 0, SCROLL_UP = 10, SCROLL_SCROLLER = 11, SCROLL_DOWN = 12, INVLIST_START = 13, VOCAB_START = 18}; class MadsInterfaceView : public GameInterfaceView { private: IntegerList _inventoryList; RectList _screenObjects; int _highlightedElement; int _topIndex; uint32 _nextScrollerTicks; int _cheatKeyCtr; // Object display fields int _selectedObject; SpriteAsset *_objectSprites; RGBList *_objectPalData; int _objectFrameNumber; void setFontMode(InterfaceFontMode newMode); bool handleCheatKey(int32 keycode); bool handleKeypress(int32 keycode); void leaveScene(); public: MadsInterfaceView(MadsM4Engine *vm); ~MadsInterfaceView(); virtual void initialise(); virtual void setSelectedObject(int objectNumber); virtual void addObjectToInventory(int objectNumber); int getSelectedObject() { return _selectedObject; } int getInventoryObject(int objectIndex) { return _inventoryList[objectIndex]; } void onRefresh(RectList *rects, M4Surface *destSurface); bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); }; } #endif