XEEN: Shifted more logic for 3d view drawing from Interface to InterfaceMap

This commit is contained in:
Paul Gilbert 2015-01-22 07:53:33 -05:00
parent 16a5a99c3a
commit 4c0c40c25d
6 changed files with 837 additions and 784 deletions

View file

@ -29,24 +29,9 @@ namespace Xeen {
Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _vm(vm) {
Common::fill(&_partyFaces[0], &_partyFaces[MAX_ACTIVE_PARTY], (SpriteResource *)nullptr);
_batUIFrame = 0;
_spotDoorsUIFrame = 0;
_dangerSenseUIFrame = 0;
_face1UIFrame = 0;
_face2UIFrame = 0;
_blessedUIFrame = 0;
_powerShieldUIFrame = 0;
_holyBonusUIFrame = 0;
_heroismUIFrame = 0;
_flipUIFrame = 0;
_buttonsLoaded = false;
_hiliteChar = -1;
_intrIndex1 = 0;
_flag1 = false;
_isAnimReset = false;
_tillMove = 0;
_overallFrame = 0;
_upDoorText = false;
_steppingFX = 0;
Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
@ -79,15 +64,10 @@ void Interface::initDrawStructs() {
}
void Interface::setup() {
_globalSprites.load("global.icn");
_borderSprites.load("border.icn");
_spellFxSprites.load("spellfx.icn");
_fecpSprites.load("fecp.brd");
_blessSprites.load("bless.icn");
InterfaceMap::setup();
_restoreSprites.load("restorex.icn");
_hpSprites.load("hpbars.icn");
_uiSprites.load("inn.icn");
_charPowSprites.load("charpow.icn");
// Get mappings to the active characters in the party
_vm->_party->_activeParty.resize(_vm->_party->_partyCount);
@ -277,14 +257,6 @@ start:
for (int i = 0; i < TOTAL_CHARACTERS; ++i)
_charFaces[i].clear();
_globalSprites.clear();
_borderSprites.clear();
_spellFxSprites.clear();
_fecpSprites.clear();
_blessSprites.clear();
_restoreSprites.clear();
_hpSprites.clear();
_uiSprites.clear();
}
void Interface::loadCharIcons() {
@ -307,114 +279,6 @@ void Interface::setupBackground() {
assembleBorder();
}
void Interface::assembleBorder() {
Screen &screen = *_vm->_screen;
// Draw the outer frame
_globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
// Draw the animating bat character used to show when levitate is active
_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
Common::Point(0, 82));
_batUIFrame = (_batUIFrame + 1) % 12;
// Draw UI element to indicate whether can spot hidden doors
_borderSprites.draw(screen,
(_thinWall && _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();
}
void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) {
Common::String playerNames[4];
Common::String playerRaces[4];
@ -535,228 +399,6 @@ void Interface::moveCharacterToRoster() {
error("TODO");
}
void Interface::draw3d(bool updateFlag) {
Combat &combat = *_vm->_combat;
EventsManager &events = *_vm->_events;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Screen &screen = *_vm->_screen;
Scripts &scripts = *_vm->_scripts;
if (screen._windows[11]._enabled)
return;
_flipUIFrame = (_flipUIFrame + 1) % 4;
if (_flipUIFrame == 0)
_flipWater = !_flipWater;
if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) &&
!_flag1 && _vm->_moveMonsters) {
if (--_tillMove == 0)
moveMonsters();
}
MazeObject &objObject = map._mobData._objects[_objNumber];
Direction partyDirection = _vm->_party->_mazeDirection;
int objNum = _objNumber - 1;
// Loop to update the frame numbers for each maze object, applying the animation frame
// limits as specified by the map's _animationInfo listing
for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) {
MazeObject &mazeObject = map._mobData._objects[idx];
AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId];
int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection];
if (_isAnimReset) {
mazeObject._frame = animEntry._frame1._frames[directionIndex];
} else {
++mazeObject._frame;
if ((int)idx == objNum && scripts._animCounter > 0 && (
objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
objObject._spriteId == 58 || objObject._spriteId == 73)) {
if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
mazeObject._frame = 1;
} else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) {
mazeObject._frame = animEntry._frame1._frames[directionIndex];
}
}
mazeObject._flipped = animEntry._flipped._flags[directionIndex];
}
if (map._isOutdoors) {
error("TODO: draw3d outdoors handling");
} else {
// Default all the parts of draw struct not to be drawn by default
for (int idx = 3; idx < _indoorList.size(); ++idx)
_indoorList[idx]._frame = -1;
if (_flag1) {
for (int idx = 0; idx < 96; ++idx) {
if (_indoorList[79 + idx]._sprites != nullptr) {
_indoorList[79 + idx]._frame = 0;
} else if (_indoorList[111 + idx]._sprites != nullptr) {
_indoorList[111 + idx]._frame = 1;
} else if (_indoorList[135 + idx]._sprites != nullptr) {
_indoorList[135 + idx]._frame = 2;
} else if (_indoorList[162 + idx]._sprites != nullptr) {
_indoorList[162 + idx]._frame = 0;
}
}
} else if (_charsShooting) {
for (int idx = 0; idx < 96; ++idx) {
if (_indoorList[162 + idx]._sprites != nullptr) {
_indoorList[162 + idx]._frame = 0;
} else if (_indoorList[135 + idx]._sprites != nullptr) {
_indoorList[135 + idx]._frame = 1;
} else if (_indoorList[111 + idx]._sprites != nullptr) {
_indoorList[111 + idx]._frame = 2;
} else if (_indoorList[79 + idx]._sprites != nullptr) {
_indoorList[79 + idx]._frame = 0;
}
}
}
setMazeBits();
_isAnimReset = false;
const int INDOOR_INDEXES[3] = { 157, 151, 154 };
const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 };
// Double check this, since it's not being used?
//MazeObject &objObject = map._mobData._objects[_objNumber - 1];
for (int idx = 0; idx < 3; ++idx) {
DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]];
DrawStruct &ds2 = _indoorList[INDOOR_INDEXES[idx] + 1];
ds1._sprites = nullptr;
ds2._sprites = nullptr;
if (combat._charsArray1[idx]) {
int posIndex= combat._attackMonsters[1] && !combat._attackMonsters[2] ? 1 : 0;
--combat._charsArray1[idx];
if (combat._monPow[idx]) {
ds1._x = INDOOR_COMBAT_POS[idx][0];
ds1._frame = 0;
ds1._scale = combat._monsterScale[idx];
if (ds1._scale == 0x8000) {
ds1._x /= 3;
ds1._y = 60;
} else {
ds1._y = 73;
}
ds1._flags = SPRFLAG_4000 | SPRFLAG_2000;
ds1._sprites = &_charPowSprites;
}
if (combat._elemPow[idx]) {
ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx];
ds2._frame = combat._elemPow[idx];
ds2._scale = combat._elemScale[idx];
if (ds2._scale == 0x8000)
ds2._x /= 3;
ds2._flags = SPRFLAG_4000 | SPRFLAG_2000;
ds2._sprites = &_charPowSprites;
}
}
}
setIndoorsMonsters();
setIndoorsObjects();
setIndoorsWallPics();
_indoorList[161]._sprites = nullptr;
_indoorList[160]._sprites = nullptr;
_indoorList[159]._sprites = nullptr;
// Handle attacking monsters
int monsterIndex = 0;
if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) {
_indoorList[159] = _indoorList[156];
_indoorList[160] = _indoorList[157];
_indoorList[161] = _indoorList[158];
_indoorList[158]._sprites = nullptr;
_indoorList[156]._sprites = nullptr;
_indoorList[157]._sprites = nullptr;
monsterIndex = 1;
} else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) {
_indoorList[159] = _indoorList[150];
_indoorList[160] = _indoorList[151];
_indoorList[161] = _indoorList[152];
_indoorList[152]._sprites = nullptr;
_indoorList[151]._sprites = nullptr;
_indoorList[150]._sprites = nullptr;
monsterIndex = 2;
} else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) {
_indoorList[159] = _indoorList[153];
_indoorList[160] = _indoorList[154];
_indoorList[161] = _indoorList[155];
_indoorList[153]._sprites = nullptr;
_indoorList[154]._sprites = nullptr;
_indoorList[155]._sprites = nullptr;
monsterIndex = 3;
}
drawIndoors();
switch (monsterIndex) {
case 1:
_indoorList[156] = _indoorList[159];
_indoorList[157] = _indoorList[160];
_indoorList[158] = _indoorList[161];
break;
case 2:
_indoorList[150] = _indoorList[159];
_indoorList[151] = _indoorList[160];
_indoorList[152] = _indoorList[161];
break;
case 3:
_indoorList[153] = _indoorList[159];
_indoorList[154] = _indoorList[160];
_indoorList[155] = _indoorList[161];
break;
default:
break;
}
}
animate3d();
drawMiniMap();
if (party._falling == 1) {
error("TODO: Indoor falling");
}
if (party._falling == 2) {
screen.saveBackground(1);
}
assembleBorder();
// Draw any on-screen text if flagged to do so
if (_upDoorText && combat._attackMonsters[0] == -1) {
screen._windows[3].writeString(_screenText);
}
if (updateFlag) {
screen._windows[1].update();
screen._windows[3].update();
}
// TODO: more stuff
_vm->_party->_stepped = false;
if (_vm->_mode == MODE_9) {
// TODO
}
events.wait(2);
}
void Interface::animate3d() {
}
void Interface::startup() {
Screen &screen = *_vm->_screen;
loadCharIcons();
@ -792,10 +434,6 @@ void Interface::mainIconsPrint() {
screen._windows[34].update();
}
void Interface::moveMonsters() {
}
void Interface::setMainButtons() {
clearButtons();
@ -821,381 +459,6 @@ void Interface::setMainButtons() {
addButton(Common::Rect(239, 47, 312, 57), Common::KEYCODE_3, &_iconSprites, false);
}
void Interface::drawMiniMap() {
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Screen &screen = *_vm->_screen;
Window &window1 = screen._windows[1];
if (screen._windows[2]._enabled || screen._windows[10]._enabled)
return;
if (!party._automapOn && !party._wizardEyeActive) {
// Draw the Might & Magic logo
_globalSprites.draw(window1, 5, Common::Point(232, 9));
return;
}
int v, frame;
int frame2 = _overallFrame * 2;
bool eyeActive = party._wizardEyeActive;
if (party._automapOn)
party._wizardEyeActive = false;
if (map._isOutdoors) {
_globalSprites.draw(window1, 15, Common::Point(237, 12));
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
4);
frame = map.mazeDataCurrent()._surfaceTypes[v];
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
}
}
}
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
4);
frame = map.mazeData()._wallTypes[v];
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp));
}
}
}
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
4);
if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp));
}
}
}
// Draw the direction arrow
_globalSprites.draw(window1, party._mazeDirection + 1,
Common::Point(267, 36));
} else {
frame2 = (frame2 + 2) % 8;
// First draw the default surface bases for each cell to show
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
0, 0xffff);
if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, 0, Common::Point(xp, yp));
}
}
}
// Draw correct surface bases for revealed tiles
for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
0, 0xffff);
int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
if (v != INVALID_CELL && map._currentSurfaceId &&
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp));
}
}
}
v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
if (v != INVALID_CELL && map._currentSurfaceId &&
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1,
map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
Common::Point(232, 9));
}
// Handle drawing surface sprites partially clipped at the left edge
for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff),
0, 0xffff);
if (v != INVALID_CELL && map._currentSurfaceId &&
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1,
map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
Common::Point(232, yp));
}
}
// Handle drawing surface sprites partially clipped at the top edge
for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4),
0, 0xffff);
if (v != INVALID_CELL && map._currentSurfaceId &&
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1,
map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
Common::Point(xp, 9));
}
}
//
for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE;
++idx, ++xDiff, xp += 10, yp -= 8) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx),
12, 0xffff);
switch (v) {
case 1:
frame = 18;
break;
case 3:
frame = 22;
break;
case 4:
case 13:
frame = 16;
break;
case 5:
case 8:
frame = 2;
break;
case 6:
frame = 30;
break;
case 7:
frame = 32;
break;
case 9:
frame = 24;
break;
case 10:
frame = 28;
break;
case 11:
frame = 14;
break;
case 12:
frame = frame2 + 4;
break;
case 14:
frame = 24;
break;
case 15:
frame = 26;
break;
default:
frame = -1;
break;
}
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
map._tileSprites.draw(window1, frame, Common::Point(222, yp));
v = map.mazeLookup(
Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4),
0);
switch (v) {
case 1:
frame = 19;
break;
case 2:
frame = 35;
break;
case 3:
frame = 23;
break;
case 4:
case 13:
frame = 17;
break;
case 5:
case 8:
frame = 3;
break;
case 6:
frame = 31;
break;
case 7:
frame = 33;
break;
case 9:
frame = 21;
break;
case 10:
frame = 29;
break;
case 11:
frame = 15;
break;
case 12:
frame = frame2 + 5;
break;
case 14:
frame = 25;
break;
case 15:
frame = 27;
break;
default:
frame = -1;
break;
}
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
map._tileSprites.draw(window1, frame, Common::Point(xp, 4));
}
// Draw the front/back walls of cells in the minimap
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
++rowNum, --yDiff, yp += 8) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
++colNum, ++xDiff, xp += 10) {
if (colNum == 4 && rowNum == 4) {
// Center of the minimap. Draw the direction arrow
_globalSprites.draw(window1, party._mazeDirection + 1,
Common::Point(272, 40));
}
v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
party._mazePosition.y + yDiff), 12, 0xffff);
switch (v) {
case 1:
frame = 18;
break;
case 3:
frame = 22;
break;
case 4:
case 13:
frame = 16;
break;
case 5:
case 8:
frame = 2;
break;
case 6:
frame = 30;
break;
case 7:
frame = 32;
break;
case 9:
frame = 20;
break;
case 10:
frame = 28;
break;
case 11:
frame = 14;
break;
case 12:
frame = frame2 + 4;
break;
case 14:
frame = 24;
break;
case 15:
frame = 26;
break;
default:
frame = -1;
break;
}
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
}
v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
party._mazePosition.y + yDiff), 12, 0xffff);
switch (v) {
case 1:
frame = 19;
break;
case 2:
frame = 35;
break;
case 3:
frame = 23;
break;
case 4:
case 13:
frame = 17;
break;
case 5:
case 8:
frame = 3;
break;
case 6:
frame = 31;
break;
case 7:
frame = 33;
break;
case 9:
frame = 21;
break;
case 10:
frame = 29;
break;
case 11:
frame = 15;
break;
case 12:
frame = frame2 + 5;
break;
case 14:
frame = 25;
break;
case 15:
frame = 27;
break;
default:
frame = -1;
break;
}
if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
}
}
}
// Draw the top of blocked/wall cells on the map
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
0, 0xffff);
if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) {
map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
}
}
}
}
// Draw outer rectangle around the automap
_globalSprites.draw(window1, 6, Common::Point(223, 3));
party._wizardEyeActive = eyeActive;
}
/**
* Waits for a keypress or click, whilst still allowing the game scene to
* be animated.

View file

@ -38,39 +38,19 @@ class XeenEngine;
class Interface: public ButtonContainer, public InterfaceMap {
private:
XeenEngine *_vm;
SpriteResource _dseFace;
SpriteResource _globalSprites;
SpriteResource _borderSprites;
SpriteResource _spellFxSprites;
SpriteResource _fecpSprites;
SpriteResource _blessSprites;
SpriteResource _restoreSprites;
SpriteResource _dseFace;
SpriteResource _hpSprites;
SpriteResource _uiSprites;
SpriteResource _iconSprites;
SpriteResource _charPowSprites;
SpriteResource _charFaces[TOTAL_CHARACTERS];
SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
DrawStruct _faceDrawStructs[4];
DrawStruct _mainList[16];
int _combatCharIds[8];
int _batUIFrame;
int _spotDoorsUIFrame;
int _dangerSenseUIFrame;
int _face1UIFrame;
int _face2UIFrame;
int _blessedUIFrame;
int _powerShieldUIFrame;
int _holyBonusUIFrame;
int _heroismUIFrame;
int _flipUIFrame;
bool _buttonsLoaded;
int _hiliteChar;
bool _flag1;
bool _isAnimReset;
byte _tillMove;
int _overallFrame;
int _steppingFX;
Common::String _interfaceText;
@ -78,8 +58,6 @@ private:
void loadSprites();
void assembleBorder();
void setupBackground();
void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag);
@ -88,14 +66,8 @@ private:
void moveCharacterToRoster();
void animate3d();
void moveMonsters();
void setMainButtons();
void drawMiniMap();
void chargeStep();
void stepTime();
@ -105,12 +77,12 @@ private:
bool checkMoveDirection(int key);
public:
int _intrIndex1;
Common::String _screenText;
bool _upDoorText;
public:
Interface(XeenEngine *vm);
void setup();
virtual ~Interface() {}
virtual void setup();
void manageCharacters(bool soundPlayed);
@ -118,8 +90,6 @@ public:
void loadPartyIcons();
void draw3d(bool updateFlag);
void startup();
void mainIconsPrint();

View file

@ -374,9 +374,266 @@ InterfaceMap::InterfaceMap(XeenEngine *vm): _vm(vm) {
_objNumber = 0;
_combatFloatCounter = 0;
_thinWall = false;
_isAnimReset = false;
_upDoorText = false;
_batUIFrame = 0;
_spotDoorsUIFrame = 0;
_dangerSenseUIFrame = 0;
_face1UIFrame = 0;
_face2UIFrame = 0;
_blessedUIFrame = 0;
_powerShieldUIFrame = 0;
_holyBonusUIFrame = 0;
_heroismUIFrame = 0;
_flipUIFrame = 0;
_tillMove = 0;
_flag1 = false;
_overallFrame = 0;
}
void InterfaceMap::setup() {
_globalSprites.load("global.icn");
_borderSprites.load("border.icn");
_spellFxSprites.load("spellfx.icn");
_fecpSprites.load("fecp.brd");
_blessSprites.load("bless.icn");
_charPowSprites.load("charpow.icn");
}
void InterfaceMap::draw3d(bool updateFlag) {
Combat &combat = *_vm->_combat;
EventsManager &events = *_vm->_events;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Screen &screen = *_vm->_screen;
Scripts &scripts = *_vm->_scripts;
if (screen._windows[11]._enabled)
return;
_flipUIFrame = (_flipUIFrame + 1) % 4;
if (_flipUIFrame == 0)
_flipWater = !_flipWater;
if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_2) &&
!_flag1 && _vm->_moveMonsters) {
if (--_tillMove == 0)
moveMonsters();
}
MazeObject &objObject = map._mobData._objects[_objNumber];
Direction partyDirection = _vm->_party->_mazeDirection;
int objNum = _objNumber - 1;
// Loop to update the frame numbers for each maze object, applying the animation frame
// limits as specified by the map's _animationInfo listing
for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) {
MazeObject &mazeObject = map._mobData._objects[idx];
AnimationEntry &animEntry = map._animationInfo[mazeObject._spriteId];
int directionIndex = DIRECTION_ANIM_POSITIONS[mazeObject._direction][partyDirection];
if (_isAnimReset) {
mazeObject._frame = animEntry._frame1._frames[directionIndex];
}
else {
++mazeObject._frame;
if ((int)idx == objNum && scripts._animCounter > 0 && (
objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
objObject._spriteId == 58 || objObject._spriteId == 73)) {
if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
mazeObject._frame = 1;
}
else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) {
mazeObject._frame = animEntry._frame1._frames[directionIndex];
}
}
mazeObject._flipped = animEntry._flipped._flags[directionIndex];
}
if (map._isOutdoors) {
error("TODO: draw3d outdoors handling");
}
else {
// Default all the parts of draw struct not to be drawn by default
for (int idx = 3; idx < _indoorList.size(); ++idx)
_indoorList[idx]._frame = -1;
if (_flag1) {
for (int idx = 0; idx < 96; ++idx) {
if (_indoorList[79 + idx]._sprites != nullptr) {
_indoorList[79 + idx]._frame = 0;
}
else if (_indoorList[111 + idx]._sprites != nullptr) {
_indoorList[111 + idx]._frame = 1;
}
else if (_indoorList[135 + idx]._sprites != nullptr) {
_indoorList[135 + idx]._frame = 2;
}
else if (_indoorList[162 + idx]._sprites != nullptr) {
_indoorList[162 + idx]._frame = 0;
}
}
}
else if (_charsShooting) {
for (int idx = 0; idx < 96; ++idx) {
if (_indoorList[162 + idx]._sprites != nullptr) {
_indoorList[162 + idx]._frame = 0;
}
else if (_indoorList[135 + idx]._sprites != nullptr) {
_indoorList[135 + idx]._frame = 1;
}
else if (_indoorList[111 + idx]._sprites != nullptr) {
_indoorList[111 + idx]._frame = 2;
}
else if (_indoorList[79 + idx]._sprites != nullptr) {
_indoorList[79 + idx]._frame = 0;
}
}
}
setMazeBits();
_isAnimReset = false;
const int INDOOR_INDEXES[3] = { 157, 151, 154 };
const int INDOOR_COMBAT_POS[3][2] = { { 102, 134 }, { 36, 67 }, { 161, 161 } };
const int INDOOR_COMBAT_POS2[4] = { 8, 6, 4, 2 };
// Double check this, since it's not being used?
//MazeObject &objObject = map._mobData._objects[_objNumber - 1];
for (int idx = 0; idx < 3; ++idx) {
DrawStruct &ds1 = _indoorList[INDOOR_INDEXES[idx]];
DrawStruct &ds2 = _indoorList[INDOOR_INDEXES[idx] + 1];
ds1._sprites = nullptr;
ds2._sprites = nullptr;
if (combat._charsArray1[idx]) {
int posIndex = combat._attackMonsters[1] && !combat._attackMonsters[2] ? 1 : 0;
--combat._charsArray1[idx];
if (combat._monPow[idx]) {
ds1._x = INDOOR_COMBAT_POS[idx][0];
ds1._frame = 0;
ds1._scale = combat._monsterScale[idx];
if (ds1._scale == 0x8000) {
ds1._x /= 3;
ds1._y = 60;
}
else {
ds1._y = 73;
}
ds1._flags = SPRFLAG_4000 | SPRFLAG_2000;
ds1._sprites = &_charPowSprites;
}
if (combat._elemPow[idx]) {
ds2._x = INDOOR_COMBAT_POS[idx][posIndex] + INDOOR_COMBAT_POS2[idx];
ds2._frame = combat._elemPow[idx];
ds2._scale = combat._elemScale[idx];
if (ds2._scale == 0x8000)
ds2._x /= 3;
ds2._flags = SPRFLAG_4000 | SPRFLAG_2000;
ds2._sprites = &_charPowSprites;
}
}
}
setIndoorsMonsters();
setIndoorsObjects();
setIndoorsWallPics();
_indoorList[161]._sprites = nullptr;
_indoorList[160]._sprites = nullptr;
_indoorList[159]._sprites = nullptr;
// Handle attacking monsters
int monsterIndex = 0;
if (combat._attackMonsters[0] != -1 && map._mobData._monsters[combat._attackMonsters[0]]._frame >= 0) {
_indoorList[159] = _indoorList[156];
_indoorList[160] = _indoorList[157];
_indoorList[161] = _indoorList[158];
_indoorList[158]._sprites = nullptr;
_indoorList[156]._sprites = nullptr;
_indoorList[157]._sprites = nullptr;
monsterIndex = 1;
}
else if (combat._attackMonsters[1] != -1 && map._mobData._monsters[combat._attackMonsters[1]]._frame >= 0) {
_indoorList[159] = _indoorList[150];
_indoorList[160] = _indoorList[151];
_indoorList[161] = _indoorList[152];
_indoorList[152]._sprites = nullptr;
_indoorList[151]._sprites = nullptr;
_indoorList[150]._sprites = nullptr;
monsterIndex = 2;
}
else if (combat._attackMonsters[2] != -1 && map._mobData._monsters[combat._attackMonsters[2]]._frame >= 0) {
_indoorList[159] = _indoorList[153];
_indoorList[160] = _indoorList[154];
_indoorList[161] = _indoorList[155];
_indoorList[153]._sprites = nullptr;
_indoorList[154]._sprites = nullptr;
_indoorList[155]._sprites = nullptr;
monsterIndex = 3;
}
drawIndoors();
switch (monsterIndex) {
case 1:
_indoorList[156] = _indoorList[159];
_indoorList[157] = _indoorList[160];
_indoorList[158] = _indoorList[161];
break;
case 2:
_indoorList[150] = _indoorList[159];
_indoorList[151] = _indoorList[160];
_indoorList[152] = _indoorList[161];
break;
case 3:
_indoorList[153] = _indoorList[159];
_indoorList[154] = _indoorList[160];
_indoorList[155] = _indoorList[161];
break;
default:
break;
}
}
animate3d();
drawMiniMap();
if (party._falling == 1) {
error("TODO: Indoor falling");
}
if (party._falling == 2) {
screen.saveBackground(1);
}
assembleBorder();
// Draw any on-screen text if flagged to do so
if (_upDoorText && combat._attackMonsters[0] == -1) {
screen._windows[3].writeString(_screenText);
}
if (updateFlag) {
screen._windows[1].update();
screen._windows[3].update();
}
// TODO: more stuff
_vm->_party->_stepped = false;
if (_vm->_mode == MODE_9) {
// TODO
}
events.wait(2);
}
void InterfaceMap::animate3d() {
}
void InterfaceMap::setMazeBits() {
Common::fill(&_wo[0], &_wo[308], 0);
@ -3453,4 +3710,491 @@ void InterfaceMap::drawIndoors() {
_charsShooting = _isShooting;
}
void InterfaceMap::moveMonsters() {
// TODO
}
void InterfaceMap::assembleBorder() {
Screen &screen = *_vm->_screen;
// Draw the outer frame
_globalSprites.draw(screen._windows[0], 0, Common::Point(8, 8));
// Draw the animating bat character used to show when levitate is active
_borderSprites.draw(screen._windows[0], _vm->_party->_levitateActive ? _batUIFrame + 16 : 16,
Common::Point(0, 82));
_batUIFrame = (_batUIFrame + 1) % 12;
// Draw UI element to indicate whether can spot hidden doors
_borderSprites.draw(screen,
(_thinWall && _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();
}
void InterfaceMap::drawMiniMap() {
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Screen &screen = *_vm->_screen;
Window &window1 = screen._windows[1];
if (screen._windows[2]._enabled || screen._windows[10]._enabled)
return;
if (!party._automapOn && !party._wizardEyeActive) {
// Draw the Might & Magic logo
_globalSprites.draw(window1, 5, Common::Point(232, 9));
return;
}
int v, frame;
int frame2 = _overallFrame * 2;
bool eyeActive = party._wizardEyeActive;
if (party._automapOn)
party._wizardEyeActive = false;
if (map._isOutdoors) {
_globalSprites.draw(window1, 15, Common::Point(237, 12));
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
4);
frame = map.mazeDataCurrent()._surfaceTypes[v];
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
}
}
}
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
4);
frame = map.mazeData()._wallTypes[v];
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, frame + 16, Common::Point(xp, yp));
}
}
}
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
4);
if (v != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, v + 32, Common::Point(xp, yp));
}
}
}
// Draw the direction arrow
_globalSprites.draw(window1, party._mazeDirection + 1,
Common::Point(267, 36));
} else {
frame2 = (frame2 + 2) % 8;
// First draw the default surface bases for each cell to show
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
0, 0xffff);
if (v != INVALID_CELL && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, 0, Common::Point(xp, yp));
}
}
}
// Draw correct surface bases for revealed tiles
for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
0, 0xffff);
int surfaceId = map.mazeData()._surfaceTypes[map._currentSurfaceId];
if (v != INVALID_CELL && map._currentSurfaceId &&
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, surfaceId + 36, Common::Point(xp, yp));
}
}
}
v = map.mazeLookup(Common::Point(party._mazePosition.x - 4, party._mazePosition.y + 4), 0xffff, 0);
if (v != INVALID_CELL && map._currentSurfaceId &&
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1,
map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
Common::Point(232, 9));
}
// Handle drawing surface sprites partially clipped at the left edge
for (int rowNum = 0, yp = 17, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, --yDiff, yp += 8) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x - 4, party._mazePosition.y + yDiff),
0, 0xffff);
if (v != INVALID_CELL && map._currentSurfaceId &&
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1,
map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
Common::Point(232, yp));
}
}
// Handle drawing surface sprites partially clipped at the top edge
for (int colNum = 0, xp = 242, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, ++xDiff, xp += 8) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + 4),
0, 0xffff);
if (v != INVALID_CELL && map._currentSurfaceId &&
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1,
map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
Common::Point(xp, 9));
}
}
//
for (int idx = 0, xp = 237, yp = 60, xDiff = -3; idx < MINIMAP_SIZE;
++idx, ++xDiff, xp += 10, yp -= 8) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x - 4, party._mazePosition.y - 3 + idx),
12, 0xffff);
switch (v) {
case 1:
frame = 18;
break;
case 3:
frame = 22;
break;
case 4:
case 13:
frame = 16;
break;
case 5:
case 8:
frame = 2;
break;
case 6:
frame = 30;
break;
case 7:
frame = 32;
break;
case 9:
frame = 24;
break;
case 10:
frame = 28;
break;
case 11:
frame = 14;
break;
case 12:
frame = frame2 + 4;
break;
case 14:
frame = 24;
break;
case 15:
frame = 26;
break;
default:
frame = -1;
break;
}
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
map._tileSprites.draw(window1, frame, Common::Point(222, yp));
v = map.mazeLookup(
Common::Point(party._mazePosition.x - 3 + idx, party._mazePosition.y + 4),
0);
switch (v) {
case 1:
frame = 19;
break;
case 2:
frame = 35;
break;
case 3:
frame = 23;
break;
case 4:
case 13:
frame = 17;
break;
case 5:
case 8:
frame = 3;
break;
case 6:
frame = 31;
break;
case 7:
frame = 33;
break;
case 9:
frame = 21;
break;
case 10:
frame = 29;
break;
case 11:
frame = 15;
break;
case 12:
frame = frame2 + 5;
break;
case 14:
frame = 25;
break;
case 15:
frame = 27;
break;
default:
frame = -1;
break;
}
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive))
map._tileSprites.draw(window1, frame, Common::Point(xp, 4));
}
// Draw the front/back walls of cells in the minimap
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE;
++rowNum, --yDiff, yp += 8) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE;
++colNum, ++xDiff, xp += 10) {
if (colNum == 4 && rowNum == 4) {
// Center of the minimap. Draw the direction arrow
_globalSprites.draw(window1, party._mazeDirection + 1,
Common::Point(272, 40));
}
v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
party._mazePosition.y + yDiff), 12, 0xffff);
switch (v) {
case 1:
frame = 18;
break;
case 3:
frame = 22;
break;
case 4:
case 13:
frame = 16;
break;
case 5:
case 8:
frame = 2;
break;
case 6:
frame = 30;
break;
case 7:
frame = 32;
break;
case 9:
frame = 20;
break;
case 10:
frame = 28;
break;
case 11:
frame = 14;
break;
case 12:
frame = frame2 + 4;
break;
case 14:
frame = 24;
break;
case 15:
frame = 26;
break;
default:
frame = -1;
break;
}
if (frame != -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
}
v = map.mazeLookup(Common::Point(party._mazePosition.x + xDiff,
party._mazePosition.y + yDiff), 12, 0xffff);
switch (v) {
case 1:
frame = 19;
break;
case 2:
frame = 35;
break;
case 3:
frame = 23;
break;
case 4:
case 13:
frame = 17;
break;
case 5:
case 8:
frame = 3;
break;
case 6:
frame = 31;
break;
case 7:
frame = 33;
break;
case 9:
frame = 21;
break;
case 10:
frame = 29;
break;
case 11:
frame = 15;
break;
case 12:
frame = frame2 + 5;
break;
case 14:
frame = 25;
break;
case 15:
frame = 27;
break;
default:
frame = -1;
break;
}
if (v == -1 && (map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(window1, frame, Common::Point(xp, yp));
}
}
}
// Draw the top of blocked/wall cells on the map
for (int rowNum = 0, yp = 12, yDiff = 3; rowNum < MINIMAP_SIZE; ++rowNum, yp += 8, --yDiff) {
for (int colNum = 0, xp = 237, xDiff = -3; colNum < MINIMAP_SIZE; ++colNum, xp += 10, ++xDiff) {
v = map.mazeLookup(
Common::Point(party._mazePosition.x + xDiff, party._mazePosition.y + yDiff),
0, 0xffff);
if (v == INVALID_CELL || (!map._currentSteppedOn && !party._wizardEyeActive)) {
map._tileSprites.draw(window1, 1, Common::Point(xp, yp));
}
}
}
}
// Draw outer rectangle around the automap
_globalSprites.draw(window1, 6, Common::Point(223, 3));
party._wizardEyeActive = eyeActive;
}
} // End of namespace Xeen

View file

@ -83,6 +83,11 @@ public:
class InterfaceMap {
private:
XeenEngine *_vm;
SpriteResource _borderSprites;
SpriteResource _spellFxSprites;
SpriteResource _fecpSprites;
SpriteResource _blessSprites;
SpriteResource _charPowSprites;
int _combatFloatCounter;
void initDrawStructs();
@ -90,9 +95,9 @@ private:
void setMonsterSprite(DrawStruct &drawStruct, MazeMonster &monster,
SpriteResource *sprites, int frame, int defaultY);
protected:
SpriteResource _globalSprites;
int8 _wp[20];
byte _wo[308];
int _overallFrame;
bool _flipWater;
bool _flipGround;
bool _flipSky;
@ -101,14 +106,44 @@ protected:
bool _charsShooting;
int _objNumber;
bool _thinWall;
bool _isAnimReset;
int _batUIFrame;
int _spotDoorsUIFrame;
int _dangerSenseUIFrame;
int _face1UIFrame;
int _face2UIFrame;
int _blessedUIFrame;
int _powerShieldUIFrame;
int _holyBonusUIFrame;
int _heroismUIFrame;
int _flipUIFrame;
byte _tillMove;
bool _flag1;
int _overallFrame;
void setMazeBits();
void animate3d();
void moveMonsters();
void drawMiniMap();
void assembleBorder();
virtual void setup();
public:
OutdoorDrawList _outdoorList;
IndoorDrawList _indoorList;
bool _upDoorText;
Common::String _screenText;
public:
InterfaceMap(XeenEngine *vm);
virtual ~InterfaceMap() {}
void draw3d(bool updateFlag);
void setIndoorsMonsters();
void setIndoorsObjects();

View file

@ -129,7 +129,7 @@ void Scripts::checkEvents() {
_vm->_mode = MODE_9;
_paramText = event._parameters.size() == 0 ? "" :
map._events._text[event._parameters[0]];
doOpcode(event._opcode, event._parameters);
doOpcode(event);
break;
} else {
var50 = true;
@ -154,7 +154,10 @@ void Scripts::openGrate(int v1, int v2) {
typedef void(Scripts::*ScriptMethodPtr)(Common::Array<byte> &);
void Scripts::doOpcode(Opcode opcode, Common::Array<byte> &params) {
/**
* Handles executing a given script command
*/
void Scripts::doOpcode(MazeEvent &event) {
static const ScriptMethodPtr COMMAND_LIST[] = {
nullptr, &Scripts::cmdDisplay1, &Scripts::cmdDoorTextSml,
&Scripts::cmdDoorTextLrg, &Scripts::cmdSignText,
@ -180,7 +183,8 @@ void Scripts::doOpcode(Opcode opcode, Common::Array<byte> &params) {
&Scripts::cmdCutsceneEdWorld, &Scripts::cmdFlipWorld, &Scripts::cmdPlayCD
};
(this->*COMMAND_LIST[opcode])(params);
_event = &event;
(this->*COMMAND_LIST[event._opcode])(event._parameters);
}
/**
@ -209,8 +213,8 @@ void Scripts::cmdDoorTextSml(Common::Array<byte> &params) {
_paramText.c_str());
intf._upDoorText = true;
intf.draw3d(true);
_var4F = true;
_var4F = true;
cmdNoAction(params);
}
@ -223,16 +227,52 @@ void Scripts::cmdDoorTextLrg(Common::Array<byte> &params) {
_paramText.c_str());
intf._upDoorText = true;
intf.draw3d(true);
_var4F = true;
_var4F = true;
cmdNoAction(params);
}
void Scripts::cmdSignText(Common::Array<byte> &params) {}
void Scripts::cmdNPC(Common::Array<byte> &params) {}
void Scripts::cmdPlayFX(Common::Array<byte> &params) {}
void Scripts::cmdTeleport(Common::Array<byte> &params) {}
void Scripts::cmdIf(Common::Array<byte> &params) {}
void Scripts::cmdSignText(Common::Array<byte> &params) {
Interface &intf = *_vm->_interface;
intf._screenText = Common::String::format("\f08\x03""c\t120\v088%s\x03""l\fd",
_paramText.c_str());
intf._upDoorText = true;
intf.draw3d(true);
_var4F = true;
cmdNoAction(params);
}
void Scripts::cmdNPC(Common::Array<byte> &params) {
warning("TODO: cmdNPC");
}
void Scripts::cmdPlayFX(Common::Array<byte> &params) {
_vm->_sound->playFX(params[0]);
_var4F = true;
cmdNoAction(params);
}
void Scripts::cmdTeleport(Common::Array<byte> &params) {
}
void Scripts::cmdIf(Common::Array<byte> &params) {
switch (params[0]) {
case 16:
case 34:
case 100:
break;
case 25:
case 35:
case 101:
case 106:
break;
default:
break;
}
}
void Scripts::cmdMoveObj(Common::Array<byte> &params) {}
void Scripts::cmdTakeOrGive(Common::Array<byte> &params) {}

View file

@ -132,8 +132,9 @@ private:
int _var4F;
int _nEdamageType;
Common::String _paramText;
MazeEvent *_event;
void doOpcode(Opcode opcode, Common::Array<byte> &params);
void doOpcode(MazeEvent &event);
void cmdDisplay1(Common::Array<byte> &params);
void cmdDoorTextSml(Common::Array<byte> &params);
void cmdDoorTextLrg(Common::Array<byte> &params);