scummvm/engines/chewy/menus.cpp
2022-07-07 13:06:22 +03:00

387 lines
10 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/detail.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/main.h"
#include "chewy/mcga_graphics.h"
#include "chewy/menus.h"
namespace Chewy {
void plotMainMenu() {
static const int IMAGES[] = { 7, 8, 9, 10, 12, 11 };
int16 zoomX, zoomY;
if (_G(menu_item) != _G(tmp_menu)) {
_G(m_flip) = 0;
_G(tmp_menu) = _G(menu_item);
}
// Don't allow the mouse to warp past the right edge, as this messes
// up the menu screen
if (g_events->_mousePos.x > 266)
g_events->warpMouse(Common::Point(266, g_events->_mousePos.y));
const int16 x = MAX(g_events->_mousePos.x - 32, 0);
_G(menu_item) = (x / (MOUSE_MENU_MAX_X / 5));
int16 *correction = (int16 *)_G(menutaf)->correction;
for (int16 i = MENU_START_SPRITE; i < MAX_MENU_SPRITE; i++) {
int deltaX = 0;
if (i <= 8) {
zoomX = 0;
zoomY = 0;
} else {
zoomX = -3;
zoomY = -3;
if (i == 11)
deltaX = 40;
else if (i == 12)
deltaX = -40;
}
_G(out)->scale_set(_G(menutaf)->image[i],
MENU_X + deltaX + correction[i * 2],
_G(gameState).MainMenuY + correction[i * 2 + 1],
zoomX, zoomY, 0);
}
zoomX = 16;
zoomY = 16;
++_G(m_flip);
if (_G(m_flip) < 12 * (_G(gameState).DelaySpeed + 1)) {
int deltaX = 0;
if (_G(menu_item) == CUR_SAVE)
deltaX = -40;
else if (_G(menu_item) == CUR_INVENT)
deltaX = 40;
int img = IMAGES[_G(menu_item)];
_G(out)->scale_set(_G(menutaf)->image[img],
MENU_X + deltaX + correction[img * 2] - 5,
_G(gameState).MainMenuY + correction[img * 2 + 1] - 10,
zoomX, zoomY, 0);
} else {
if (_G(m_flip) > 15 * (_G(gameState).DelaySpeed + 1))
_G(m_flip) = 0;
}
}
void calcTxtXy(int16 *x, int16 *y, char *txtAdr, int16 txtCount) {
int16 len = 0;
for (int16 i = 0; i < txtCount; i++) {
int16 tmpLen = strlen(_G(txt)->strPos(txtAdr, i));
if (tmpLen > len)
len = tmpLen;
}
len = len * _G(fontMgr)->getFont()->getDataWidth();
int16 pixLen = len / 2;
*x = *x - pixLen + 12;
if (*x > (SCREEN_WIDTH - len))
*x = SCREEN_WIDTH - len;
else if (*x < 0)
*x = 0;
*y = *y - (10 * txtCount);
if (*y < 0)
*y = 0;
}
void calcTxtXy(int16 *x, int16 *y, Common::StringArray &textList) {
int16 len = 0;
for (int16 i = 0; i < (int16)textList.size(); i++) {
if ((int16)textList[i].size() > len)
len = textList[i].size();
}
len = len * _G(fontMgr)->getFont()->getDataWidth();
int16 pixLen = len / 2;
*x = *x - pixLen + 12;
if (*x > (SCREEN_WIDTH - len))
*x = SCREEN_WIDTH - len;
else if (*x < 0)
*x = 0;
*y = *y - (10 * textList.size());
if (*y < 0)
*y = 0;
}
void getDisplayCoord(int16 *x, int16 *y, int16 nr) {
int16 *xy = (int16 *)_G(inv_spr)[nr];
int16 x1 = 48 - xy[0];
x1 /= 2;
*x = x1;
int16 y1 = 48 - xy[1];
y1 /= 2;
*y = y1;
}
void buildMenu(int16 x, int16 y, int16 xNr, int16 yNr, int16 col, int16 mode) {
#define BUILDING_MENU_CORNER_LO 15
#define BUILDING_MENU_CORNER_RO 16
#define BUILDING_MENU_CORNER_LU 17
#define BUILDING_MENU_CORNER_RU 18
#define BUILDING_MENU_BELOW 19
#define BUILDING_MENU_SIDE_L 20
#define BUILDING_MENU_SIDE_R 21
#define BUILDING_MENU_ABOVE 22
#define BUILDING_MENU_ABOVE_L 23
#define BUILDING_MENU_ABOVE_R 24
#define BUILDING_MENU_ABOVE_M 25
int16 i, j;
int16 xy[4][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
uint8 spriteCornerNr[4] = { BUILDING_MENU_CORNER_LO, BUILDING_MENU_CORNER_RO, BUILDING_MENU_CORNER_LU, BUILDING_MENU_CORNER_RU };
xy[0][0] = x;
xy[0][1] = y;
xy[1][0] = x + 16 * (xNr - 1);
xy[1][1] = y;
xy[2][0] = x;
xy[2][1] = y + 16 * (yNr - 1);
xy[3][0] = x + 16 * (xNr - 1);
xy[3][1] = y + 16 * (yNr - 1);
for (i = 0; i < 4; i++)
_G(out)->spriteSet(_G(menutaf)->image[(int16)spriteCornerNr[i]],
xy[i][0], xy[i][1], _G(scr_width));
int16 s_nr = BUILDING_MENU_SIDE_L;
for (j = 0; j < 2; j++) {
y = xy[j][1] + 16;
for (i = 0; i < yNr - 2; i++) {
_G(out)->spriteSet(_G(menutaf)->image[s_nr], xy[j][0], y + i * 16, _G(scr_width));
}
++s_nr;
}
s_nr = BUILDING_MENU_ABOVE;
for (j = 0; j < 2; j++) {
x = xy[j * 2][0] + 16;
if ((!mode) || (mode == 1 && j == 1)) {
for (i = 0; i < xNr - 2; i++) {
_G(out)->spriteSet(_G(menutaf)->image[s_nr], x + i * 16, xy[j * 2][1], _G(scr_width));
}
}
s_nr -= 3;
}
if (mode) {
int16 leer = 0;
int16 center;
i = xNr - 7;
if (i == 0)
center = 1;
else if (i < 6)
center = i + 1;
else if (i < 8) {
leer = 1;
center = i - 1;
} else {
leer = 2;
center = i - 3;
}
x = xy[0][0] + 16;
for (j = 0; j < 2; j++) {
for (i = 0; i < leer; i++)
_G(out)->spriteSet(_G(menutaf)->image[BUILDING_MENU_ABOVE], x + i * 16, xy[0][1], _G(scr_width));
x = xy[1][0] - leer * 16;
}
_G(out)->spriteSet(_G(menutaf)->image[BUILDING_MENU_ABOVE_L], xy[0][0] + 16 + leer * 16, xy[0][1], _G(scr_width));
x = xy[0][0] + 16 + leer * 16 + 32;
for (i = 0; i < center; i++)
_G(out)->spriteSet(_G(menutaf)->image[BUILDING_MENU_ABOVE_M], x + i * 16, xy[0][1], _G(scr_width));
_G(out)->spriteSet(_G(menutaf)->image[BUILDING_MENU_ABOVE_R], x + i * 16, xy[0][1], _G(scr_width));
}
_G(out)->boxFill(xy[0][0] + 16, xy[0][1] + 16, xy[0][0] + 16 + (xNr - 2) * 16, xy[0][1] + 16 + (yNr - 2) * 16, col);
}
void autoMenu(int16 *x, int16 *y, int16 lineNr, int16 height, char *text, int16 mode) {
int16 tmp;
int16 x_pix = 0;
for (int16 i = 0; i < lineNr; i++) {
tmp = strlen(_G(txt)->strPos(text, i));
if (x_pix < tmp)
x_pix = tmp;
}
x_pix *= _G(font8)->getDataWidth();
x_pix += 12;
tmp = x_pix;
if (x_pix % 16)
tmp += 16;
int16 tmp1 = lineNr * height + 6 + 11;
if (tmp1 % 16)
tmp1 += 16;
*x -= ((tmp / 16) * 16) / 2;
*y -= ((tmp1 / 16) * 16) / 2;
buildMenu(*x, *y, tmp / 16, tmp1 / 16, 60, mode);
*x += 6 + (((tmp / 16) * 16) - x_pix) / 2;
*y += 5 + ((((tmp1 / 16) * 16) - 4) - (lineNr * height)) / 2;
}
#define ADS_WIN 0,153,20,3,60,1
void handleDialogCloseupMenu() {
int16 curYStart;
int16 col;
if (_G(flags).DialogCloseup) {
_G(flags).ShowAtsInvTxt = false;
_G(flags).MainInput = false;
if (_G(ads_item_nr) > 4)
curYStart = 190;
else
curYStart = 190 - (4 - _G(ads_item_nr)) * 10;
int16 curY = g_events->_mousePos.y;
if (curY < 160 || curY > curYStart + 10)
curY = 255;
else
curY = (curYStart + 8 - curY) / 10;
if (_G(atds)->aadGetStatus() == -1 && _G(ads_push) == false &&
_G(flags).NoDiaBox == false) {
buildMenu(ADS_WIN);
_G(fontMgr)->setFont(_G(font6));
if (_G(ads_item_nr) > 4)
curYStart = 190;
else
curYStart = 190 - (4 - _G(ads_item_nr)) * 10;
for (int16 i = 0; i < _G(ads_item_nr) && i < 4; i++) {
if (curY == i)
col = 255;
else
col = 14;
_G(out)->printxy(4, curYStart - i * 10, col, 300, 0, _G(dialogCloseupItemPtr)[i]);
}
}
switch (g_events->getSwitchCode()) {
case Common::MOUSE_BUTTON_LEFT:
case Common::KEYCODE_RETURN:
if (curY < _G(ads_item_nr) && curY >= 0 && _G(ads_push) == false) {
_G(ads_push) = true;
g_events->_mousePos.y = 159;
DialogCloseupNextBlock *an_blk = _G(atds)->dialogCloseupItemChoice(_G(ads_dia_nr), _G(ads_blk_nr), curY);
if (an_blk->_blkNr == -1) {
selectDialogOption(_G(ads_dia_nr), _G(ads_blk_nr), an_blk->_endNr);
endDialogCloseup(_G(ads_dia_nr), _G(ads_blk_nr), an_blk->_endNr);
stopDialogCloseupDialog();
} else {
an_blk = _G(atds)->calcNextDialogCloseupBlock(_G(ads_dia_nr), _G(ads_blk_nr), curY);
selectDialogOption(_G(ads_dia_nr), _G(ads_blk_nr), an_blk->_endNr);
_G(ads_blk_nr) = an_blk->_blkNr;
_G(dialogCloseupItemPtr) = _G(atds)->dialogCloseupItemPtr(_G(ads_dia_nr), _G(ads_blk_nr), &_G(ads_item_nr));
}
_G(det)->stopDetail(_G(talk_start_ani));
_G(det)->showStaticSpr(_G(talk_hide_static));
_G(talk_start_ani) = -1;
_G(talk_hide_static) = -1;
}
break;
default:
_G(ads_push) = false;
break;
}
}
}
void stopDialogCloseupDialog() {
aadWait(-1);
_G(gameState).DispFlag = _G(ads_tmp_dsp);
_G(flags).ShowAtsInvTxt = true;
_G(flags).MainInput = true;
_G(flags).DialogCloseup = false;
_G(mouseLeftClick) = false;
_G(atds)->stopDialogCloseup();
if (_G(minfo).button)
_G(flags).mainMouseFlag = 1;
}
void cur_2_inventory() {
if (_G(cur)->usingInventoryCursor()) {
invent_2_slot(_G(cur)->getInventoryCursor());
_G(cur)->setInventoryCursor(-1);
_G(menu_item) = CUR_WALK;
cursorChoice(_G(menu_item));
}
_G(cur)->setInventoryCursor(-1);
}
void inventory_2_cur(int16 nr) {
if (!_G(cur)->usingInventoryCursor() && _G(obj)->checkInventory(nr)) {
del_invent_slot(nr);
_G(menu_item) = CUR_USE;
_G(cur)->setInventoryCursor(nr);
getDisplayCoord(&_G(gameState).DispZx, &_G(gameState).DispZy, _G(cur)->getInventoryCursor());
}
}
void new_invent_2_cur(int16 inv_nr) {
cur_2_inventory();
_G(obj)->addInventory(inv_nr, &_G(room_blk));
inventory_2_cur(inv_nr);
}
void invent_2_slot(int16 nr) {
for (int16 i = 0; i < MAX_MOV_OBJ; i++) {
if (_G(gameState).InventSlot[i] == -1) {
_G(gameState).InventSlot[i] = nr;
break;
}
}
_G(obj)->addInventory(nr, &_G(room_blk));
}
int16 del_invent_slot(int16 nr) {
int16 ok = -1;
for (int16 i = 0; i < MAX_MOV_OBJ; i++) {
if (_G(gameState).InventSlot[i] == nr) {
_G(gameState).InventSlot[i] = -1;
if (ok == -1)
ok = i;
}
}
return ok;
}
void remove_inventory(int16 nr) {
if (nr == _G(cur)->getInventoryCursor()) {
delInventory(nr);
} else {
_G(obj)->delInventory(nr, &_G(room_blk));
del_invent_slot(nr);
}
}
} // namespace Chewy