mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 17:29:39 +00:00
055231181e
svn-id: r16515
795 lines
19 KiB
C++
795 lines
19 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2004-2005 The ScummVM project
|
|
*
|
|
* The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*
|
|
*/
|
|
|
|
// Game interface module
|
|
#include "saga/saga.h"
|
|
|
|
#include "saga/gfx.h"
|
|
#include "saga/actor.h"
|
|
#include "saga/console.h"
|
|
#include "saga/font.h"
|
|
#include "saga/objectmap.h"
|
|
#include "saga/objectdata.h"
|
|
#include "saga/rscfile_mod.h"
|
|
#include "saga/scene.h"
|
|
#include "saga/script.h"
|
|
#include "saga/sprite.h"
|
|
|
|
#include "saga/interface.h"
|
|
|
|
namespace Saga {
|
|
|
|
static VERB_DATA I_VerbData[] = {
|
|
{I_VERB_WALKTO, "verb_walkto", "Walk to", kVerbWalkTo},
|
|
{I_VERB_LOOKAT, "verb_lookat", "Look at", kVerbLookAt},
|
|
{I_VERB_PICKUP, "verb_pickup", "Pick up", kVerbPickup},
|
|
{I_VERB_TALKTO, "verb_talkto", "Talk to", kVerbSpeakTo},
|
|
{I_VERB_OPEN, "verb_open", "Open", kVerbOpen},
|
|
{I_VERB_CLOSE, "verb_close", "Close", kVerbClose},
|
|
{I_VERB_USE, "verb_use", "Use", kVerbUse},
|
|
{I_VERB_GIVE, "verb_give", "Give", kVerbGive}
|
|
};
|
|
|
|
static INTERFACE_DESC ITE_interface = {
|
|
ITE_STATUS_Y,
|
|
ITE_STATUS_W,
|
|
ITE_STATUS_H,
|
|
ITE_STATUS_TEXT_Y,
|
|
ITE_STATUS_TXTCOL,
|
|
ITE_STATUS_BGCOL,
|
|
|
|
ITE_CMD_TEXT_COL,
|
|
ITE_CMD_TEXT_SHADOWCOL,
|
|
ITE_CMD_TEXT_HILITECOL,
|
|
|
|
COMMAND_DEFAULT_BUTTON,
|
|
|
|
ITE_LPORTRAIT_X,
|
|
ITE_LPORTRAIT_Y,
|
|
ITE_RPORTRAIT_X,
|
|
ITE_RPORTRAIT_Y,
|
|
|
|
ITE_INVENTORY_XSTART,
|
|
ITE_INVENTORY_YSTART,
|
|
ITE_INVENTORY_ROWS,
|
|
ITE_INVENTORY_COLUMNS,
|
|
ITE_INVENTORY_ICON_WIDTH,
|
|
ITE_INVENTORY_ICON_HEIGHT,
|
|
ITE_INVENTORY_ICON_XOFFSET,
|
|
ITE_INVENTORY_ICON_YOFFSET,
|
|
ITE_INVENTORY_XSPACING,
|
|
ITE_INVENTORY_YSPACING
|
|
};
|
|
|
|
static InterfaceButton ITEMainPanel[] = {
|
|
{5, 4, 46, 47, "Portrait", 0, 0, BUTTON_NONE, 0}, //TODO: remove?
|
|
// "Walk To" and "Talk To" share button sprites
|
|
{52, 4, 109, 14, "Walk To", 1, 2, BUTTON_VERB, I_VERB_WALKTO},
|
|
{52, 15, 109, 25, "Look At", 3, 4, BUTTON_VERB, I_VERB_LOOKAT},
|
|
{52, 26, 109, 36, "Pick Up", 5, 6, BUTTON_VERB, I_VERB_PICKUP},
|
|
{52, 37, 109, 47, "Talk To", 1, 2, BUTTON_VERB, I_VERB_TALKTO},
|
|
{110, 4, 166, 14, "Open", 7, 8, BUTTON_VERB, I_VERB_OPEN},
|
|
{110, 15, 166, 25, "Close", 9, 10, BUTTON_VERB, I_VERB_CLOSE},
|
|
{110, 26, 166, 36, "Use", 11, 12, BUTTON_VERB, I_VERB_USE},
|
|
{110, 37, 166, 47, "Give", 13, 14, BUTTON_VERB, I_VERB_GIVE},
|
|
|
|
{181, 6, 206, 24, "Inv1", 0, 0, BUTTON_NONE, 0},
|
|
{213, 6, 240, 24, "Inv2", 0, 0, BUTTON_NONE, 0},
|
|
{245, 6, 272, 24, "Inv3", 0, 0, BUTTON_NONE, 0},
|
|
{277, 6, 304, 24, "Inv4", 0, 0, BUTTON_NONE, 0},
|
|
{181, 27, 208, 45, "Inv5", 0, 0, BUTTON_NONE, 0},
|
|
{213, 27, 240, 45, "Inv6", 0, 0, BUTTON_NONE, 0},
|
|
{245, 27, 272, 45, "Inv7", 0, 0, BUTTON_NONE, 0},
|
|
{277, 27, 304, 45, "Inv8", 0, 0, BUTTON_NONE, 0},
|
|
{306, 6, 314, 11, "InvUp", 0, 0, BUTTON_NONE, 0},
|
|
{306, 41, 314, 45, "InvDown", 0, 0, BUTTON_NONE, 0}
|
|
};
|
|
|
|
static INTERFACE_DESC IHNM_interface = {
|
|
IHNM_STATUS_Y,
|
|
IHNM_STATUS_W,
|
|
IHNM_STATUS_H,
|
|
IHNM_STATUS_TEXT_Y,
|
|
IHNM_STATUS_TXTCOL,
|
|
IHNM_STATUS_BGCOL,
|
|
|
|
IHNM_CMD_TEXT_COL,
|
|
IHNM_CMD_TEXT_SHADOWCOL,
|
|
IHNM_CMD_TEXT_HILITECOL,
|
|
|
|
COMMAND_DEFAULT_BUTTON,
|
|
|
|
IHNM_LPORTRAIT_X,
|
|
IHNM_LPORTRAIT_Y,
|
|
IHNM_RPORTRAIT_X,
|
|
IHNM_RPORTRAIT_Y,
|
|
|
|
IHNM_INVENTORY_XSTART,
|
|
IHNM_INVENTORY_YSTART,
|
|
IHNM_INVENTORY_ROWS,
|
|
IHNM_INVENTORY_COLUMNS,
|
|
IHNM_INVENTORY_ICON_WIDTH,
|
|
IHNM_INVENTORY_ICON_HEIGHT,
|
|
IHNM_INVENTORY_ICON_XOFFSET,
|
|
IHNM_INVENTORY_ICON_YOFFSET,
|
|
IHNM_INVENTORY_XSPACING,
|
|
IHNM_INVENTORY_YSPACING
|
|
};
|
|
|
|
static InterfaceButton IHNMMainPanel[] = {
|
|
{5, 4, 46, 47, "Portrait", 0, 0, 0, 0}
|
|
};
|
|
|
|
int Interface::registerLang(void) {
|
|
#if 0
|
|
size_t i;
|
|
|
|
for (i = 0; i < ARRAYSIZE(I_VerbData); i++) {
|
|
if (CVAR_Register_S(I_VerbData[i].verb_str,
|
|
I_VerbData[i].verb_cvar,
|
|
NULL, CVAR_CFG, VERB_STRLIMIT) != SUCCESS) {
|
|
|
|
return FAILURE;
|
|
}
|
|
|
|
assert(CVAR_Find(I_VerbData[i].verb_cvar) != NULL);
|
|
}
|
|
#endif
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
|
int result;
|
|
|
|
if (_initialized) {
|
|
return;
|
|
}
|
|
|
|
_iThread = _vm->_script->SThreadCreate();
|
|
if (_iThread == NULL) {
|
|
warning("Interface::Interface(): Error creating script thread for game interface module");
|
|
return;
|
|
}
|
|
|
|
// Load interface module resource file context
|
|
_interfaceContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
|
if (_interfaceContext == NULL) {
|
|
return;
|
|
}
|
|
|
|
// Initialize interface data by game type
|
|
if (_vm->_gameType == GType_ITE) {
|
|
// Load Inherit the Earth interface desc
|
|
_mainPanel.buttons = ITEMainPanel;
|
|
_mainPanel.nbuttons = ARRAYSIZE(ITEMainPanel);
|
|
|
|
_iDesc = ITE_interface;
|
|
} else if (_vm->_gameType == GType_IHNM) {
|
|
// Load I Have No Mouth interface desc
|
|
_mainPanel.buttons = IHNMMainPanel;
|
|
_mainPanel.nbuttons = ARRAYSIZE(IHNMMainPanel);
|
|
_iDesc = IHNM_interface;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
// Load command panel resource
|
|
result = RSC_LoadResource(_interfaceContext, _vm->getResourceDescription()->command_panel_rn, &_mainPanel.res, &_mainPanel.res_len);
|
|
if (result != SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
// Load dialogue panel resource
|
|
result = RSC_LoadResource(_interfaceContext, _vm->getResourceDescription()->dialogue_panel_rn, &_conversePanel.res, &_conversePanel.res_len);
|
|
if (result != SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
if (_vm->_sprite->loadList(RID_ITE_COMMAND_BUTTONSPRITES, _mainPanel.sprites) != SUCCESS) {
|
|
error("Unable to load sprite list");
|
|
}
|
|
|
|
|
|
if (_vm->_sprite->loadList(RID_ITE_DEFAULT_PORTRAITS, _defPortraits) != SUCCESS) {
|
|
error("Unable to load sprite list");
|
|
}
|
|
|
|
|
|
_vm->decodeBGImage(_mainPanel.res, _mainPanel.res_len, &_mainPanel.img,
|
|
&_mainPanel.img_len, &_mainPanel.img_w, &_mainPanel.img_h);
|
|
|
|
_vm->decodeBGImage(_conversePanel.res, _conversePanel.res_len,
|
|
&_conversePanel.img, &_conversePanel.img_len,
|
|
&_conversePanel.img_w, &_conversePanel.img_h);
|
|
|
|
_mainPanel.x = 0;
|
|
_mainPanel.y = 149;
|
|
|
|
_conversePanel.x = 0;
|
|
_conversePanel.y = 149;
|
|
|
|
_mainPanel.set_button = COMMAND_DEFAULT_BUTTON;
|
|
_leftPortrait = 0;
|
|
_rightPortrait = 0;
|
|
|
|
_activeVerb = I_VERB_WALKTO;
|
|
|
|
_active = false;
|
|
_panelMode = _lockedMode = kPanelNull;
|
|
_savedMode = -1;
|
|
_inMainMode = false;
|
|
*_statusText = 0;
|
|
|
|
_inventoryCount = 0;
|
|
_inventorySize = ITE_INVENTORY_SIZE;
|
|
|
|
_inventory = (uint16 *)calloc(_inventorySize, sizeof(uint16));
|
|
if (_inventory == NULL) {
|
|
return;
|
|
}
|
|
|
|
_initialized = true;
|
|
}
|
|
|
|
Interface::~Interface(void) {
|
|
free(_inventory);
|
|
|
|
_mainPanel.sprites.freeMem();
|
|
_defPortraits.freeMem();
|
|
_scenePortraits.freeMem();
|
|
_initialized = false;
|
|
}
|
|
|
|
int Interface::activate() {
|
|
if (!_active) {
|
|
_active = true;
|
|
_vm->_script->_skipSpeeches = false;
|
|
_vm->_gfx->showCursor(true);
|
|
unlockMode();
|
|
if (_panelMode == kPanelMain)
|
|
;// show save reminder
|
|
draw();
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::deactivate() {
|
|
if (_active) {
|
|
_active = false;
|
|
_vm->_gfx->showCursor(false);
|
|
lockMode();
|
|
setMode(kPanelNull);
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
void Interface::rememberMode() {
|
|
assert (_savedMode == -1);
|
|
|
|
_savedMode = _panelMode;
|
|
}
|
|
|
|
void Interface::restoreMode() {
|
|
assert (_savedMode != -1);
|
|
|
|
_panelMode = _savedMode;
|
|
_savedMode = -1;
|
|
|
|
draw();
|
|
}
|
|
|
|
int Interface::setMode(int mode, bool force) {
|
|
// TODO: Is this where we should hide/show the mouse cursor?
|
|
int newMode = mode;
|
|
|
|
if (mode == kPanelConverse) {
|
|
_inMainMode = false;
|
|
} else {
|
|
if (mode == kPanelInventory) {
|
|
_inMainMode = true;
|
|
newMode = kPanelMain;
|
|
}
|
|
}
|
|
|
|
// This lets us to prevents actors to pop up during initial
|
|
// scene fade in.
|
|
if (_savedMode != -1 && !force) {
|
|
_savedMode = newMode;
|
|
debug(0, "Saved mode: %d. my mode is %d", newMode, _panelMode);
|
|
}
|
|
else
|
|
_panelMode = newMode;
|
|
|
|
draw();
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::setStatusText(const char *new_txt) {
|
|
assert(new_txt != NULL);
|
|
|
|
strncpy(_statusText, new_txt, STATUS_TEXT_LEN);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::loadScenePortraits(int resourceId) {
|
|
_scenePortraits.freeMem();
|
|
|
|
return _vm->_sprite->loadList(resourceId, _scenePortraits);
|
|
}
|
|
|
|
int Interface::setLeftPortrait(int portrait) {
|
|
_leftPortrait = portrait;
|
|
draw();
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::setRightPortrait(int portrait) {
|
|
_rightPortrait = portrait;
|
|
draw();
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::draw() {
|
|
SURFACE *backBuffer;
|
|
|
|
Point base;
|
|
Point leftPortraitPoint;
|
|
Point rightPortraitPoint;
|
|
Point origin;
|
|
|
|
backBuffer = _vm->_gfx->getBackBuffer();
|
|
|
|
if (_vm->_scene->isInDemo() || _panelMode == kPanelFade)
|
|
return SUCCESS;
|
|
|
|
|
|
drawStatusBar(backBuffer);
|
|
|
|
if (_panelMode == kPanelMain) {
|
|
base.x = _mainPanel.x;
|
|
base.y = _mainPanel.y;
|
|
|
|
origin.x = 0;
|
|
origin.y = _vm->getDisplayHeight() - _mainPanel.img_h;
|
|
|
|
bufToSurface(backBuffer, _mainPanel.img, _mainPanel.img_w, _mainPanel.img_h, NULL, &origin);
|
|
|
|
} else {
|
|
base.x = _conversePanel.x;
|
|
base.y = _conversePanel.y;
|
|
|
|
origin.x = 0;
|
|
origin.y = _vm->getDisplayHeight() - _mainPanel.img_h;
|
|
|
|
bufToSurface(backBuffer, _conversePanel.img, _conversePanel.img_w,
|
|
_conversePanel.img_h, NULL, &origin);
|
|
}
|
|
|
|
if (_panelMode == kPanelMain || _panelMode == kPanelConverse ||
|
|
_lockedMode == kPanelMain || _lockedMode == kPanelConverse) {
|
|
leftPortraitPoint.x = base.x + _iDesc.lportrait_x;
|
|
leftPortraitPoint.y = base.y + _iDesc.lportrait_y;
|
|
_vm->_sprite->draw(backBuffer, _defPortraits, _leftPortrait, leftPortraitPoint, 256);
|
|
}
|
|
|
|
|
|
if (!_inMainMode && _iDesc.rportrait_x >= 0) {
|
|
rightPortraitPoint.x = base.x + _iDesc.rportrait_x;
|
|
rightPortraitPoint.y = base.y + _iDesc.rportrait_y;
|
|
|
|
_vm->_sprite->draw(backBuffer, _scenePortraits, _rightPortrait, rightPortraitPoint, 256);
|
|
}
|
|
|
|
if (_inMainMode) {
|
|
drawInventory();
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::update(const Point& imousePt, int update_flag) {
|
|
SURFACE *back_buf;
|
|
|
|
int imouse_x, imouse_y;
|
|
|
|
if (_vm->_scene->isInDemo() || _panelMode == kPanelFade)
|
|
return SUCCESS;
|
|
|
|
imouse_x = imousePt.x;
|
|
imouse_y = imousePt.y;
|
|
|
|
back_buf = _vm->_gfx->getBackBuffer();
|
|
|
|
|
|
if (_panelMode == kPanelMain) { // FIXME: HACK
|
|
// Update playfield space ( only if cursor is inside )
|
|
if (imouse_y < _vm->getStatusYOffset()) {
|
|
// Mouse is in playfield space
|
|
if (update_flag == UPDATE_MOUSEMOVE) {
|
|
handlePlayfieldUpdate(back_buf, imousePt);
|
|
} else if (update_flag == UPDATE_MOUSECLICK) {
|
|
handlePlayfieldClick(back_buf, imousePt);
|
|
}
|
|
}
|
|
|
|
// Update command space
|
|
if (update_flag == UPDATE_MOUSEMOVE) {
|
|
handleCommandUpdate(back_buf, imousePt);
|
|
} else if (update_flag == UPDATE_MOUSECLICK) {
|
|
handleCommandClick(back_buf, imousePt);
|
|
}
|
|
}
|
|
|
|
drawStatusBar(back_buf);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::drawStatusBar(SURFACE *ds) {
|
|
Rect rect;
|
|
|
|
int string_w;
|
|
|
|
// Disable this for IHNM for now, since that game uses the full screen
|
|
// in some cases.
|
|
|
|
if (_vm->_gameType == GType_IHNM) {
|
|
return SUCCESS;
|
|
}
|
|
|
|
|
|
// Erase background of status bar
|
|
rect.left = 0;
|
|
rect.top = _iDesc.status_y;
|
|
rect.right = _vm->getDisplayWidth();
|
|
rect.bottom = _iDesc.status_y + _iDesc.status_h;
|
|
|
|
drawRect(ds, &rect, _iDesc.status_bgcol);
|
|
|
|
string_w = _vm->_font->getStringWidth(SMALL_FONT_ID, _statusText, 0, 0);
|
|
|
|
_vm->_font->draw(SMALL_FONT_ID, ds, _statusText, 0, (_iDesc.status_w / 2) - (string_w / 2),
|
|
_iDesc.status_y + _iDesc.status_txt_y, _iDesc.status_txt_col, 0, 0);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::handleCommandClick(SURFACE *ds, const Point& imousePt) {
|
|
int hit_button;
|
|
int ibutton_num;
|
|
|
|
int x_base;
|
|
int y_base;
|
|
|
|
Point button;
|
|
|
|
int old_set_button;
|
|
int set_button;
|
|
|
|
hit_button = hitTest(imousePt, &ibutton_num);
|
|
if (hit_button != SUCCESS) {
|
|
// Clicking somewhere other than a button doesn't do anything
|
|
return SUCCESS;
|
|
}
|
|
|
|
x_base = _mainPanel.x;
|
|
y_base = _mainPanel.y;
|
|
|
|
if (_mainPanel.buttons[ibutton_num].flags & BUTTON_SET) {
|
|
old_set_button = _mainPanel.set_button;
|
|
set_button = ibutton_num;
|
|
_mainPanel.set_button = set_button;
|
|
|
|
if (_mainPanel.buttons[set_button].flags & BUTTON_VERB) {
|
|
_activeVerb = _mainPanel.buttons[ibutton_num].data;
|
|
}
|
|
|
|
if (_mainPanel.buttons[set_button].flags & BUTTON_BITMAP) {
|
|
button.x = x_base + _mainPanel.buttons[set_button].x1;
|
|
button.y = y_base + _mainPanel.buttons[set_button].y1;
|
|
|
|
_vm->_sprite->draw(ds, _mainPanel.sprites, _mainPanel.buttons[set_button].
|
|
active_sprite - 1, button, 256);
|
|
}
|
|
|
|
if (_mainPanel.buttons[old_set_button].flags & BUTTON_BITMAP) {
|
|
button.x = x_base + _mainPanel.buttons[old_set_button].x1;
|
|
button.y = y_base + _mainPanel.buttons[old_set_button].y1;
|
|
|
|
_vm->_sprite->draw(ds, _mainPanel.sprites, _mainPanel.buttons[old_set_button].
|
|
inactive_sprite - 1, button, 256);
|
|
}
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::handleCommandUpdate(SURFACE *ds, const Point& imousePt) {
|
|
int hit_button;
|
|
int ibutton_num;
|
|
|
|
// int button_w = 0;
|
|
|
|
/* int verb_idx = 0;
|
|
int string_w = 0;
|
|
int color;
|
|
int i;*/
|
|
|
|
hit_button = inventoryTest(imousePt, &ibutton_num);
|
|
|
|
if (hit_button == SUCCESS) {
|
|
// Hovering over an inventory object
|
|
return SUCCESS;
|
|
}
|
|
|
|
/* hit_button = hitTest(imousePt, &ibutton_num);
|
|
|
|
if (hit_button == SUCCESS) {
|
|
// Hovering over a command panel button
|
|
setStatusText(I_VerbData[_activeVerb].verb_str);
|
|
}
|
|
|
|
for (i = 0; i < _mainPanel.nbuttons; i++) {
|
|
if (!(_mainPanel.buttons[i].flags & BUTTON_LABEL)) {
|
|
continue;
|
|
}
|
|
|
|
button_w = _mainPanel.buttons[i].x2 - _mainPanel.buttons[i].x1;
|
|
|
|
verb_idx = _mainPanel.buttons[i].data;
|
|
|
|
string_w = _vm->_font->getStringWidth(SMALL_FONT_ID, I_VerbData[verb_idx].verb_str, 0, 0);
|
|
|
|
if (i == hit_button) {
|
|
color = _iDesc.cmd_txt_hilitecol;
|
|
} else {
|
|
color = _iDesc.cmd_txt_col;
|
|
}
|
|
|
|
button.x = _mainPanel.x + _mainPanel.buttons[i].x1;
|
|
button.y = _mainPanel.y + _mainPanel.buttons[i].y1;
|
|
|
|
_vm->_font->draw(SMALL_FONT_ID, ds, I_VerbData[verb_idx].verb_str, 0,
|
|
button.x + ((button_w / 2) - (string_w / 2)), button.y + 1,
|
|
color, _iDesc.cmd_txt_shadowcol, FONT_SHADOW);
|
|
|
|
if ((i == _mainPanel.set_button) && (_mainPanel.buttons[i].flags & BUTTON_BITMAP)) {
|
|
_vm->_sprite->draw(ds, _mainPanel.sprites, _mainPanel.buttons[i].active_sprite - 1,
|
|
button, 256);
|
|
}
|
|
}
|
|
*/
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::handlePlayfieldClick(SURFACE *ds, const Point& imousePt) {
|
|
// return SUCCESS;
|
|
|
|
int objectNum;
|
|
uint16 object_flags = 0;
|
|
|
|
int script_num;
|
|
ActorLocation location;
|
|
|
|
objectNum = _vm->_scene->_objectMap->hitTest(imousePt);
|
|
|
|
if (objectNum == -1) {
|
|
// Player clicked on empty spot - walk here regardless of verb
|
|
location.fromScreenPoint(imousePt);
|
|
|
|
_vm->_actor->actorWalkTo(ID_PROTAG, location);
|
|
return SUCCESS;
|
|
}
|
|
|
|
object_flags = _vm->_scene->_objectMap->getFlags(objectNum);
|
|
|
|
if (object_flags & kHitZoneExit) { // FIXME. This is wrong
|
|
if ((script_num = _vm->_scene->_objectMap->getEPNum(objectNum)) != -1) {
|
|
// Set active verb in script module
|
|
_vm->_script->putWord(4, 4, I_VerbData[_activeVerb].s_verb);
|
|
|
|
// Execute object script if present
|
|
if (script_num != 0) {
|
|
_vm->_script->SThreadExecute(_iThread, script_num);
|
|
}
|
|
}
|
|
} else {
|
|
// Not a normal scene object - walk to it as if it weren't there
|
|
location.fromScreenPoint(imousePt);
|
|
|
|
_vm->_actor->actorWalkTo(ID_PROTAG, location);
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::handlePlayfieldUpdate(SURFACE *ds, const Point& imousePt) {
|
|
return SUCCESS;
|
|
/*
|
|
const char *object_name;
|
|
int objectNum;
|
|
uint16 object_flags = 0;
|
|
|
|
char new_status[STATUS_TEXT_LEN];
|
|
|
|
new_status[0] = 0;
|
|
|
|
objectNum = _vm->_scene->_objectMap->hitTest(imousePt);
|
|
|
|
if (objectNum == -1) {
|
|
// Cursor over nothing - just display current verb
|
|
setStatusText(I_VerbData[_activeVerb].verb_str);
|
|
return SUCCESS;
|
|
}
|
|
|
|
object_flags = _vm->_scene->_objectMap->getFlags(objectNum);
|
|
object_name = _vm->_scene->_objectMap->getName(objectNum);
|
|
|
|
if (object_flags & OBJECT_EXIT) { // FIXME. This is wrong
|
|
// Normal scene object - display as subject of verb
|
|
snprintf(new_status, STATUS_TEXT_LEN, "%s %s", I_VerbData[_activeVerb].verb_str, object_name);
|
|
} else {
|
|
// Not normal scene object - override verb as we can only
|
|
// walk to this object
|
|
snprintf(new_status, STATUS_TEXT_LEN, "%s %s", I_VerbData[I_VERB_WALKTO].verb_str, object_name);
|
|
}
|
|
|
|
setStatusText(new_status);
|
|
|
|
return SUCCESS;
|
|
*/
|
|
}
|
|
|
|
int Interface::hitTest(const Point& imousePt, int *ibutton) {
|
|
InterfaceButton *buttons;
|
|
|
|
int nbuttons;
|
|
int xbase;
|
|
int ybase;
|
|
|
|
int i;
|
|
|
|
buttons = _mainPanel.buttons;
|
|
nbuttons = _mainPanel.nbuttons;
|
|
|
|
xbase = _mainPanel.x;
|
|
ybase = _mainPanel.y;
|
|
|
|
for (i = 0; i < nbuttons; i++) {
|
|
if ((imousePt.x >= (xbase + buttons[i].x1)) && (imousePt.x < (xbase + buttons[i].x2)) &&
|
|
(imousePt.y >= (ybase + buttons[i].y1)) && (imousePt.y < (ybase + buttons[i].y2))) {
|
|
*ibutton = i;
|
|
return SUCCESS;
|
|
}
|
|
}
|
|
|
|
*ibutton = -1;
|
|
return FAILURE;
|
|
}
|
|
|
|
void Interface::addToInventory(int sprite) {
|
|
if (_inventoryCount < _inventorySize) {
|
|
for (int i = _inventoryCount; i > 0; i--) {
|
|
_inventory[i] = _inventory[i - 1];
|
|
}
|
|
|
|
_inventory[0] = sprite;
|
|
_inventoryCount++;
|
|
draw();
|
|
}
|
|
}
|
|
|
|
void Interface::removeFromInventory(int sprite) {
|
|
for (int i = 0; i < _inventoryCount; i++) {
|
|
if (_inventory[i] == sprite) {
|
|
int j;
|
|
|
|
for (j = i; i < _inventoryCount; j++) {
|
|
_inventory[j] = _inventory[j + 1];
|
|
}
|
|
|
|
_inventory[j] = 0;
|
|
_inventoryCount--;
|
|
draw();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Interface::drawInventory() {
|
|
if (_panelMode != kPanelMain)
|
|
return;
|
|
|
|
SURFACE *back_buf = _vm->_gfx->getBackBuffer();
|
|
|
|
// TODO: Inventory scrolling
|
|
|
|
int row = 0;
|
|
int col = 0;
|
|
|
|
int x = _iDesc.inv_xstart + _iDesc.inv_icon_xoffset;
|
|
int y = _iDesc.inv_ystart + _iDesc.inv_icon_yoffset;
|
|
int width = _iDesc.inv_icon_width + _iDesc.inv_xspacing;
|
|
int height = _iDesc.inv_icon_height + _iDesc.inv_yspacing;
|
|
Point drawPoint;
|
|
|
|
for (int i = 0; i < _inventoryCount; i++) {
|
|
if (_inventory[i] >= ARRAYSIZE(ObjectTable)) {
|
|
continue;
|
|
}
|
|
drawPoint.x = x + col * width;
|
|
drawPoint.y = y + row * height;
|
|
|
|
_vm->_sprite->draw(back_buf, _vm->_sprite->_mainSprites,
|
|
ObjectTable[_inventory[i]].spritelistRn,
|
|
drawPoint, 256);
|
|
|
|
if (++col >= _iDesc.inv_columns) {
|
|
if (++row >= _iDesc.inv_rows) {
|
|
break;
|
|
}
|
|
col = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int Interface::inventoryTest(const Point& imousePt, int *ibutton) {
|
|
int row = 0;
|
|
int col = 0;
|
|
|
|
int xbase = _iDesc.inv_xstart;
|
|
int ybase = _iDesc.inv_ystart;
|
|
int width = _iDesc.inv_icon_width + _iDesc.inv_xspacing;
|
|
int height = _iDesc.inv_icon_height + _iDesc.inv_yspacing;
|
|
|
|
for (int i = 0; i < _inventoryCount; i++) {
|
|
int x = xbase + col * width;
|
|
int y = ybase + row * height;
|
|
|
|
if (imousePt.x >= x && imousePt.x < x + _iDesc.inv_icon_width && imousePt.y >= y && imousePt.y < y + _iDesc.inv_icon_height) {
|
|
*ibutton = i;
|
|
return SUCCESS;
|
|
}
|
|
|
|
if (++col >= _iDesc.inv_columns) {
|
|
if (++row >= _iDesc.inv_rows) {
|
|
break;
|
|
}
|
|
col = 0;
|
|
}
|
|
}
|
|
|
|
return FAILURE;
|
|
}
|
|
|
|
void Interface::drawVerb(int verb, int state) {
|
|
}
|
|
|
|
} // End of namespace Saga
|