mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 11:51:52 +00:00
583 lines
16 KiB
C++
583 lines
16 KiB
C++
/* 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.
|
|
*
|
|
*
|
|
* Based on the original sources
|
|
* Faery Tale II -- The Halls of the Dead
|
|
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
|
|
*/
|
|
|
|
#ifndef SAGA2_CONTAIN_H
|
|
#define SAGA2_CONTAIN_H
|
|
|
|
#include "saga2/floating.h"
|
|
|
|
namespace Saga2 {
|
|
|
|
//DNode
|
|
// gPanel
|
|
// gControl
|
|
class ContainerView;
|
|
class ScrollingContainerView;
|
|
class ActorContainerView;
|
|
class ReadyContainerView;
|
|
class SmallContainerView;
|
|
class EnchantContainerView;
|
|
// gWindow
|
|
// DecoratedWindow
|
|
// FloatingWindow
|
|
class ContainerWindow;
|
|
class ContainerNode;
|
|
//DList
|
|
class ContainerList;
|
|
struct ContainerAppearanceDef;
|
|
|
|
class CMassWeightIndicator;
|
|
class ProtoObj;
|
|
|
|
class gCompButton;
|
|
class gCompImage;
|
|
class gMultCompButton;
|
|
class TilePoint;
|
|
|
|
/* ===================================================================== *
|
|
Class definitions
|
|
* ===================================================================== */
|
|
|
|
// The base class for all container panels
|
|
|
|
class ContainerView : public gControl {
|
|
|
|
friend class ContainerWindow;
|
|
friend class TangibleContainerWindow;
|
|
friend class IntangibleContainerWindow;
|
|
|
|
protected:
|
|
|
|
enum imageData {
|
|
selectorX = 10,
|
|
selectorY = 25,
|
|
};
|
|
|
|
public:
|
|
|
|
ContainerNode &node;
|
|
|
|
Point16 iconOrigin; // of the top left icon.
|
|
Point16 iconSpacing; // The spacing between icons (in both X and Y)
|
|
|
|
// The number of rows and columns of icons that can be seen
|
|
int16 visibleRows,
|
|
visibleCols;
|
|
|
|
// The total number of rows, and the scroll position of the control
|
|
int16 totalRows,
|
|
scrollPosition;
|
|
|
|
// Pointer to the object that this control is showing the
|
|
// contents of.
|
|
GameObject *containerObject;
|
|
|
|
// Mass and bulk indicators
|
|
int16 totalMass,
|
|
totalBulk;
|
|
|
|
// Number of visible objects currently in the container
|
|
int16 numObjects;
|
|
|
|
// These indicators are static
|
|
// becuase there is only one mouse cursor,
|
|
// and therefore only one set of information
|
|
// about the last place it's been anywhere on the game screen.
|
|
// ID of the last object the mouse was on
|
|
enum {
|
|
bufSize = 60,
|
|
accelSpeed = 8, // this tells the multi-item getting gadget how many items to grab per time unit
|
|
};
|
|
|
|
static ObjectID lastPickedObjectID;
|
|
|
|
// this will be used to hold a value of uint16 plus a -1 as a flag
|
|
static int32 lastPickedObjectQuantity;
|
|
|
|
// this will be used to determine if the cursor has been
|
|
// held over an object long enough to qualify for the hint to be displayed
|
|
static bool objTextAlarm;
|
|
|
|
// buffer for the mouse text
|
|
static char mouseText[bufSize];
|
|
|
|
// determines if the cursor is in *A* container view
|
|
static bool mouseInView;
|
|
|
|
// number of items to move for merged objects
|
|
static uint16 numPicked;
|
|
|
|
// merged object currently being gotten
|
|
static GameObject *objToGet;
|
|
|
|
static int32 amountAccumulator;
|
|
|
|
static int16 amountIndY;
|
|
|
|
// Constructor
|
|
ContainerView(
|
|
gPanelList &,
|
|
const Rect16 &,
|
|
ContainerNode &nd,
|
|
ContainerAppearanceDef &app,
|
|
AppFunc *cmd = NULL);
|
|
|
|
// Destructor
|
|
~ContainerView();
|
|
|
|
// redraw the panel offscreen
|
|
virtual void drawClipped(gPort &port, const Point16 &offset, const Rect16 &clip);
|
|
|
|
// draws the mereged object multi-item selector
|
|
void drawSelector(gPort &port, Point16 &pos);
|
|
|
|
// Draw the quantity indicator below the object if quantity > 1
|
|
void drawQuantity(gPort &port, GameObject *item, ProtoObj *objProto, int16 x, int16 y);
|
|
|
|
// returns true if the object is visible for this type of
|
|
// container.
|
|
virtual bool isVisible(GameObject *obj);
|
|
|
|
// total the mass, bulk, and number of all objects in container.
|
|
void totalObjects(void);
|
|
|
|
// Get the Nth visible object from this container.
|
|
ObjectID getObject(int16 slotNum);
|
|
|
|
void setContainer(GameObject *container);
|
|
|
|
// get the slot the point is over
|
|
TilePoint pickObjectSlot(const Point16 &pickPos);
|
|
|
|
// Get the object in a slot (u/v)
|
|
GameObject *getObject(const TilePoint &slot);
|
|
|
|
// Get the object that the point is over
|
|
GameObject *pickObject(const Point16 &pickPos);
|
|
|
|
// Get the object ID that the point is over
|
|
ObjectID pickObjectID(const Point16 &pickPos);
|
|
|
|
protected: // actions within a container
|
|
|
|
// These are the actions when there is no Item in the mouse
|
|
virtual void clickOn(gPanelMessage &msg, GameObject *mObj, GameObject *cObj);
|
|
virtual void dblClickOn(gPanelMessage &msg, GameObject *mObj, GameObject *cObj);
|
|
|
|
// this gets a merged item
|
|
void getMerged(GameObject *obj);
|
|
|
|
// drop Physical Object into container
|
|
virtual void dropPhysical(gPanelMessage &msg, GameObject *mObj, GameObject *cObj, int16 num = 1);
|
|
|
|
// Use Physical Object on other object in container
|
|
virtual void usePhysical(gPanelMessage &msg, GameObject *mObj, GameObject *cObj);
|
|
|
|
// Use Concept or Psycological object in container
|
|
// note: only valid container use is to drop into
|
|
// center characters's ready container.
|
|
virtual void useConcept(gPanelMessage &msg, GameObject *mObj, GameObject *cObj);
|
|
|
|
// Use Spell or Skill on other object in container or
|
|
// drop into center characters's ready container.
|
|
virtual void useSpell(gPanelMessage &msg, GameObject *mObj, GameObject *cObj);
|
|
|
|
// Event-handling functions
|
|
|
|
bool activate(gEventType why); // activate the control
|
|
void deactivate(void);
|
|
|
|
virtual void pointerMove(gPanelMessage &msg);
|
|
virtual bool pointerHit(gPanelMessage &msg);
|
|
virtual void pointerRelease(gPanelMessage &msg);
|
|
virtual void timerTick(gPanelMessage &msg);
|
|
|
|
void dblClick(GameObject *mouseObject, GameObject *slotObject, gPanelMessage &msg);
|
|
|
|
private:
|
|
// Container manipulation functions
|
|
void add(ObjectID newObj);
|
|
void remove(ObjectID obj);
|
|
void swap(ObjectID newObj, ObjectID oldObj);
|
|
|
|
// Determine if the mouse is pointing a new object, and if so,
|
|
// adjust the mouse text
|
|
void updateMouseText(Point16 &pickPos);
|
|
void setCursorText(GameObject *obj);
|
|
void setDelayedCursorText(GameObject *obj);
|
|
};
|
|
|
|
// sub class for ready inventory items
|
|
|
|
class ReadyContainerView : public ContainerView {
|
|
private:
|
|
void **backImages; // pointers to background imagery
|
|
int16 numIm;
|
|
|
|
public:
|
|
|
|
ReadyContainerView(gPanelList &,
|
|
const Rect16 &,
|
|
ContainerNode &,
|
|
void **backgrounds,
|
|
int16 numRes,
|
|
int16 numRows,
|
|
int16 numCols,
|
|
int16 totRows,
|
|
AppFunc *cmd);
|
|
|
|
// redraw the panel offscreen
|
|
virtual void drawClipped(gPort &port, const Point16 &offset, const Rect16 &clip);
|
|
|
|
void setScrollOffset(int8 num);
|
|
void timerTick(gPanelMessage &msg);
|
|
};
|
|
|
|
// sub class for enchantment container panels
|
|
|
|
class EnchantmentContainerView : public ContainerView {
|
|
public:
|
|
EnchantmentContainerView(gPanelList &list,
|
|
ContainerNode &nd,
|
|
ContainerAppearanceDef &app,
|
|
AppFunc *cmd = NULL);
|
|
|
|
virtual void pointerMove(gPanelMessage &msg);
|
|
virtual bool pointerHit(gPanelMessage &msg);
|
|
};
|
|
|
|
|
|
// The container window is simply a floating window with an embedded
|
|
// container view panel and a close button control
|
|
|
|
class ContainerWindow : public FloatingWindow {
|
|
protected:
|
|
gCompButton *closeCompButton; // the close button object
|
|
ContainerView *view; // the container view object
|
|
|
|
public:
|
|
ContainerWindow(ContainerNode &nd,
|
|
ContainerAppearanceDef &app,
|
|
const char saveas[]);
|
|
|
|
virtual ~ContainerWindow(void);
|
|
|
|
ContainerView &getView(void);
|
|
GameObject *containerObject(void) {
|
|
return getView().containerObject;
|
|
}
|
|
|
|
virtual void massBulkUpdate(void) {}
|
|
};
|
|
|
|
// Base class for all container windows with scroll control
|
|
class ScrollableContainerWindow : public ContainerWindow {
|
|
protected:
|
|
gCompButton *scrollCompButton;
|
|
|
|
public:
|
|
ScrollableContainerWindow(ContainerNode &nd,
|
|
ContainerAppearanceDef &app,
|
|
const char saveas[]);
|
|
|
|
void scrollUp(void) {
|
|
if (view->scrollPosition > 0) view->scrollPosition--;
|
|
}
|
|
|
|
void scrollDown(void) {
|
|
if (view->scrollPosition + view->visibleRows < view->totalRows)
|
|
view->scrollPosition++;
|
|
}
|
|
};
|
|
|
|
// A container window for tangible containers
|
|
class TangibleContainerWindow : public ScrollableContainerWindow {
|
|
private:
|
|
gCompImage *containerSpriteImg;
|
|
CMassWeightIndicator *massWeightIndicator;
|
|
|
|
Rect16 objRect;
|
|
bool deathFlag;
|
|
|
|
private:
|
|
void setContainerSprite(void);
|
|
|
|
public:
|
|
|
|
TangibleContainerWindow(ContainerNode &nd,
|
|
ContainerAppearanceDef &app);
|
|
~TangibleContainerWindow(void);
|
|
|
|
void drawClipped(gPort &port, const Point16 &offset, const Rect16 &clip);
|
|
|
|
// this sets the mass and bulk gauges for physical containers
|
|
void massBulkUpdate(void);
|
|
};
|
|
|
|
class IntangibleContainerWindow : public ScrollableContainerWindow {
|
|
protected:
|
|
friend void setMindContainer(int index, IntangibleContainerWindow &cw);
|
|
private:
|
|
gMultCompButton *mindSelectorCompButton;
|
|
|
|
public:
|
|
|
|
IntangibleContainerWindow(ContainerNode &nd, ContainerAppearanceDef &app);
|
|
};
|
|
|
|
class EnchantmentContainerWindow : public ContainerWindow {
|
|
protected:
|
|
gCompButton *scrollCompButton;
|
|
|
|
public:
|
|
EnchantmentContainerWindow(ContainerNode &nd,
|
|
ContainerAppearanceDef &app);
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
ContainerAppearanceDef: A record listing container appearance info
|
|
* ===================================================================== */
|
|
|
|
struct ContainerAppearanceDef {
|
|
Rect16 defaultWindowPos; // default position of window
|
|
Rect16 viewRect; // position of view within window
|
|
Rect16 closeRect, // position of close button
|
|
scrollRect, // position of scrolling button
|
|
iconRect, // position of container icon
|
|
massRect; // position of mass & bulk indicator
|
|
hResID closeResID[2], // resource ID's for close box
|
|
scrollResID[2]; // resource ID's for scroll indicator
|
|
Point16 iconOrigin,
|
|
iconSpacing;
|
|
uint16 rows,
|
|
cols,
|
|
totRows;
|
|
|
|
ContainerAppearanceDef(
|
|
Rect16 _defaultWindowPos,
|
|
Rect16 _viewRect,
|
|
Rect16 _closeRect,
|
|
Rect16 _scrollRect,
|
|
Rect16 _iconRect,
|
|
Rect16 _massRect,
|
|
hResID _closeResID_0,
|
|
hResID _closeResID_1,
|
|
hResID _scrollResID_0,
|
|
hResID _scrollResID_1,
|
|
Point16 _iconOrigin,
|
|
Point16 _iconSpacing,
|
|
uint16 _rows,
|
|
uint16 _cols,
|
|
uint16 _totRows)
|
|
: defaultWindowPos(_defaultWindowPos),
|
|
viewRect(_viewRect),
|
|
closeRect(_closeRect),
|
|
scrollRect(_scrollRect),
|
|
iconRect(_iconRect),
|
|
massRect(_massRect),
|
|
iconOrigin(_iconOrigin),
|
|
iconSpacing(_iconSpacing),
|
|
rows(_rows),
|
|
cols(_cols),
|
|
totRows(_totRows) {
|
|
closeResID[0] = _closeResID_0;
|
|
closeResID[1] = _closeResID_1;
|
|
scrollResID[0] = _scrollResID_0;
|
|
scrollResID[1] = _scrollResID_1;
|
|
}
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
ContainerNode: records the fact that a container was open for a
|
|
specific player
|
|
* ===================================================================== */
|
|
|
|
// ContainerNode records the fact that a container was opened for a
|
|
// specific player
|
|
|
|
// REM: What about the ordering of windows?
|
|
|
|
class ContainerNode : public DNode {
|
|
|
|
friend class ContainerList;
|
|
friend class ContainerView;
|
|
friend class ContainerWindow;
|
|
|
|
public:
|
|
enum ContainerNodeOwnerType {
|
|
readyType = 0, // This is a player ready container
|
|
deadType, // The "dead" container
|
|
mentalType, // A player's mental container
|
|
physicalType, // Physical container
|
|
enchantType // Enchantment container
|
|
};
|
|
|
|
enum ContainerNodeOwners {
|
|
nobody = 255 // owner = 255 means it's on the ground
|
|
};
|
|
|
|
enum containerAction {
|
|
actionUpdate = (1 << 0), // Refresh this window
|
|
actionDelete = (1 << 1), // Delete this window
|
|
actionHide = (1 << 2), // Refresh this window
|
|
actionShow = (1 << 3), // Refresh this window
|
|
};
|
|
|
|
private:
|
|
ObjectID object; // Object being viewed
|
|
uint8 type; // type of container
|
|
uint8 owner; // which brother owns this container
|
|
Rect16 position; // position of window
|
|
ContainerWindow *window; // window, which may be NULL if hidden.
|
|
uint8 action; // What action to take on container
|
|
public:
|
|
uint8 mindType; // mindContainer type
|
|
|
|
private:
|
|
// Nested structure used to archive ContainerNodes
|
|
struct Archive {
|
|
ObjectID object;
|
|
uint8 type;
|
|
uint8 owner;
|
|
Rect16 position;
|
|
uint8 mindType;
|
|
bool shown;
|
|
};
|
|
|
|
public:
|
|
ContainerNode(void) {}
|
|
ContainerNode(ContainerList &cl, ObjectID id, int type);
|
|
~ContainerNode();
|
|
|
|
static int32 archiveSize(void) {
|
|
return sizeof(Archive);
|
|
}
|
|
void *restore(void *buf);
|
|
void *archive(void *buf);
|
|
|
|
// Hide or show this container window.
|
|
void hide(void);
|
|
void show(void);
|
|
void update(void); // Update container associated with this node
|
|
|
|
// Set for lazy deletion
|
|
void markForDelete(void) {
|
|
action |= actionDelete;
|
|
}
|
|
void markForShow(void) {
|
|
action |= actionShow;
|
|
action &= ~actionHide;
|
|
}
|
|
void markForHide(void) {
|
|
action |= actionHide;
|
|
action &= ~actionShow;
|
|
}
|
|
void markForUpdate(void) {
|
|
action |= actionUpdate;
|
|
}
|
|
|
|
// Find the address of the window and/or view
|
|
ContainerWindow *getWindow(void);
|
|
ContainerView *getView(void);
|
|
|
|
// Access functions
|
|
uint8 getType(void) {
|
|
return type;
|
|
}
|
|
uint8 getOwnerIndex(void) {
|
|
return owner;
|
|
}
|
|
ObjectID getObject(void) {
|
|
return object;
|
|
}
|
|
Rect16 &getPosition(void) {
|
|
return position;
|
|
}
|
|
void setObject(ObjectID id) {
|
|
object = id;
|
|
}
|
|
|
|
// returns true if the object represented by the container can be
|
|
// accessed by the player.
|
|
bool isAccessable(ObjectID enactor);
|
|
|
|
void changeOwner(int16 newOwner);
|
|
};
|
|
|
|
// A list of container nodes
|
|
|
|
class ContainerList : public DList {
|
|
|
|
friend class ContainerNodeIterator;
|
|
|
|
public:
|
|
void add(ContainerNode &cn) {
|
|
addHead(cn);
|
|
}
|
|
void remove(ContainerNode &cn) {
|
|
cn.remove();
|
|
}
|
|
void moveToFront(ContainerNode &cn) {
|
|
cn.remove();
|
|
add(cn);
|
|
}
|
|
ContainerNode *find(ObjectID id);
|
|
ContainerNode *find(ObjectID id, int16 type);
|
|
|
|
// Set which player is viewing the container windows.
|
|
void setPlayerNum(PlayerActorID playerNum);
|
|
void doDeferredActions(void);
|
|
void setUpdate(ObjectID id);
|
|
};
|
|
|
|
extern ContainerList globalContainerList;
|
|
|
|
ContainerNode *CreateContainerNode(ObjectID id, bool open = true, int16 mindType = 0);
|
|
ContainerNode *CreateReadyContainerNode(PlayerActorID player);
|
|
ContainerNode *OpenMindContainer(PlayerActorID player, int16 open, int16 type);
|
|
|
|
/* ===================================================================== *
|
|
Exports
|
|
* ===================================================================== */
|
|
|
|
void initContainers(void);
|
|
void cleanupContainers(void);
|
|
|
|
void initContainerNodes(void);
|
|
void saveContainerNodes(SaveFileConstructor &saveGame);
|
|
void loadContainerNodes(SaveFileReader &saveGame);
|
|
void cleanupContainerNodes(void);
|
|
|
|
extern void updateContainerWindows(void);
|
|
|
|
extern APPFUNC(cmdCloseButtonFunc);
|
|
extern APPFUNC(cmdMindContainerFunc);
|
|
extern APPFUNC(cmdScrollFunc);
|
|
|
|
} // end of namespace Saga2
|
|
|
|
#endif
|