232 lines
7.5 KiB
C++
232 lines
7.5 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.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include "xeen/interface.h"
|
||
|
#include "xeen/resources.h"
|
||
|
#include "xeen/xeen.h"
|
||
|
|
||
|
namespace Xeen {
|
||
|
|
||
|
Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
|
||
|
Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], nullptr);
|
||
|
_batUIFrame = 0;
|
||
|
_spotDoorsUIFrame = 0;
|
||
|
_dangerSenseUIFrame = 0;
|
||
|
_face1UIFrame = 0;
|
||
|
_face2UIFrame = 0;
|
||
|
_blessedUIFrame = 0;
|
||
|
_powerShieldUIFrame = 0;
|
||
|
_holyBonusUIFrame = 0;
|
||
|
_heroismUIFrame = 0;
|
||
|
_isEarlyGame = false;
|
||
|
_buttonsLoaded = false;
|
||
|
|
||
|
loadSprites();
|
||
|
}
|
||
|
|
||
|
void Interface::loadSprites() {
|
||
|
_globalSprites.load("global.icn");
|
||
|
_borderSprites.load("border.icn");
|
||
|
_spellFxSprites.load("spellfx.icn");
|
||
|
_fecpSprites.load("fecp.brd");
|
||
|
_blessSprites.load("bless.icn");
|
||
|
}
|
||
|
|
||
|
void Interface::setup(bool soundPlayed) {
|
||
|
SpriteResource uiSprites("inn.icn");
|
||
|
|
||
|
// Get mappings to the active characters in the party
|
||
|
_vm->_party._activeParty.resize(_vm->_party._partyCount);
|
||
|
for (int i = 0; i < _vm->_party._partyCount; ++i) {
|
||
|
_vm->_party._activeParty[i] = &_vm->_roster[_vm->_party._partyMembers[i]];
|
||
|
}
|
||
|
|
||
|
_isEarlyGame = _vm->_party._minutes >= 300;
|
||
|
|
||
|
if (_vm->_party._mazeId == 0) {
|
||
|
if (!soundPlayed) {
|
||
|
warning("TODO: loadSound?");
|
||
|
}
|
||
|
|
||
|
if (!_partyFaces[0]) {
|
||
|
// Xeen only uses 24 of possible 30 character slots
|
||
|
loadCharIcons(XEEN_TOTAL_CHARACTERS);
|
||
|
|
||
|
for (int i = 0; i < _vm->_party._partyCount; ++i)
|
||
|
_partyFaces[i] = &_charFaces[_vm->_party._partyMembers[i]];
|
||
|
}
|
||
|
|
||
|
_vm->_mode = MODE_1;
|
||
|
Common::Array<int> xeenSideChars;
|
||
|
|
||
|
// Build up a list of characters on the same Xeen side being loaded
|
||
|
for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
|
||
|
PlayerStruct &player = _vm->_roster[i];
|
||
|
if (player._name.empty() || player._xeenSide != _vm->_loadDarkSide)
|
||
|
continue;
|
||
|
|
||
|
xeenSideChars.push_back(i);
|
||
|
}
|
||
|
|
||
|
// Add in buttons for the UI
|
||
|
_buttonsLoaded = true;
|
||
|
addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true);
|
||
|
addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true);
|
||
|
addButton(Common::Rect(87, 100, 111, 120), 68, &uiSprites, true);
|
||
|
addButton(Common::Rect(122, 100, 146, 120), 82, &uiSprites, true);
|
||
|
addButton(Common::Rect(157, 100, 181, 120), 67, &uiSprites, true);
|
||
|
addButton(Common::Rect(192, 100, 216, 120), 88, &uiSprites, true);
|
||
|
addButton(Common::Rect(), 27, &uiSprites, false);
|
||
|
addButton(Common::Rect(16, 16, 48, 48), 49, &uiSprites, false);
|
||
|
addButton(Common::Rect(117, 16, 139, 48), 50, &uiSprites, false);
|
||
|
addButton(Common::Rect(16, 59, 48, 81), 51, &uiSprites, false);
|
||
|
addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false);
|
||
|
|
||
|
setupBackground();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Interface::loadCharIcons(int numChars) {
|
||
|
for (int i = 0; i < numChars; ++i) {
|
||
|
// Load new character resource
|
||
|
Common::String name = Common::String::format("char%02d.fac", i);
|
||
|
_charFaces[i].load(name);
|
||
|
}
|
||
|
|
||
|
_dseFace.load("dse.fac");
|
||
|
}
|
||
|
|
||
|
void Interface::setupBackground() {
|
||
|
_vm->_screen->loadBackground("back.raw");
|
||
|
assembleBorder();
|
||
|
}
|
||
|
|
||
|
void Interface::assembleBorder() {
|
||
|
Screen &screen = *_vm->_screen;
|
||
|
Window &gameWindow = screen._windows[28];
|
||
|
|
||
|
// Draw the outer frame
|
||
|
_globalSprites.draw(gameWindow, 0);
|
||
|
|
||
|
// Draw the animating bat character used to show when levitate is active
|
||
|
_borderSprites.draw(screen, _vm->_party._levitateActive ? _batUIFrame + 16 : 16);
|
||
|
_batUIFrame = (_batUIFrame + 1) % 12;
|
||
|
|
||
|
// Draw UI element to indicate whether can spot hidden doors
|
||
|
_borderSprites.draw(screen,
|
||
|
(_vm->_spotDoorsAllowed && _vm->_party.checkSkill(SPOT_DOORS)) ? _spotDoorsUIFrame + 28 : 28,
|
||
|
Common::Point(194, 91));
|
||
|
_spotDoorsUIFrame = (_spotDoorsUIFrame + 1) % 12;
|
||
|
|
||
|
// Draw UI element to indicate whether can sense danger
|
||
|
_borderSprites.draw(screen,
|
||
|
(_vm->_dangerSenseAllowed && _vm->_party.checkSkill(DANGER_SENSE)) ? _spotDoorsUIFrame + 40 : 40,
|
||
|
Common::Point(107, 9));
|
||
|
_dangerSenseUIFrame = (_dangerSenseUIFrame + 1) % 12;
|
||
|
|
||
|
// Handle the face UI elements for indicating clairvoyance status
|
||
|
_face1UIFrame = (_face1UIFrame + 1) % 4;
|
||
|
if (_vm->_face1State == 0)
|
||
|
_face1UIFrame += 4;
|
||
|
else if (_vm->_face1State == 2)
|
||
|
_face1UIFrame = 0;
|
||
|
|
||
|
_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
|
||
|
if (_vm->_face2State == 0)
|
||
|
_face2UIFrame += 252;
|
||
|
else if (_vm->_face2State == 2)
|
||
|
_face2UIFrame = 0;
|
||
|
|
||
|
if (!_vm->_party._clairvoyanceActive) {
|
||
|
_face1UIFrame = 0;
|
||
|
_face2UIFrame = 8;
|
||
|
}
|
||
|
|
||
|
_borderSprites.draw(screen, _face1UIFrame, Common::Point(0, 32));
|
||
|
_borderSprites.draw(screen,
|
||
|
screen._windows[10]._enabled || screen._windows[2]._enabled ?
|
||
|
52 : _face2UIFrame,
|
||
|
Common::Point(215, 32));
|
||
|
|
||
|
// Draw resistence indicators
|
||
|
if (!screen._windows[10]._enabled && !screen._windows[2]._enabled
|
||
|
&& screen._windows[38]._enabled) {
|
||
|
_fecpSprites.draw(screen, _vm->_party._fireResistence ? 1 : 0,
|
||
|
Common::Point(2, 2));
|
||
|
_fecpSprites.draw(screen, _vm->_party._electricityResistence ? 3 : 2,
|
||
|
Common::Point(219, 2));
|
||
|
_fecpSprites.draw(screen, _vm->_party._coldResistence ? 5 : 4,
|
||
|
Common::Point(2, 134));
|
||
|
_fecpSprites.draw(screen, _vm->_party._poisonResistence ? 7 : 6,
|
||
|
Common::Point(219, 134));
|
||
|
} else {
|
||
|
_fecpSprites.draw(screen, _vm->_party._fireResistence ? 9 : 8,
|
||
|
Common::Point(8, 8));
|
||
|
_fecpSprites.draw(screen, _vm->_party._electricityResistence ? 10 : 11,
|
||
|
Common::Point(219, 8));
|
||
|
_fecpSprites.draw(screen, _vm->_party._coldResistence ? 12 : 13,
|
||
|
Common::Point(8, 134));
|
||
|
_fecpSprites.draw(screen, _vm->_party._poisonResistence ? 14 : 15,
|
||
|
Common::Point(219, 134));
|
||
|
}
|
||
|
|
||
|
// Draw UI element for blessed
|
||
|
_blessSprites.draw(screen, 16, Common::Point(33, 137));
|
||
|
if (_vm->_party._blessedActive) {
|
||
|
_blessedUIFrame = (_blessedUIFrame + 1) % 4;
|
||
|
_blessSprites.draw(screen, _blessedUIFrame, Common::Point(33, 137));
|
||
|
}
|
||
|
|
||
|
// Draw UI element for power shield
|
||
|
if (_vm->_party._powerShieldActive) {
|
||
|
_powerShieldUIFrame = (_powerShieldUIFrame + 1) % 4;
|
||
|
_blessSprites.draw(screen, _powerShieldUIFrame + 4,
|
||
|
Common::Point(55, 137));
|
||
|
}
|
||
|
|
||
|
// Draw UI element for holy bonus
|
||
|
if (_vm->_party._holyBonusActive) {
|
||
|
_holyBonusUIFrame = (_holyBonusUIFrame + 1) % 4;
|
||
|
_blessSprites.draw(screen, _holyBonusUIFrame + 8, Common::Point(160, 137));
|
||
|
}
|
||
|
|
||
|
// Draw UI element for heroism
|
||
|
if (_vm->_party._heroismActive) {
|
||
|
_heroismUIFrame = (_heroismUIFrame + 1) % 4;
|
||
|
_blessSprites.draw(screen, _heroismUIFrame + 12, Common::Point(182, 137));
|
||
|
}
|
||
|
|
||
|
// Draw direction character if direction sense is active
|
||
|
if (_vm->_party.checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
|
||
|
const char *dirText = DIRECTION_TEXT[_vm->_party._mazeDirection];
|
||
|
Common::String msg = Common::String::format(
|
||
|
"\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
|
||
|
screen._windows[0].writeString(msg);
|
||
|
}
|
||
|
|
||
|
// Draw view frame
|
||
|
if (screen._windows[12]._enabled)
|
||
|
screen._windows[12].frame();
|
||
|
}
|
||
|
|
||
|
} // End of namespace Xeen
|