Files
scummvm-cursorfix/engines/tot/engine.cpp
2026-02-02 04:50:13 +01:00

5553 lines
174 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 "backends/keymapper/keymapper.h"
#include "common/config-manager.h"
#include "common/savefile.h"
#include "image/png.h"
#include "tot/anims.h"
#include "tot/debug.h"
#include "tot/statics.h"
#include "tot/tot.h"
#include "tot/util.h"
namespace Tot {
void TotEngine::drawText(uint number) {
readTextFile();
uint foo = 0;
sayLine(number, 255, 0, foo, false);
_verbFile.close();
}
void TotEngine::displayLoading() {
const char *msg = getFullScreenMessagesByCurrentLanguage()[58];
setRGBPalette(255, 63, 63, 63);
littText(121, 72, msg, 0);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(120, 71, msg, 0);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(119, 72, msg, 0);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(120, 73, msg, 0);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(120, 72, msg, 255);
_screen->update();
// enforce a delay for now so it's visible
g_system->delayMillis(200);
}
void TotEngine::runaroundRed() {
const uint devilTrajectory[91][2] = {
{204, 47}, {204, 49}, {203, 51}, {203, 53}, {201, 55}, {199, 57}, {197, 59}, {195, 61},
{193, 63}, {192, 65}, {192, 67}, {192, 69}, {192, 71}, {192, 73}, {191, 75}, {191, 77},
{191, 79}, {191, 81}, {191, 83}, {191, 85}, {191, 87}, {192, 89}, {192, 91}, {192, 93},
{192, 95}, {193, 97}, {194, 99}, {195, 101}, {196, 103}, {197, 105}, {198, 107}, {199, 109},
{200, 111}, {201, 111}, {203, 111}, {205, 111}, {207, 111}, {209, 111}, {211, 111}, {213, 111},
{215, 110}, {217, 110}, {219, 110}, {221, 110}, {223, 110}, {225, 110}, {227, 110}, {229, 110},
{231, 110}, {232, 109}, {234, 108}, {236, 107}, {238, 106}, {240, 105}, {242, 104}, {244, 103},
{246, 102}, {248, 101}, {250, 100}, {252, 99}, {254, 98}, {256, 97}, {258, 96}, {260, 95},
{261, 93}, {262, 91}, {263, 89}, {264, 87}, {265, 85}, {266, 83}, {267, 81}, {268, 79},
{269, 77}, {270, 75}, {271, 73}, {272, 71}, {273, 69}, {274, 67}, {275, 65}, {276, 63},
{277, 61}, {278, 59}, {279, 57}, {280, 55}, {281, 53}, {282, 52}, {282, 52}, {282, 52},
{282, 52}, {282, 52}, {282, 52}
};
bool exitLoop = false;
loadDevil();
uint secTrajIndex = 0;
uint secTrajLength = 82;
_iframe2 = 0;
_isSecondaryAnimationEnabled = true;
do {
_chrono->updateChrono();
if (_chrono->_gameTick) {
if (secTrajIndex == secTrajLength)
exitLoop = true;
secTrajIndex += 1;
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
_secondaryAnimation.posx = devilTrajectory[secTrajIndex][0] - 15;
_secondaryAnimation.posy = devilTrajectory[secTrajIndex][1] - 42;
if (secTrajIndex <= 8) {
_secondaryAnimation.dir = 2;
_secondaryAnimation.depth = 1;
} else if (secTrajIndex <= 33) {
_secondaryAnimation.dir = 2;
_secondaryAnimation.depth = 14;
} else if (secTrajIndex <= 63) {
_secondaryAnimation.dir = 1;
_secondaryAnimation.depth = 14;
} else {
_secondaryAnimation.dir = 0;
_secondaryAnimation.depth = 3;
}
_chrono->_gameTickHalfSpeed = true;
sprites(false);
_chrono->_gameTick = false;
_graphics->advancePaletteAnim();
_screen->update();
}
} while (!exitLoop && !shouldQuit());
clearAnimation();
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
}
void updateMovementGrids() {
uint j1arm, j2arm;
byte i1arm, i2arm;
j1arm = (g_engine->_currentRoomData->secondaryAnimTrajectory[g_engine->_currentSecondaryTrajectoryIndex - 1].x / kXGridCount) + 1;
j2arm = (g_engine->_currentRoomData->secondaryAnimTrajectory[g_engine->_currentSecondaryTrajectoryIndex - 1].y / kYGridCount) + 1;
if ((g_engine->_oldposx != j1arm) || (g_engine->_oldposy != j2arm)) {
for (i1arm = 0; i1arm < g_engine->_maxXGrid; i1arm++)
for (i2arm = 0; i2arm < g_engine->_maxYGrid; i2arm++) {
g_engine->_currentRoomData->walkAreasGrid[g_engine->_oldposx + i1arm][g_engine->_oldposy + i2arm] = g_engine->_movementGridForSecondaryAnim[i1arm][i2arm];
g_engine->_currentRoomData->mouseGrid[g_engine->_oldposx + i1arm][g_engine->_oldposy + i2arm] = g_engine->_mouseGridForSecondaryAnim[i1arm][i2arm];
}
for (i1arm = 0; i1arm < g_engine->_maxXGrid; i1arm++)
for (i2arm = 0; i2arm < g_engine->_maxYGrid; i2arm++) {
g_engine->_movementGridForSecondaryAnim[i1arm][i2arm] = g_engine->_currentRoomData->walkAreasGrid[j1arm + i1arm][j2arm + i2arm];
if (g_engine->_maskGridSecondaryAnim[i1arm][i2arm] > 0)
g_engine->_currentRoomData->walkAreasGrid[j1arm + i1arm][j2arm + i2arm] = g_engine->_maskGridSecondaryAnim[i1arm][i2arm];
g_engine->_mouseGridForSecondaryAnim[i1arm][i2arm] = g_engine->_currentRoomData->mouseGrid[j1arm + i1arm][j2arm + i2arm];
if (g_engine->_maskMouseSecondaryAnim[i1arm][i2arm] > 0)
g_engine->_currentRoomData->mouseGrid[j1arm + i1arm][j2arm + i2arm] = g_engine->_maskMouseSecondaryAnim[i1arm][i2arm];
}
g_engine->_oldposx = j1arm;
g_engine->_oldposy = j2arm;
g_engine->_oldGridX = 0;
g_engine->_oldGridY = 0;
}
}
void sprites(bool drawCharacter);
static void assembleBackground() {
uint posabs;
// copies the entire clean background in backgroundCopy back into background
g_engine->_graphics->restoreBackground();
posabs = 4 + g_engine->_dirtyMainSpriteY * 320 + g_engine->_dirtyMainSpriteX;
uint16 w, h;
w = READ_LE_UINT16(g_engine->_characterDirtyRect);
h = READ_LE_UINT16(g_engine->_characterDirtyRect + 2);
w++;
h++;
g_engine->_dirtyMainSpriteX2 = g_engine->_dirtyMainSpriteX + w;
g_engine->_dirtyMainSpriteY2 = g_engine->_dirtyMainSpriteY + h;
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
int pos = posabs + j * 320 + i;
int destPos = 4 + (j * w + i);
g_engine->_characterDirtyRect[destPos] = g_engine->_sceneBackground[pos];
}
}
}
/**
* calculates the overlapping area between the source image and the background,
* then "blits" (copies) the pixels from the image to the overlapping area of the background, respecting transparency.
*/
static void assembleImage(const byte *img, uint imgPosX, uint imgPosY) {
uint x, // starting point of the overlap
y;
uint incx, // width and height of the overlapping area
incy;
uint16 wImg = READ_LE_UINT16(img) + 1;
uint16 hImg = READ_LE_UINT16(img + 2) + 1;
uint16 wBg = READ_LE_UINT16(g_engine->_characterDirtyRect) + 1;
uint16 hBg = READ_LE_UINT16(g_engine->_characterDirtyRect + 2) + 1;
// This region calculates the overlapping area of (x, incx, y, incy)
{
if (imgPosX < g_engine->_dirtyMainSpriteX)
x = g_engine->_dirtyMainSpriteX;
else
x = imgPosX;
if (imgPosX + wImg < static_cast<uint>(g_engine->_dirtyMainSpriteX + wBg))
incx = imgPosX + wImg - x;
else
incx = g_engine->_dirtyMainSpriteX + wBg - x;
if (imgPosY < g_engine->_dirtyMainSpriteY)
y = g_engine->_dirtyMainSpriteY;
else
y = imgPosY;
if (imgPosY + hImg < static_cast<uint>(g_engine->_dirtyMainSpriteY + hBg))
incy = imgPosY + hImg - y;
else
incy = g_engine->_dirtyMainSpriteY + hBg - y;
} // end of region calculating overlapping area
for (uint j = 0; j < incy; j++) {
for (uint i = 0; i < incx; i++) {
int bgOffset = 4 + ((y - g_engine->_dirtyMainSpriteY) + j) * wBg + i + (x - g_engine->_dirtyMainSpriteX);
int imgOffset = 4 + (y - imgPosY + j) * wImg + i + (x - imgPosX);
if (img[imgOffset] != 0) {
g_engine->_characterDirtyRect[bgOffset] = img[imgOffset];
}
}
}
}
static void overlayLayers() {
if (g_engine->_screenLayers[g_engine->_curDepth] != nullptr) {
if (
(g_engine->_depthMap[g_engine->_curDepth].posx <= g_engine->_dirtyMainSpriteX2) &&
(g_engine->_depthMap[g_engine->_curDepth].posx2 > g_engine->_dirtyMainSpriteX) &&
(g_engine->_depthMap[g_engine->_curDepth].posy < g_engine->_dirtyMainSpriteY2) &&
(g_engine->_depthMap[g_engine->_curDepth].posy2 > g_engine->_dirtyMainSpriteY)) {
assembleImage(g_engine->_screenLayers[g_engine->_curDepth], g_engine->_depthMap[g_engine->_curDepth].posx, g_engine->_depthMap[g_engine->_curDepth].posy);
}
}
}
void drawMainCharacter() {
uint16 tempW;
uint16 tempH;
tempW = READ_LE_UINT16(g_engine->_curCharacterAnimationFrame);
tempH = READ_LE_UINT16(g_engine->_curCharacterAnimationFrame + 2);
tempW += 6;
tempH += 6;
if (g_engine->_dirtyMainSpriteY + tempH > 140) {
tempH -= (g_engine->_dirtyMainSpriteY + tempH) - 140;
}
if (g_engine->_dirtyMainSpriteX + tempW > 320) {
tempW -= (g_engine->_dirtyMainSpriteX + tempW) - 320;
}
g_engine->_characterDirtyRect = (byte *)malloc((tempW + 1) * (tempH + 1) + 4);
WRITE_LE_UINT16(g_engine->_characterDirtyRect, tempW);
WRITE_LE_UINT16(g_engine->_characterDirtyRect + 2, tempH);
assembleBackground();
g_engine->_curDepth = 0;
while (g_engine->_curDepth != kDepthLevelCount) {
overlayLayers();
if (g_engine->_mainCharAnimation.depth == g_engine->_curDepth)
assembleImage(g_engine->_curCharacterAnimationFrame, g_engine->_characterPosX, g_engine->_characterPosY);
g_engine->_curDepth += 1;
}
g_engine->_graphics->putImg(g_engine->_dirtyMainSpriteX, g_engine->_dirtyMainSpriteY, g_engine->_characterDirtyRect);
free(g_engine->_characterDirtyRect);
}
void TotEngine::sprites(bool drawMainCharachter) {
// grabs the current frame from the walk cycle
_curCharacterAnimationFrame = _mainCharAnimation.bitmap[_charFacingDirection][_iframe];
_dirtyMainSpriteX = _characterPosX - 3;
_dirtyMainSpriteY = _characterPosY - 3;
if (_isSecondaryAnimationEnabled) {
if (_currentRoomData->secondaryTrajectoryLength > 1) {
updateMovementGrids();
}
if (_chrono->_gameTickHalfSpeed) {
if (_isPeterCoughing && !_sound->isVocPlaying()) {
_iframe2 = 0;
}
newSecondaryAnimationFrame();
Common::copy(_secondaryAnimation.bitmap[_secondaryAnimation.dir][_iframe2], _secondaryAnimation.bitmap[_secondaryAnimation.dir][_iframe2] + _secondaryAnimFrameSize, _curSecondaryAnimationFrame);
}
uint16 curCharFrameW = READ_LE_UINT16(_curCharacterAnimationFrame);
uint16 curCharFrameH = READ_LE_UINT16(_curCharacterAnimationFrame + 2);
uint16 secAnimW = READ_LE_UINT16(_curSecondaryAnimationFrame);
uint16 secAnimH = READ_LE_UINT16(_curSecondaryAnimationFrame + 2);
if (
((_secondaryAnimation.posx < (_characterPosX + curCharFrameW) + 4) &&
((_secondaryAnimation.posx + secAnimW + 1) > _dirtyMainSpriteX) &&
(_secondaryAnimation.posy < (_characterPosY + curCharFrameH + 4))) &&
((_secondaryAnimation.posy + secAnimH + 1) > _dirtyMainSpriteY)) { // Character is in the area of the animation
if (_secondaryAnimation.posx < _characterPosX) {
_dirtyMainSpriteX = _secondaryAnimation.posx - 3;
}
if (_secondaryAnimation.posy < _characterPosY) {
_dirtyMainSpriteY = _secondaryAnimation.posy - 3;
}
uint16 patchW = secAnimW + curCharFrameW + 6;
uint16 patchH;
if ((curCharFrameH + _characterPosY) > (_secondaryAnimation.posy + secAnimH)) {
patchH = curCharFrameH + 6 + abs(_characterPosY - _secondaryAnimation.posy);
} else {
patchH = secAnimH + 6 + abs(_characterPosY - _secondaryAnimation.posy);
}
if (_dirtyMainSpriteY + patchH > 140) {
patchH -= (_dirtyMainSpriteY + patchH) - 140 + 1;
}
if (_dirtyMainSpriteX + patchW > 320) {
patchW -= (_dirtyMainSpriteX + patchW) - 320 + 1;
}
_characterDirtyRect = (byte *)malloc((patchW + 1) * (patchH + 1) + 4);
WRITE_LE_UINT16(_characterDirtyRect, patchW);
WRITE_LE_UINT16(_characterDirtyRect + 2, patchH);
assembleBackground();
_curDepth = 0;
while (_curDepth != kDepthLevelCount) {
overlayLayers();
if (_secondaryAnimation.depth == _curDepth)
assembleImage(_curSecondaryAnimationFrame, _secondaryAnimation.posx, _secondaryAnimation.posy);
if (_mainCharAnimation.depth == _curDepth)
assembleImage(_curCharacterAnimationFrame, _characterPosX, _characterPosY);
_curDepth += 1;
}
_graphics->putImg(_dirtyMainSpriteX, _dirtyMainSpriteY, _characterDirtyRect);
free(_characterDirtyRect);
} else { // character and animation are in different parts of the screen
if (drawMainCharachter) {
drawMainCharacter();
}
_dirtyMainSpriteX = _secondaryAnimation.posx - 3;
_dirtyMainSpriteY = _secondaryAnimation.posy - 3;
secAnimW = READ_LE_UINT16(_curSecondaryAnimationFrame) + 6;
secAnimH = READ_LE_UINT16(_curSecondaryAnimationFrame + 2) + 6;
if (_dirtyMainSpriteY + secAnimH > 140) {
secAnimH -= (_dirtyMainSpriteY + secAnimH) - 140 + 1;
}
if (_dirtyMainSpriteX + secAnimW > 320) {
secAnimW -= (_dirtyMainSpriteX + secAnimW) - 320 + 1;
}
_characterDirtyRect = (byte *)malloc((secAnimW + 1) * (secAnimH + 1) + 4);
WRITE_LE_UINT16(_characterDirtyRect, secAnimW);
WRITE_LE_UINT16(_characterDirtyRect + 2, secAnimH);
assembleBackground();
_curDepth = 0;
while (_curDepth != kDepthLevelCount) {
overlayLayers();
if (_secondaryAnimation.depth == _curDepth)
assembleImage(_curSecondaryAnimationFrame, _secondaryAnimation.posx, _secondaryAnimation.posy);
_curDepth += 1;
}
_graphics->putImg(_dirtyMainSpriteX, _dirtyMainSpriteY, _characterDirtyRect);
free(_characterDirtyRect);
}
} else if (drawMainCharachter) {
drawMainCharacter();
}
}
void TotEngine::adjustKey() {
_iframe = 0;
calculateTrajectory(129, 13);
_charFacingDirection = 0;
do {
_characterPosX = _trajectory[_currentTrajectoryIndex].x;
_characterPosY = _trajectory[_currentTrajectoryIndex].y;
_iframe++;
_currentTrajectoryIndex += 1;
emptyLoop();
_chrono->_gameTick = false;
_graphics->advancePaletteAnim();
sprites(true);
} while (_currentTrajectoryIndex != _trajectoryLength);
_charFacingDirection = 3;
emptyLoop();
_chrono->_gameTick = false;
sprites(true);
}
void TotEngine::adjustKey2() {
_iframe = 0;
_charFacingDirection = 2;
_trajectoryLength = 1;
do {
_characterPosX = _trajectory[_currentTrajectoryIndex].x;
_characterPosY = _trajectory[_currentTrajectoryIndex].y;
_iframe++;
_currentTrajectoryIndex -= 1;
emptyLoop();
_chrono->_gameTick = false;
_graphics->advancePaletteAnim();
sprites(true);
} while (_currentTrajectoryIndex != 0);
emptyLoop();
_chrono->_gameTick = false;
sprites(true);
}
void TotEngine::animatedSequence(uint numSequence) {
Common::File animationFile;
uint repIndex, animIndex;
uint16 animFrameSize;
uint animX, animY;
int tmpCharacterPosX;
byte secFrameCount;
byte *animptr;
switch (numSequence) {
case 1: {
tmpCharacterPosX = _characterPosX;
_characterPosX = 3;
if (!animationFile.open("POZO01.DAT")) {
showError(277);
}
animX = 127;
animY = 70;
animFrameSize = animationFile.readUint16LE();
secFrameCount = animationFile.readByte();
animationFile.readByte();
animptr = (byte *)malloc(animFrameSize);
for (uint loopIdx = 1; loopIdx <= 3; loopIdx++) {
_sound->playVoc("POZO", 180395, 6034);
animIndex = 0;
do {
emptyLoop();
_chrono->_gameTick = false;
if (_chrono->_gameTickHalfSpeed) {
if (_currentSecondaryTrajectoryIndex >= _currentRoomData->secondaryTrajectoryLength)
_currentSecondaryTrajectoryIndex = 1;
else
_currentSecondaryTrajectoryIndex += 1;
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
sprites(false);
animationFile.read(animptr, animFrameSize);
_graphics->putImg(animX, animY, animptr);
animIndex += 1;
}
} while (animIndex != secFrameCount && !shouldQuit());
animationFile.seek(4);
}
free(animptr);
animationFile.close();
_characterPosX = tmpCharacterPosX;
} break;
case 2: {
if (!animationFile.open("POZOATR.DAT")) {
showError(277);
}
animX = 127;
tmpCharacterPosX = _characterPosX;
_characterPosX = 3;
animY = 70;
animFrameSize = animationFile.readUint16LE();
secFrameCount = animationFile.readByte();
animationFile.readByte();
animptr = (byte *)malloc(animFrameSize);
for (repIndex = 1; repIndex <= 3; repIndex++) {
_sound->playVoc("POZO", 180395, 6034);
animIndex = 0;
do {
emptyLoop();
_chrono->_gameTick = false;
if (_chrono->_gameTickHalfSpeed) {
if (_currentSecondaryTrajectoryIndex >= _currentRoomData->secondaryTrajectoryLength)
_currentSecondaryTrajectoryIndex = 1;
else
_currentSecondaryTrajectoryIndex += 1;
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
sprites(false);
animationFile.read(animptr, animFrameSize);
_graphics->putImg(animX, animY, animptr);
animIndex += 1;
}
} while (animIndex != secFrameCount && !shouldQuit());
animationFile.seek(4);
}
_sound->stopVoc();
free(animptr);
animationFile.close();
_characterPosX = tmpCharacterPosX;
} break;
case 3: {
tmpCharacterPosX = _characterPosX;
_characterPosX = 3;
if (!animationFile.open("POZO02.DAT")) {
showError(277);
}
animX = 127;
animY = 70;
animFrameSize = animationFile.readUint16LE();
secFrameCount = animationFile.readByte();
animationFile.readByte();
animptr = (byte *)malloc(animFrameSize);
animIndex = 0;
do {
emptyLoop();
_chrono->_gameTick = false;
if (_chrono->_gameTickHalfSpeed) {
if (_currentSecondaryTrajectoryIndex >= _currentRoomData->secondaryTrajectoryLength)
_currentSecondaryTrajectoryIndex = 1;
else
_currentSecondaryTrajectoryIndex += 1;
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
sprites(false);
animationFile.read(animptr, animFrameSize);
_graphics->putImg(animX, animY, animptr);
animIndex += 1;
}
} while (animIndex != secFrameCount && !shouldQuit());
free(animptr);
animationFile.close();
_iframe = 0;
_charFacingDirection = 2;
emptyLoop();
_chrono->_gameTick = false;
_characterPosX = tmpCharacterPosX;
sprites(true);
} break;
case 4: {
adjustKey();
if (!animationFile.open("TIOLLAVE.DAT")) {
showError(277);
}
animX = 85;
animY = 15;
animFrameSize = animationFile.readUint16LE();
secFrameCount = animationFile.readByte();
animationFile.readByte();
animptr = (byte *)malloc(animFrameSize);
for (animIndex = 1; animIndex <= 31; animIndex++) {
animationFile.read(animptr, animFrameSize);
emptyLoop();
_chrono->_gameTick = false;
_graphics->advancePaletteAnim();
_graphics->putShape(animX, animY, animptr);
}
clearScreenLayer(_curObject->depth - 1);
_graphics->restoreBackground();
animIndex = _mainCharAnimation.depth;
_mainCharAnimation.depth = 30;
clearScreenLayer(12);
_screenLayers[12] = animptr;
_depthMap[12].posx = animX;
_depthMap[12].posy = animY;
assembleScreen();
_graphics->drawScreen(_sceneBackground);
// do not clear layer yet, needed for next frames
_screenLayers[12] = nullptr;
_mainCharAnimation.depth = animIndex;
drawInventory();
for (animIndex = 32; animIndex <= secFrameCount; animIndex++) {
animationFile.read(animptr, animFrameSize);
emptyLoop();
_chrono->_gameTick = false;
_graphics->advancePaletteAnim();
_graphics->putImg(animX, animY, animptr);
if (shouldQuit()) {
break;
}
}
adjustKey2();
free(animptr);
animationFile.close();
} break;
case 5: {
if (!animationFile.open("TIOSACO.DAT")) {
showError(277);
}
animX = 204;
animY = 44;
animFrameSize = animationFile.readUint16LE();
secFrameCount = animationFile.readByte();
animationFile.readByte();
animptr = (byte *)malloc(animFrameSize);
for (animIndex = 1; animIndex <= 8; animIndex++) {
animationFile.read(animptr, animFrameSize);
emptyLoop();
_chrono->_gameTick = false;
_graphics->putShape(animX, animY, animptr);
if (shouldQuit()) {
break;
}
}
animIndex = _mainCharAnimation.depth;
_mainCharAnimation.depth = 30;
clearScreenLayer(12);
_screenLayers[12] = animptr;
_depthMap[12].posx = animX;
_depthMap[12].posy = animY;
disableSecondAnimation();
_mainCharAnimation.depth = animIndex;
_graphics->drawScreen(_sceneBackground);
// do not clear layer yet, needed for next frames
_screenLayers[12] = nullptr;
for (animIndex = 9; animIndex <= secFrameCount; animIndex++) {
animationFile.read(animptr, animFrameSize);
emptyLoop();
_chrono->_gameTick = false;
emptyLoop();
_chrono->_gameTick = false;
_graphics->putShape(animX, animY, animptr);
if (shouldQuit()) {
break;
}
}
free(animptr);
animationFile.close();
_iframe = 0;
_charFacingDirection = 2;
emptyLoop();
_chrono->_gameTick = false;
sprites(true);
} break;
case 6: {
_currentRoomData->animationFlag = false;
if (!animationFile.open("AZCCOG.DAT")) {
showError(277);
}
animFrameSize = animationFile.readUint16LE();
secFrameCount = animationFile.readByte();
animationFile.readByte();
if (g_engine->_screenLayers[6]) {
free(g_engine->_screenLayers[6]);
}
_screenLayers[6] = (byte *)malloc(animFrameSize);
_depthMap[6].posx = _secondaryAnimation.posx + 5;
_depthMap[6].posy = _secondaryAnimation.posy - 6;
animIndex = 0;
do {
emptyLoop();
_chrono->_gameTick = false;
_graphics->advancePaletteAnim();
if (_chrono->_gameTickHalfSpeed) {
animationFile.read(_screenLayers[6], animFrameSize);
Common::copy(_screenLayers[6], _screenLayers[6] + animFrameSize, _sceneBackground + 44900);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animIndex += 1;
if (animIndex == 8)
_sound->playVoc("PUFF", 191183, 18001);
}
} while (animIndex != secFrameCount && !shouldQuit());
animationFile.close();
_sound->stopVoc();
clearScreenLayer(6);
_currentRoomData->animationFlag = true;
} break;
}
}
void TotEngine::loadScreenData(uint screenNumber) {
_currentRoomNumber = screenNumber;
_rooms->seek(screenNumber * kRoomRegSize, SEEK_SET);
if (_currentRoomData) {
delete _currentRoomData;
}
_currentRoomData = readScreenDataFile(_rooms);
loadScreen();
for (int i = 0; i < 15; i++) {
RoomBitmapRegister &bitmap = _currentRoomData->screenLayers[i];
if (bitmap.bitmapSize > 0) {
loadScreenLayer(bitmap.coordx, bitmap.coordy, bitmap.bitmapSize, bitmap.bitmapPointer, bitmap.depth);
}
}
if (_currentRoomData->animationFlag && _currentRoomData->code != 24) {
loadAnimation(_currentRoomData->animationName);
_iframe2 = 0;
_currentSecondaryTrajectoryIndex = 1;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
if (_currentRoomData->animationName == "FUENTE01")
_secondaryAnimation.depth = 0;
else {
updateSecondaryAnimationDepth();
}
for (int i = 0; i < _maxXGrid; i++)
for (int j = 0; j < _maxYGrid; j++) {
if (_maskGridSecondaryAnim[i][j] > 0)
_currentRoomData->walkAreasGrid[_oldposx + i][_oldposy + j] = _maskGridSecondaryAnim[i][j];
if (_maskMouseSecondaryAnim[i][j] > 0)
_currentRoomData->mouseGrid[_oldposx + i][_oldposy + j] = _maskMouseSecondaryAnim[i][j];
}
} else
_currentRoomData->animationFlag = false;
updateMainCharacterDepth();
assembleScreen();
g_engine->_graphics->_paletteAnimFrame = 0;
}
/**
* Calculates a trajectory between the current position (xframe, yframe)
* and the target position (finalx, finaly) using bresenham's algorithm
*/
void TotEngine::calculateTrajectory(uint finalX, uint finalY) {
int deltaX = finalX - _characterPosX;
int deltaY = finalY - _characterPosY;
int incrXDiag = (deltaX >= 0) ? 1 : -1;
int incrYDiag = (deltaY >= 0) ? 1 : -1;
deltaX = abs(deltaX);
deltaY = abs(deltaY);
bool horizontalDominant = (deltaX >= deltaY);
if (!horizontalDominant) {
int tmp = deltaX;
deltaX = deltaY;
deltaY = tmp;
}
// step increments for straight moves
int straightXIncrease = horizontalDominant ? incrXDiag : 0;
int straightYIncrease = horizontalDominant ? 0 : incrYDiag;
int straightAmount = 2 * deltaY;
int slope = straightAmount - (2 * deltaX);
int dec = straightAmount - deltaX; // decision variable
// start at initial position
uint x = _characterPosX, y = _characterPosY;
int trajectorySteps = deltaX + 1; // number of steps
_currentTrajectoryIndex = 0;
_trajectoryLength = 0;
_trajectory[_trajectoryLength].x = x;
_trajectory[_trajectoryLength].y = y;
_trajectoryLength++;
while (--trajectorySteps) {
if (dec >= 0) {
x += incrXDiag;
y += incrYDiag;
dec += slope;
} else {
x += straightXIncrease;
y += straightYIncrease;
dec += straightAmount;
}
_trajectory[_trajectoryLength].x = x;
_trajectory[_trajectoryLength].y = y;
_trajectoryLength++;
}
// Ensure last value is also final position to account for overflow of the route
_trajectory[_trajectoryLength].x = finalX;
_trajectory[_trajectoryLength].y = finalY;
_trajectory[_trajectoryLength + 1].x = finalX;
_trajectory[_trajectoryLength + 1].y = finalY;
}
void TotEngine::lookAtObject(byte objectCode) {
byte yaux;
Common::String description;
bool foobar = false;
TextEntry textRef;
Palette secPalette;
_cpCounter2 = _cpCounter;
_mouse->hide();
_graphics->copyPalette(g_engine->_graphics->_pal, secPalette);
readObject(_inventory[objectCode].code);
_graphics->getImg(0, 0, 319, 139, _sceneBackground);
_graphics->partialFadeOut(234);
bar(0, 0, 319, 139, 0);
for (yaux = 1; yaux <= 12; yaux++)
buttonBorder(
120 - (yaux * 5), // x1
80 - (yaux * 5), // y1
200 + (yaux * 5), // x2
70 + (yaux * 5), // y2
251, // color1
251, // color2
251, // color3
251, // color4
0 // color5
);
drawMenu(4);
if (_curObject->used[0] != 9) {
if (_curObject->beforeUseTextRef != 0) {
readTextFile();
textRef = readTextRegister(_curObject->beforeUseTextRef);
description = textRef.text;
for (yaux = 0; yaux < textRef.text.size(); yaux++)
description.setChar(_decryptionKey[yaux] ^ textRef.text[yaux], yaux);
displayObjectDescription(description);
_verbFile.close();
} else {
description = _inventory[objectCode].objectName;
displayObjectDescription(description);
}
} else {
if (_curObject->afterUseTextRef != 0) {
readTextFile();
textRef = readTextRegister(_curObject->afterUseTextRef);
description = textRef.text;
for (yaux = 0; yaux < textRef.text.size(); yaux++)
description.setChar(_decryptionKey[yaux] ^ textRef.text[yaux], yaux);
displayObjectDescription(description);
_verbFile.close();
} else {
description = _inventory[objectCode].objectName;
displayObjectDescription(description);
}
}
drawFlc(125, 70, _curObject->rotatingObjectAnimation, 60000, 9, 0, false, true, true, foobar);
_graphics->sceneTransition(true, nullptr, 3);
_graphics->partialFadeOut(234);
assembleScreen();
_graphics->drawScreen(_sceneBackground);
_graphics->copyPalette(secPalette, g_engine->_graphics->_pal);
_graphics->partialFadeIn(234);
_mouse->show();
}
void TotEngine::useInventoryObjectWithInventoryObject(int16 objectCode1, int16 objectCode2) {
byte invIndex, indobj1, indobj2;
readObject(_sceneObjectsData, objectCode1, _curObject);
if (_curObject->used[0] != 1 || _curObject->useWith != objectCode2) {
drawText(getRandom(11) + 1022);
return;
}
invIndex = 0;
while (_inventory[invIndex].code != objectCode1) {
invIndex += 1;
}
indobj1 = invIndex;
invIndex = 0;
while (_inventory[invIndex].code != objectCode2) {
invIndex += 1;
}
indobj2 = invIndex;
uint textRef = _curObject->useTextRef;
if (_curObject->replaceWith == 0) {
readObject(_sceneObjectsData, objectCode1, _curObject);
_curObject->used[0] = 9;
saveObject(_curObject, _sceneObjectsData);
readObject(_sceneObjectsData, objectCode2, _curObject);
_curObject->used[0] = 9;
saveObject(_curObject, _sceneObjectsData);
} else {
readObject(_sceneObjectsData, _curObject->replaceWith, _curObject);
_inventory[indobj1].bitmapIndex = _curObject->objectIconBitmap;
_inventory[indobj1].code = _curObject->code;
_inventory[indobj1].objectName = _curObject->name;
for (indobj1 = indobj2; indobj1 < (kInventoryIconCount - 1); indobj1++) {
_inventory[indobj1].bitmapIndex = _inventory[indobj1 + 1].bitmapIndex;
_inventory[indobj1].code = _inventory[indobj1 + 1].code;
_inventory[indobj1].objectName = _inventory[indobj1 + 1].objectName;
}
_mouse->hide();
drawInventory();
_mouse->show();
}
if (textRef > 0)
drawText(textRef);
}
void TotEngine::calculateRoute(byte zone1, byte zone2, bool extraCorrection, bool barredZone) {
// Resets the entire route
for (_trajectorySteps = 0; _trajectorySteps < 7; _trajectorySteps++) {
_mainRoute[_trajectorySteps].x = 0;
_mainRoute[_trajectorySteps].y = 0;
}
_trajectorySteps = 0;
// Starts first element of route with current position
_mainRoute[0].x = _characterPosX;
_mainRoute[0].y = _characterPosY;
Common::Point point;
do {
_trajectorySteps += 1;
point = _currentRoomData->trajectories[zone1 - 1][zone2 - 1][_trajectorySteps - 1];
if (point.x < (kCharacterCorrectionX + 3))
_mainRoute[_trajectorySteps].x = 3;
else
_mainRoute[_trajectorySteps].x = point.x - kCharacterCorrectionX;
if (point.y < (kCharacerCorrectionY + 3))
_mainRoute[_trajectorySteps].y = 3;
else
_mainRoute[_trajectorySteps].y = point.y - kCharacerCorrectionY;
} while (point.y != 9999 && _trajectorySteps != 5);
if (zone2 < 10) {
if (point.y == 9999) {
_mainRoute[_trajectorySteps].x = _xframe2 - kCharacterCorrectionX;
_mainRoute[_trajectorySteps].y = _yframe2 - kCharacerCorrectionY;
} else {
_mainRoute[6].x = _xframe2 - kCharacterCorrectionX;
_mainRoute[6].y = _yframe2 - kCharacerCorrectionY;
_trajectorySteps = 6;
}
} else {
if ((_mainRoute[_trajectorySteps].y + kCharacerCorrectionY) == 9999) {
_trajectorySteps -= 1;
}
if (extraCorrection) {
switch (_currentRoomData->code) {
case 5:
if (zone2 == 27)
_trajectorySteps += 1;
break;
case 6:
if (zone2 == 21)
_trajectorySteps += 1;
break;
}
}
}
if (extraCorrection && barredZone) {
_trajectorySteps -= 1;
}
// Sets xframe2 now to be the number of steps in the route
_xframe2 = _trajectorySteps;
// Sets yframe2 to now be current step
_yframe2 = 1;
_trajectoryLength = 10;
_currentTrajectoryIndex = 30;
}
void TotEngine::goToObject(byte zone1, byte zone2) {
bool barredZone = false;
_cpCounter2 = _cpCounter;
for (int i = 0; i < 5; i++) {
if (_currentRoomData->doors[i].doorcode == zone2) {
barredZone = true;
break;
}
}
if (_currentRoomData->code == 21 && _currentRoomData->animationFlag) {
if ((zone2 >= 1 && zone2 <= 5) ||
(zone2 >= 9 && zone2 <= 13) ||
(zone2 >= 18 && zone2 <= 21) ||
zone2 == 25) {
_targetZone = 7;
_mouse->mouseClickX = 232;
_mouse->mouseClickY = 75;
zone2 = 7;
}
if (zone2 == 24) {
barredZone = false;
_targetZone = 7;
_mouse->mouseClickX = 232;
_mouse->mouseClickY = 75;
zone2 = 7;
}
}
if (zone1 < 10) {
_xframe2 = _mouse->mouseClickX + 7;
_yframe2 = _mouse->mouseClickY + 7;
_mouse->hide();
calculateRoute(zone1, zone2, true, barredZone);
do {
_chrono->updateChrono();
g_engine->_events->pollEvent();
advanceAnimations(barredZone, false);
_screen->update();
g_system->delayMillis(10);
} while (_xframe2 != 0);
_iframe = 0;
sprites(true);
_mouse->show();
}
}
void TotEngine::updateSecondaryAnimationDepth() {
uint animationPos = _secondaryAnimation.posy + _secondaryAnimHeight - 1;
if (animationPos && animationPos <= 56) {
_secondaryAnimation.depth = 0;
} else if (animationPos >= 57 && animationPos <= 64) {
_secondaryAnimation.depth = 1;
} else if (animationPos >= 65 && animationPos <= 72) {
_secondaryAnimation.depth = 2;
} else if (animationPos >= 73 && animationPos <= 80) {
_secondaryAnimation.depth = 3;
} else if (animationPos >= 81 && animationPos <= 88) {
_secondaryAnimation.depth = 4;
} else if (animationPos >= 89 && animationPos <= 96) {
_secondaryAnimation.depth = 5;
} else if (animationPos >= 97 && animationPos <= 104) {
_secondaryAnimation.depth = 6;
} else if (animationPos >= 105 && animationPos <= 112) {
_secondaryAnimation.depth = 7;
} else if (animationPos >= 113 && animationPos <= 120) {
_secondaryAnimation.depth = 8;
} else if (animationPos >= 121 && animationPos <= 140) {
_secondaryAnimation.depth = 9;
}
}
void TotEngine::updateMainCharacterDepth() {
if (_characterPosY && _characterPosY <= 7) {
_mainCharAnimation.depth = 0;
} else if (_characterPosY >= 8 && _characterPosY <= 17) {
_mainCharAnimation.depth = 1;
} else if (_characterPosY >= 18 && _characterPosY <= 25) {
_mainCharAnimation.depth = 2;
} else if (_characterPosY >= 26 && _characterPosY <= 33) {
_mainCharAnimation.depth = 3;
} else if (_characterPosY >= 34 && _characterPosY <= 41) {
_mainCharAnimation.depth = 4;
} else if (_characterPosY >= 42 && _characterPosY <= 49) {
_mainCharAnimation.depth = 5;
} else if (_characterPosY >= 50 && _characterPosY <= 57) {
_mainCharAnimation.depth = 6;
} else if (_characterPosY >= 58 && _characterPosY <= 65) {
_mainCharAnimation.depth = 7;
} else if (_characterPosY >= 66 && _characterPosY <= 73) {
_mainCharAnimation.depth = 8;
} else if (_characterPosY >= 74 && _characterPosY <= 139) {
_mainCharAnimation.depth = 9;
}
}
void TotEngine::advanceAnimations(bool barredZone, bool animateMouse) {
if (_chrono->_gameTick) {
if (_currentRoomData->animationFlag && _chrono->_gameTickHalfSpeed) {
if (_isPeterCoughing && (getRandom(100) == 1) && !_sound->isVocPlaying() && _mintTopic[0] == false) {
debug("Playing tos");
_sound->playVoc("TOS", 258006, 14044);
}
if (_currentSecondaryTrajectoryIndex >= _currentRoomData->secondaryTrajectoryLength)
_currentSecondaryTrajectoryIndex = 1;
else
_currentSecondaryTrajectoryIndex += 1;
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
switch (_currentRoomData->code) {
case 23:
_secondaryAnimation.depth = 0;
break;
case 24:
_secondaryAnimation.depth = 14;
break;
default:
updateSecondaryAnimationDepth();
}
}
// This means character needs to walk
if (_xframe2 > 0) {
if (_charFacingDirection == 1 || _charFacingDirection == 3) {
_currentTrajectoryIndex += 1;
}
_currentTrajectoryIndex += 1;
// yframe2, xframe2 now represent max steps and current step
if (_yframe2 <= _xframe2) {
if (_currentTrajectoryIndex > _trajectoryLength) {
_element1 = _mainRoute[_yframe2].x - _mainRoute[_yframe2 - 1].x;
_element2 = _mainRoute[_yframe2].y - _mainRoute[_yframe2 - 1].y;
if ((abs(_element1) > 2) || (abs(_element2) > 2)) {
if (abs(_element2) > (abs(_element1) + 5)) {
if (_element2 < 0)
_charFacingDirection = 0;
else
_charFacingDirection = 2;
} else {
if (_element1 > 0)
_charFacingDirection = 1;
else
_charFacingDirection = 3;
}
}
_yframe2 += 1;
calculateTrajectory(_mainRoute[_yframe2 - 1].x, _mainRoute[_yframe2 - 1].y);
}
} else if (_currentTrajectoryIndex >= _trajectoryLength) {
_xframe2 = 0;
if (!_roomChange) {
_element1 = (_mouse->mouseX + 7) - (_characterPosX + kCharacterCorrectionX);
_element2 = (_mouse->mouseY + 7) - (_characterPosY + kCharacerCorrectionY);
if (abs(_element2) > (abs(_element1) + 20)) {
if (_element2 < 0)
_charFacingDirection = 0;
else
_charFacingDirection = 2;
} else {
if (_element1 > 0)
_charFacingDirection = 1;
else
_charFacingDirection = 3;
}
}
}
_iframe++;
if (_iframe > kWalkFrameCount)
_iframe = 0;
} else {
_iframe = 0;
if (barredZone == false && !_roomChange) {
_element1 = (_mouse->mouseX + 7) - (_characterPosX + kCharacterCorrectionX);
_element2 = (_mouse->mouseY + 7) - (_characterPosY + kCharacerCorrectionY);
if (abs(_element2) > (abs(_element1) + 20)) {
if (_element2 < 0)
_charFacingDirection = 0;
else
_charFacingDirection = 2;
} else {
if (_element1 > 0)
_charFacingDirection = 1;
else
_charFacingDirection = 3;
}
}
}
_characterPosX = _trajectory[_currentTrajectoryIndex].x;
_characterPosY = _trajectory[_currentTrajectoryIndex].y;
updateMainCharacterDepth();
if (_isDrawingEnabled) {
sprites(true);
}
_chrono->_gameTick = false;
_graphics->advancePaletteAnim();
}
}
void TotEngine::actionLineText(const Common::String &actionLine) {
euroText(160, 144, actionLine, 255, Graphics::kTextAlignCenter);
}
void TotEngine::animateGive(uint dir, uint height) {
_charFacingDirection = dir;
for (uint i = 0; i < 5; i++) {
emptyLoop();
_chrono->_gameTick = false;
// Must add 1 to i because the original game uses 1-based indices
_iframe = 15 + 6 + 5 + height * 10 - (i + 1);
_graphics->advancePaletteAnim();
sprites(true);
}
_iframe = 0;
}
// Lean over to pick
void TotEngine::animatePickup1(uint dir, uint height) {
_charFacingDirection = dir;
for (uint i = 0; i < 5; i++) {
emptyLoop();
_chrono->_gameTick = false;
_iframe = 15 + height * 10 + (i + 1);
_graphics->advancePaletteAnim();
sprites(true);
_screen->update();
}
}
// Lean back after pick
void TotEngine::animatePickup2(uint dir, uint height) {
_charFacingDirection = dir;
for (uint i = 0; i < 5; i++) {
emptyLoop();
_chrono->_gameTick = false;
_iframe = 15 + 5 + height * 10 + (i + 1);
_graphics->advancePaletteAnim();
sprites(true);
_screen->update();
}
emptyLoop();
_chrono->_gameTick = false;
sprites(true);
_iframe = 0;
}
void TotEngine::animateOpen2(uint dir, uint height) {
_charFacingDirection = dir;
_cpCounter = _cpCounter2;
for (uint i = 0; i < 5; i++) {
emptyLoop();
_chrono->_gameTick = false;
_iframe = 15 + 6 + height * 10 - (i + 1);
_graphics->advancePaletteAnim();
sprites(true);
}
emptyLoop();
_chrono->_gameTick = false;
sprites(true);
_iframe = 0;
}
void TotEngine::animateBat() {
const uint batTrajectory[91][2] = {
{288, 40}, {289, 38}, {289, 36}, {289, 34}, {290, 32}, {290, 30}, {289, 31}, {288, 32},
{288, 34}, {286, 36}, {284, 38}, {282, 40}, {280, 42}, {278, 44}, {276, 46}, {274, 48},
{272, 50}, {270, 48}, {268, 46}, {266, 48}, {265, 50}, {264, 52}, {263, 54}, {263, 56},
{262, 58}, {261, 60}, {261, 62}, {261, 64}, {260, 66}, {260, 68}, {260, 70}, {260, 72},
{259, 74}, {259, 76}, {260, 78}, {262, 76}, {264, 74}, {266, 72}, {266, 74}, {266, 76},
{268, 78}, {270, 80}, {272, 82}, {274, 84}, {276, 86}, {278, 88}, {279, 90}, {280, 88},
{281, 86}, {282, 84}, {283, 82}, {283, 84}, {283, 86}, {283, 88}, {284, 90}, {284, 92},
{284, 94}, {284, 96}, {285, 98}, {285, 100}, {286, 98}, {288, 96}, {290, 94}, {290, 92},
{290, 90}, {289, 92}, {289, 94}, {289, 96}, {289, 98}, {289, 100}, {289, 102}, {288, 104},
{287, 106}, {287, 108}, {288, 110}, {288, 112}, {288, 114}, {289, 116}, {289, 114}, {289, 112},
{290, 110}, {290, 112}, {290, 114}, {289, 116}, {289, 118}, {289, 120}, {289, 122}, {289, 124},
{290, 122}, {290, 120}, {290, 118}
};
byte curAnimIFrame = 0;
uint currAnimWidth = 0, curAnimHeight = 0,
curAnimIdx = 0, curAnimLength = 0,
curAnimX = 0, curAnimY = 0,
curAnimDepth = 0, curAnimDir = 0;
bool loopBreak = false;
if (_currentRoomData->animationFlag) {
curAnimIFrame = _iframe2;
curAnimX = _secondaryAnimation.posx;
curAnimY = _secondaryAnimation.posy;
currAnimWidth = _secondaryAnimWidth;
curAnimHeight = _secondaryAnimHeight;
curAnimDepth = _secondaryAnimation.depth;
curAnimDir = _secondaryAnimation.dir;
clearAnimation();
}
loadBat();
_sound->stopVoc();
_sound->playVoc("MURCIEL", 160848, 4474);
curAnimIdx = 0;
curAnimLength = 87;
_iframe2 = 0;
_secondaryAnimation.depth = 14;
do {
_chrono->updateChrono();
if (_chrono->_gameTick) {
if (curAnimIdx == curAnimLength)
loopBreak = true;
curAnimIdx += 1;
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
_secondaryAnimation.posx = batTrajectory[curAnimIdx][0] - 20;
_secondaryAnimation.posy = batTrajectory[curAnimIdx][1];
_secondaryAnimation.dir = 0;
sprites(true);
_chrono->_gameTick = false;
if (curAnimIdx % 24 == 0)
_sound->playVoc();
_graphics->advancePaletteAnim();
}
_screen->update();
g_system->delayMillis(10);
} while (!loopBreak && !shouldQuit());
_sound->stopVoc();
clearAnimation();
if (_currentRoomData->animationFlag) {
_secondaryAnimWidth = currAnimWidth;
_secondaryAnimHeight = curAnimHeight;
setRoomTrajectories(_secondaryAnimHeight, _secondaryAnimWidth, RESTORE, false);
loadAnimation(_currentRoomData->animationName);
_iframe2 = curAnimIFrame;
_secondaryAnimation.posx = curAnimX;
_secondaryAnimation.posy = curAnimY;
_secondaryAnimation.depth = curAnimDepth;
_secondaryAnimation.dir = curAnimDir;
}
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
}
void TotEngine::updateVideo() {
readBitmap(_curObject->dropOverlay, _screenLayers[_curObject->depth - 1], _curObject->dropOverlaySize, 319);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
}
void TotEngine::nicheAnimation(byte nicheDir, int32 bitmap) {
uint bitmapOffset = 0;
int increment = 0;
// Room with Red
if (_currentRoomData->code == 24) {
if (g_engine->_screenLayers[1]) {
free(g_engine->_screenLayers[1]);
}
_screenLayers[1] = (byte *)malloc(3660);
readBitmap(1382874, _screenLayers[1], 3652, 319);
uint16 object1Width = READ_LE_UINT16(_screenLayers[1]);
uint16 object1Height = READ_LE_UINT16(_screenLayers[1] + 2);
_depthMap[1].posx = 211;
_depthMap[1].posy = 16;
_depthMap[1].posx2 = 211 + object1Width + 1;
_depthMap[1].posy2 = 16 + object1Height + 1;
}
switch (nicheDir) {
case 0: {
bitmapOffset = 44904;
increment = 1;
Common::copy(_screenLayers[0], _screenLayers[0] + 892, _sceneBackground + 44900);
readBitmap(bitmap, _screenLayers[0], 892, 319);
Common::copy(_screenLayers[0] + 4, _screenLayers[0] + 4 + 888, _sceneBackground + 44900 + 892);
} break;
case 1: { // object slides to reveal empty stand
bitmapOffset = 892 + 44900;
increment = -1;
// Reads the empty niche into a non-visible part of background
readBitmap(bitmap, _sceneBackground + 44900, 892, 319);
// Copies whatever is currently on the niche in a non-visible part of background contiguous with the above
Common::copy(_screenLayers[0] + 4, _screenLayers[0] + 4 + 888, _sceneBackground + 44900 + 892);
// We now have in consecutive pixels the empty stand and the object
} break;
}
uint16 nicheWidth = READ_LE_UINT16(_screenLayers[0]);
uint16 nicheHeight = READ_LE_UINT16(_screenLayers[0] + 2);
// Set the height to double to animate 2 images of the same height moving up/down
*(_sceneBackground + 44900 + 2) = (nicheHeight * 2) + 1;
_graphics->restoreBackground();
for (uint i = 1; i <= nicheHeight; i++) {
bitmapOffset = bitmapOffset + (increment * (nicheWidth + 1));
Common::copy(_sceneBackground + bitmapOffset, _sceneBackground + bitmapOffset + 888, _screenLayers[0] + 4);
assembleScreen();
_graphics->drawScreen(_sceneBackground);
_screen->update();
}
readBitmap(bitmap, _screenLayers[0], 892, 319);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
if (_currentRoomData->code == 24) {
clearScreenLayer(1);
}
}
void TotEngine::pickupScreenObject() {
byte inventoryIndex;
uint screenObject;
Common::Point p = _mouse->getClickCoordsWithinGrid();
uint correctedMouseX = p.x;
uint correctedMouseY = p.y;
screenObject = _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex;
if (screenObject == 0)
return;
readObject(screenObject);
goToObject(
_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount],
_currentRoomData->walkAreasGrid[correctedMouseX][correctedMouseY]);
if (_curObject->pickupable) {
_mouse->hide();
switch (_curObject->code) {
case 521: { // Corridor lamp
_currentRoomData->mouseGrid[10][11] = 19;
_currentRoomData->mouseGrid[9][12] = 18;
_currentRoomData->mouseGrid[10][12] = 18;
} break;
case 567: { // Pickup rubble
if (_currentRoomData->animationFlag) {
_mouse->show();
drawText(3226);
return;
}
} break;
case 590: // Ectoplasm
_caves[1] = true;
break;
case 665: // Bird
_caves[0] = true;
break;
case 676:
case 688: {
_caves[4] = true;
_isVasePlaced = false;
} break;
}
switch (_curObject->height) {
case 0: { // Pick up above
switch (_curObject->code) {
case 590: { // Ectoplasm
animatePickup1(3, 0);
animatePickup2(3, 0);
} break;
default: {
animatePickup1(_charFacingDirection, 0);
clearScreenLayer(_curObject->depth - 1);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(_charFacingDirection, 0);
}
}
} break;
case 1: { // Waist level
switch (_curObject->code) {
case 218: // Necronomicon
case 308: // Mistletoe
case 517: // mints
animatePickup1(0, 1);
animatePickup2(0, 1);
break;
case 223: { // table cloths
animatePickup1(0, 1);
_currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex = _curObject->replaceWith;
updateVideo();
animatePickup2(0, 1);
} break;
case 402: { // Kitchen table
animatePickup1(0, 1);
updateVideo();
animatePickup2(0, 1);
} break;
case 479: { // Scissors
animatePickup1(3, 1);
animatePickup2(3, 1);
} break;
case 521: { // Puts plaster and key on the floor
animatePickup1(0, 1);
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[1];
with.bitmapPointer = 775611;
with.bitmapSize = 36;
with.coordx = 80;
with.coordy = 56;
with.depth = 2;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[2];
with.bitmapPointer = 730743;
with.bitmapSize = 64;
with.coordx = 76;
with.coordy = 62;
with.depth = 1;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
clearScreenLayer(_curObject->depth -1);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(0, 1);
} break;
case 562: { // niche
switch (_currentRoomData->code) {
case 20: { // First scene with niche
if (_niche[0][_niche[0][3]] > 0) {
// Possibly
if (_niche[0][3] == 2 || _niche[0][_niche[0][3]] == 563) {
readObject(_niche[0][_niche[0][3]]);
_niche[0][_niche[0][3]] = 0;
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(4);
animatePickup1(3, 1);
readBitmap(1190768, _screenLayers[_curObject->depth - 1], 892, 319);
_currentRoomData->screenLayers[1].bitmapPointer = 1190768;
_currentRoomData->screenLayers[1].bitmapSize = 892;
_currentRoomData->screenLayers[1].coordx = 66;
_currentRoomData->screenLayers[1].coordy = 35;
_currentRoomData->screenLayers[1].depth = 1;
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(3, 1);
} else {
readObject(_niche[0][_niche[0][3]]);
_niche[0][_niche[0][3]] = 0;
_niche[0][3] += 1;
_niche[1][3] -= 1;
_currentRoomData->screenObjectIndex[9]->objectName = " ";
animatePickup1(3, 1);
readBitmap(1190768, _screenLayers[_curObject->depth - 1],
892, 319);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(3, 1);
_sound->playVoc("PLATAF", 375907, 14724);
_currentRoomData->screenLayers[1].bitmapSize = 892;
_currentRoomData->screenLayers[1].coordx = 66;
_currentRoomData->screenLayers[1].coordy = 35;
_currentRoomData->screenLayers[1].depth = 1;
switch (_niche[0][_niche[0][3]]) {
case 0: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(4);
nicheAnimation(0, 1190768);
_currentRoomData->screenLayers[1].bitmapPointer = 1190768;
} break;
case 561: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(5);
nicheAnimation(0, 1182652);
_currentRoomData->screenLayers[1].bitmapPointer = 1182652;
} break;
case 563: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(6);
nicheAnimation(0, 1186044);
_currentRoomData->screenLayers[1].bitmapPointer = 1186044;
} break;
case 615: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(7);
nicheAnimation(0, 1181760);
_currentRoomData->screenLayers[1].bitmapPointer = 1181760;
} break;
}
updateAltScreen(24);
}
} else {
_mouse->show();
drawText(1049 + getRandom(10));
_mouse->hide();
return;
}
} break;
case 24: { // Second scene with niche
if (_niche[1][_niche[1][3]] > 0 && _niche[1][3] != 1) {
if (_niche[1][3] == 2) {
readObject(_niche[1][2]);
_niche[1][2] = 0;
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(4);
animatePickup1(0, 1);
readBitmap(1399610, _screenLayers[_curObject->depth - 1], 892, 319);
_currentRoomData->screenLayers[0].bitmapPointer = 1399610;
_currentRoomData->screenLayers[0].bitmapSize = 892;
_currentRoomData->screenLayers[0].coordx = 217;
_currentRoomData->screenLayers[0].coordy = 48;
_currentRoomData->screenLayers[0].depth = 1;
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(0, 1);
} else {
readObject(_niche[1][_niche[1][3]]);
_niche[1][_niche[1][3]] = 622;
_niche[1][3] += 1;
_niche[0][3] -= 1;
_currentRoomData->screenObjectIndex[8]->objectName = " ";
animatePickup1(0, 1);
readBitmap(1399610, _screenLayers[0], 892, 319);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(0, 1);
_sound->playVoc("PLATAF", 375907, 14724);
_currentRoomData->screenLayers[0].bitmapSize = 892;
_currentRoomData->screenLayers[0].coordx = 217;
_currentRoomData->screenLayers[0].coordy = 48;
_currentRoomData->screenLayers[0].depth = 1;
switch (_niche[1][_niche[1][3]]) {
case 0: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(4);
nicheAnimation(0, 1399610);
_currentRoomData->screenLayers[0].bitmapPointer = 1399610;
} break;
case 561: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(5);
nicheAnimation(0, 1381982);
_currentRoomData->screenLayers[0].bitmapPointer = 1381982;
} break;
case 615: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(7);
nicheAnimation(0, 1381090);
_currentRoomData->screenLayers[0].bitmapPointer = 1381090;
} break;
case 622: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(8);
nicheAnimation(0, 1400502);
_currentRoomData->screenLayers[0].bitmapPointer = 1400502;
} break;
case 623: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(9);
nicheAnimation(0, 1398718);
_currentRoomData->screenLayers[0].bitmapPointer = 1398718;
} break;
}
updateAltScreen(20);
}
} else {
_mouse->show();
drawText(1049 + getRandom(10));
_mouse->hide();
return;
}
} break;
}
} break;
case 624: { // red devil
animatePickup1(2, 1);
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[3];
with.bitmapPointer = 0;
with.bitmapSize = 0;
with.coordx = 0;
with.coordy = 0;
with.depth = 0;
}
clearScreenLayer(3);
disableSecondAnimation();
_graphics->drawScreen(_sceneBackground);
animatePickup2(2, 1);
_isRedDevilCaptured = true;
_isTrapSet = false;
} break;
default: {
animatePickup1(_charFacingDirection, 1);
clearScreenLayer(_curObject->depth - 1);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(_charFacingDirection, 1);
}
}
} break;
case 2: { // Pick up feet level
switch (_curObject->code) {
case 216: { // chisel
animatePickup1(0, 2);
_currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex = _curObject->replaceWith;
updateVideo();
animatePickup2(0, 2);
} break;
case 295: { // candles
animatePickup1(3, 2);
_currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex = _curObject->replaceWith;
updateVideo();
animatePickup2(3, 2);
} break;
case 362: { // charcoal
animatePickup1(0, 2);
animatePickup2(0, 2);
} break;
case 598: { // mud
animatePickup1(3, 2);
animatePickup2(3, 2);
} break;
case 659: { // spider web, puts bird and ring on the floor
animatePickup1(3, 2);
clearScreenLayer(_curObject->depth - 1);
{ // bird
RoomBitmapRegister &with = _currentRoomData->screenLayers[2];
with.bitmapPointer = 1545924;
with.bitmapSize = 172;
with.coordx = 38;
with.coordy = 58;
with.depth = 1;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
{ // ring
RoomBitmapRegister &with = _currentRoomData->screenLayers[1];
with.bitmapPointer = 1591272;
with.bitmapSize = 92;
with.coordx = 50;
with.coordy = 58;
with.depth = 3;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(3, 2);
} break;
default: {
animatePickup1(_charFacingDirection, 2);
clearScreenLayer(_curObject->depth - 1);
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(_charFacingDirection, 2);
}
}
} break;
case 9: { // bat
uint textRef = _curObject->pickTextRef;
readObject(204);
animatePickup1(0, 1);
animateOpen2(0, 1);
animateBat();
_mouse->show();
drawText(textRef);
_currentRoomData->mouseGrid[34][8] = 24;
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
return;
} break;
}
_mouse->show();
if (_curObject->code != 624)
for (int j = _curObject->ygrid1; j <= _curObject->ygrid2; j++)
for (int i = _curObject->xgrid1; i <= _curObject->xgrid2; i++) {
_currentRoomData->walkAreasGrid[i][j] = _curObject->walkAreasPatch[i - _curObject->xgrid1][j - _curObject->ygrid1];
_currentRoomData->mouseGrid[i][j] = _curObject->mouseGridPatch[i - _curObject->xgrid1][j - _curObject->ygrid1];
}
switch (_curObject->code) {
case 216: { // chisel
_currentRoomData->screenLayers[5].bitmapPointer = 517485;
_currentRoomData->screenLayers[5].bitmapSize = 964;
_currentRoomData->screenLayers[5].coordx = 223;
_currentRoomData->screenLayers[5].coordy = 34;
_currentRoomData->screenLayers[5].depth = 1;
} break;
case 218:; // necronomicon
break;
case 223: { // table cloth
_currentRoomData->screenLayers[6].bitmapPointer = 436752;
_currentRoomData->screenLayers[6].bitmapSize = 1372;
_currentRoomData->screenLayers[6].coordx = 174;
_currentRoomData->screenLayers[6].coordy = 32;
_currentRoomData->screenLayers[6].depth = 1;
} break;
case 295: { // candles
_currentRoomData->screenLayers[3].bitmapPointer = 1130756;
_currentRoomData->screenLayers[3].bitmapSize = 1764;
_currentRoomData->screenLayers[3].coordx = 100;
_currentRoomData->screenLayers[3].coordy = 28;
_currentRoomData->screenLayers[3].depth = 1;
} break;
case 308:; // mistletoe
break;
case 362:; // charcoal
break;
case 402: {
_currentRoomData->screenLayers[5].bitmapPointer = 68130;
_currentRoomData->screenLayers[5].bitmapSize = 2564;
_currentRoomData->screenLayers[5].coordx = 148;
_currentRoomData->screenLayers[5].coordy = 49;
_currentRoomData->screenLayers[5].depth = 7;
} break;
case 479:; // scissors
break;
case 517:; // mints
break;
case 590:; // ectoplasm
break;
case 598:; // mud
break;
case 624:; // red devil
break;
default: {
for (int i = 0; i < 15; i++)
if (_currentRoomData->screenLayers[i].bitmapPointer == _curObject->bitmapPointer) {
_currentRoomData->screenLayers[i].bitmapPointer = 0;
_currentRoomData->screenLayers[i].bitmapSize = 0;
_currentRoomData->screenLayers[i].coordx = 0;
_currentRoomData->screenLayers[i].coordy = 0;
_currentRoomData->screenLayers[i].depth = 0;
}
}
}
} else {
if (_curObject->pickTextRef > 0)
drawText(_curObject->pickTextRef);
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
return;
}
inventoryIndex = 0;
while (_inventory[inventoryIndex].code != 0) {
inventoryIndex += 1;
}
_inventory[inventoryIndex].bitmapIndex = _curObject->objectIconBitmap;
_inventory[inventoryIndex].code = _curObject->code;
_inventory[inventoryIndex].objectName = _curObject->name;
_mouse->hide();
drawInventory();
_mouse->show();
if (_curObject->pickTextRef > 0)
drawText(_curObject->pickTextRef);
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
}
void TotEngine::replaceBackpack(byte obj1, uint obj2) {
readObject(obj2);
_inventory[obj1].bitmapIndex = _curObject->objectIconBitmap;
_inventory[obj1].code = obj2;
_inventory[obj1].objectName = _curObject->name;
_cpCounter = _cpCounter2;
}
void TotEngine::dropObjectInScreen(ScreenObject *replacementObject) {
byte objIndex;
if (replacementObject->bitmapSize > 0) {
objIndex = 0;
while (!(_currentRoomData->screenLayers[objIndex].bitmapSize == 0) || objIndex == 15) {
objIndex++;
}
if (_currentRoomData->screenLayers[objIndex].bitmapSize == 0) {
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[objIndex];
with.bitmapPointer = replacementObject->bitmapPointer;
with.bitmapSize = replacementObject->bitmapSize;
with.coordx = replacementObject->dropOverlayX;
with.coordy = replacementObject->dropOverlayY;
with.depth = replacementObject->depth;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
for (int j = replacementObject->ygrid1; j <= replacementObject->ygrid2; j++)
for (int i = replacementObject->xgrid1; i <= replacementObject->xgrid2; i++) {
_currentRoomData->walkAreasGrid[i][j] = replacementObject->walkAreasPatch[i - replacementObject->xgrid1][j - replacementObject->ygrid1];
_currentRoomData->mouseGrid[i][j] = replacementObject->mouseGridPatch[i - replacementObject->xgrid1][j - replacementObject->ygrid1];
}
} else
showError(264);
}
}
void TotEngine::useScreenObject() {
byte usedObjectIndex,
listIndex, invIndex;
bool verifyList, foobar;
uint foo;
Common::Point p = _mouse->getClickCoordsWithinGrid();
uint correctedMouseX = p.x;
uint correctedMouseY = p.y;
uint sceneObject = _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex;
if (_inventoryObjectName != "") { //Use inv object with something on the scene
usedObjectIndex = 0;
while (_inventory[usedObjectIndex].objectName != _inventoryObjectName) {
usedObjectIndex += 1;
}
readObject(_inventory[usedObjectIndex].code);
goToObject(
_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount],
_currentRoomData->walkAreasGrid[correctedMouseX][correctedMouseY]);
if (_curObject->useWith == sceneObject && sceneObject > 0 && _curObject->used[0] == 5) {
switch (_curObject->useWith) {
case 30: { // corn with rooster
drawText(_curObject->useTextRef);
_mouse->hide();
animateGive(1, 2);
animatePickup2(1, 2);
updateObject(_curObject->code);
_currentRoomData->screenObjectIndex[27]->fileIndex = 201;
do {
_chrono->updateChrono();
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
if (_currentSecondaryTrajectoryIndex >= _currentRoomData->secondaryTrajectoryLength)
_currentSecondaryTrajectoryIndex = 1;
else
_currentSecondaryTrajectoryIndex += 1;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
emptyLoop();
_chrono->_gameTick = false;
emptyLoop2();
sprites(true);
_screen->update();
} while (_currentSecondaryTrajectoryIndex != 4);
for (listIndex = 0; listIndex < _maxXGrid; listIndex++)
for (invIndex = 0; invIndex < _maxYGrid; invIndex++) {
_currentRoomData->walkAreasGrid[_oldposx + listIndex][_oldposy + invIndex] = _movementGridForSecondaryAnim[listIndex][invIndex];
_currentRoomData->mouseGrid[_oldposx + listIndex][_oldposy + invIndex] = _mouseGridForSecondaryAnim[listIndex][invIndex];
}
clearAnimation();
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x + 8;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
_currentRoomData->animationName = "GALLOPIC";
_currentRoomData->secondaryAnimDirections[299] = 201;
loadAnimation("GALLOPIC");
_currentRoomData->secondaryAnimDirections[0] = 0;
_currentRoomData->secondaryAnimTrajectory[0].x = _secondaryAnimation.posx;
_currentRoomData->secondaryAnimTrajectory[0].y = _secondaryAnimation.posy;
_currentSecondaryTrajectoryIndex = 1;
_currentRoomData->secondaryTrajectoryLength = 1;
for (listIndex = 0; listIndex < _maxXGrid; listIndex++)
for (invIndex = 0; invIndex < _maxYGrid; invIndex++) {
if (_maskGridSecondaryAnim[listIndex][invIndex] > 0)
_currentRoomData->walkAreasGrid[_oldposx + listIndex][_oldposy + invIndex] = _maskGridSecondaryAnim[listIndex][invIndex];
if (_maskMouseSecondaryAnim[listIndex][invIndex] > 0)
_currentRoomData->mouseGrid[_oldposx + listIndex][_oldposy + invIndex] = _maskMouseSecondaryAnim[listIndex][invIndex];
}
_mouse->show();
} break;
case 153: { // oil with well
drawText(_curObject->useTextRef);
_mouse->hide();
_sound->playVoc("BLUP", 330921, 3858);
animateGive(3, 1);
animatePickup2(3, 1);
_mouse->show();
updateObject(_curObject->code);
_currentRoomData->screenObjectIndex[21]->fileIndex = 154;
} break;
case 157: { // giving something to john
verifyList = false;
debug("used object = %d", _inventory[usedObjectIndex].code);
if (_obtainedList1) {
for (listIndex = 0; listIndex < 5; listIndex++) {
if (_inventory[usedObjectIndex].code == _firstList[listIndex])
verifyList = true;
}
if (verifyList) {
int completedListItems = 0;
for (listIndex = 0; listIndex < 5; listIndex++) {
for (invIndex = 0; invIndex < kInventoryIconCount; invIndex++) {
if (_inventory[invIndex].code == _firstList[listIndex]) {
completedListItems += 1;
break;
}
}
}
if (completedListItems == 5) {
_obtainedList1 = false;
_list1Complete = true;
readTextFile();
sayLine(1018, 255, 0, foo, false);
sayLine(foo, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
animateGive(_charFacingDirection, 1);
animateOpen2(_charFacingDirection, 1);
for (listIndex = 0; listIndex < 5; listIndex++) {
invIndex = 0;
while (_inventory[invIndex].code != _firstList[listIndex]) {
invIndex += 1;
}
updateInventory(invIndex);
}
listIndex = 0;
while (_inventory[listIndex].code != 149) {
listIndex += 1;
}
updateInventory(listIndex);
drawInventory();
_mouse->show();
} else {
readTextFile();
sayLine(_curObject->useTextRef, 255, 0, foo, false);
_mouse->hide();
animateGive(_charFacingDirection, 1);
animateOpen2(_charFacingDirection, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_verbFile.close();
}
}
}
verifyList = false;
if (_obtainedList2) {
for (listIndex = 0; listIndex < 5; listIndex++)
if (_inventory[usedObjectIndex].code == _secondList[listIndex])
verifyList = true;
if (verifyList) {
int completedListItems = 0;
for (listIndex = 0; listIndex < 5; listIndex++) {
for (invIndex = 0; invIndex < kInventoryIconCount; invIndex++) {
if (_inventory[invIndex].code == _secondList[listIndex]) {
completedListItems += 1;
break;
}
}
}
if (completedListItems == 5) {
_obtainedList2 = false;
_list2Complete = true;
readTextFile();
sayLine(1020, 255, 0, foo, false);
sayLine(foo, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
animateGive(_charFacingDirection, 1);
animateOpen2(_charFacingDirection, 1);
for (listIndex = 0; listIndex < 5; listIndex++) {
invIndex = 0;
while (_inventory[invIndex].code != _secondList[listIndex]) {
invIndex += 1;
}
updateInventory(invIndex);
}
listIndex = 0;
while (_inventory[listIndex].code != 150) {
listIndex += 1;
}
updateInventory(listIndex);
drawInventory();
_mouse->show();
} else {
readTextFile();
sayLine(_curObject->useTextRef, 255, 0, foo, false);
_mouse->hide();
animateGive(_charFacingDirection, 1);
animateOpen2(_charFacingDirection, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_verbFile.close();
}
}
}
} break;
case 159: {
switch (_curObject->code) {
case 173: {
readTextFile();
sayLine(1118, 255, 0, foo, false);
_mouse->hide();
animateGive(_charFacingDirection, 1);
animateOpen2(_charFacingDirection, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_verbFile.close();
} break;
case 218: {
readTextFile();
sayLine(687, 255, 0, foo, false);
_mouse->hide();
animateGive(_charFacingDirection, 1);
animateOpen2(_charFacingDirection, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
for (foo = 0; foo < kCharacterCount; foo++)
_bookTopic[foo] = true;
_firstTimeTopicB[0] = true;
} break;
}
} break;
case 160: {
readTextFile();
sayLine(2466, 255, 0, foo, false);
_mouse->hide();
animateGive(_charFacingDirection, 1);
animateOpen2(_charFacingDirection, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
for (foo = 0; foo < kCharacterCount; foo++) {
_mintTopic[foo] = true;
_firstTimeTopicC[foo] = true;
}
} break;
case 164: {
switch (_curObject->code) {
case 563: {
_isPottersManualDelivered = true;
if (_isPottersWheelDelivered && _isGreenDevilDelivered && _isMudDelivered) {
readTextFile();
sayLine(2696, 255, 0, foo, false);
_mouse->hide();
animateGive(0, 1);
animateOpen2(0, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_caves[4] = true;
sayLine(3247, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
replaceBackpack(usedObjectIndex, 676);
drawInventory();
disableSecondAnimation();
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[0];
with.bitmapPointer = 1545820;
with.bitmapSize = 104;
with.coordx = 120;
with.coordy = 55;
with.depth = 1;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
_currentRoomData->mouseGrid[15][12] = 7;
_mouse->show();
} else {
readTextFile();
sayLine(2696, 255, 0, foo, false);
_mouse->hide();
animateGive(0, 1);
animateOpen2(0, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
sayLine(3246, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
}
} break;
case 598: {
_isMudDelivered = true;
if (_isPottersWheelDelivered && _isGreenDevilDelivered && _isPottersManualDelivered) {
readTextFile();
sayLine(2821, 255, 0, foo, false);
_mouse->hide();
animateGive(0, 1);
animatePickup2(0, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_caves[4] = true;
sayLine(3247, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
replaceBackpack(usedObjectIndex, 676);
drawInventory();
disableSecondAnimation();
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[0];
with.bitmapPointer = 1545820;
with.bitmapSize = 104;
with.coordx = 120;
with.coordy = 55;
with.depth = 1;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
_currentRoomData->mouseGrid[15][12] = 7;
_mouse->show();
} else {
readTextFile();
sayLine(2821, 255, 0, foo, false);
_mouse->hide();
animateGive(0, 1);
animateOpen2(0, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
sayLine(3246, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
}
} break;
case 623: {
_isPottersWheelDelivered = true;
if (_isMudDelivered && _isGreenDevilDelivered && _isPottersManualDelivered) {
readTextFile();
sayLine(2906, 255, 0, foo, false);
_mouse->hide();
animateGive(0, 1);
animatePickup2(0, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_caves[4] = true;
sayLine(3247, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
replaceBackpack(usedObjectIndex, 676);
drawInventory();
disableSecondAnimation();
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[0];
with.bitmapPointer = 1545820;
with.bitmapSize = 104;
with.coordx = 120;
with.coordy = 55;
with.depth = 1;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
_currentRoomData->mouseGrid[15][12] = 7;
_mouse->show();
} else {
readTextFile();
sayLine(2906, 255, 0, foo, false);
_mouse->hide();
animateGive(0, 1);
animateOpen2(0, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
sayLine(3246, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
}
} break;
case 701: {
_isGreenDevilDelivered = true;
if (_isMudDelivered && _isPottersWheelDelivered && _isPottersManualDelivered) {
readTextFile();
sayLine(3188, 255, 0, foo, false);
_mouse->hide();
animateGive(0, 1);
animatePickup2(0, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
_caves[4] = true;
sayLine(3247, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
replaceBackpack(usedObjectIndex, 676);
drawInventory();
disableSecondAnimation();
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[0];
with.bitmapPointer = 1545820;
with.bitmapSize = 104;
with.coordx = 120;
with.coordy = 55;
with.depth = 1;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
_currentRoomData->mouseGrid[15][12] = 7;
_mouse->show();
} else {
readTextFile();
sayLine(3188, 255, 0, foo, false);
_mouse->hide();
animateGive(0, 1);
animateOpen2(0, 1);
_mouse->show();
sayLine(foo, 253, 249, foo, true);
sayLine(3246, 253, 249, foo, true);
_verbFile.close();
_mouse->hide();
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
}
} break;
}
} break;
case 165: {
drawText(1098);
_mouse->hide();
do {
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
if (_currentSecondaryTrajectoryIndex >= _currentRoomData->secondaryTrajectoryLength)
_currentSecondaryTrajectoryIndex = 1;
else
_currentSecondaryTrajectoryIndex += 1;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
emptyLoop();
_chrono->_gameTick = false;
emptyLoop2();
sprites(true);
} while (!(_currentSecondaryTrajectoryIndex == (_currentRoomData->secondaryTrajectoryLength / 2u)));
animateGive(3, 2);
updateInventory(usedObjectIndex);
drawInventory();
animateOpen2(3, 2);
animatedSequence(6);
do {
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
if (_currentSecondaryTrajectoryIndex >= _currentRoomData->secondaryTrajectoryLength)
_currentSecondaryTrajectoryIndex = 1;
else
_currentSecondaryTrajectoryIndex += 1;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
emptyLoop();
_chrono->_gameTick = false;
emptyLoop2();
sprites(true);
} while (_currentSecondaryTrajectoryIndex != _currentRoomData->secondaryTrajectoryLength);
disableSecondAnimation();
_graphics->drawScreen(_sceneBackground);
_mouse->show();
} break;
case 201: {
drawText(_curObject->useTextRef);
_sound->playVoc("GALLO", 94965, 46007);
_mouse->hide();
animatedSequence(5);
replaceBackpack(usedObjectIndex, 423);
drawInventory();
_mouse->show();
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
} break;
case 219: {
drawText(_curObject->useTextRef);
_mouse->hide();
_sound->playVoc("TAZA", 223698, 29066);
animateGive(3, 2);
do {
_chrono->updateChrono();
if (_chrono->_gameTick) {
_graphics->advancePaletteAnim();
_chrono->_gameTick = false;
}
_screen->update();
g_system->delayMillis(10);
} while (_sound->isVocPlaying());
animateOpen2(3, 2);
updateObject(_curObject->code);
disableSecondAnimation();
_graphics->drawScreen(_sceneBackground);
_mouse->show();
drawText(2652);
_mouse->hide();
readObject(536);
for (int i = 12; i <= 13; i++)
for (int j = 7; j <= 14; j++)
_currentRoomData->mouseGrid[i][j] = 14;
for (int i = 8; i <= 12; i++)
_currentRoomData->mouseGrid[14][i] = 14;
_currentRoomData->mouseGrid[9][10] = 1;
_currentRoomData->mouseGrid[10][10] = 1;
for (int i = 0; i < 15; i++)
if (_currentRoomData->screenLayers[i].bitmapPointer == _curObject->bitmapPointer) {
_currentRoomData->screenLayers[i].bitmapPointer = 0;
_currentRoomData->screenLayers[i].bitmapSize = 0;
_currentRoomData->screenLayers[i].coordx = 0;
_currentRoomData->screenLayers[i].coordy = 0;
_currentRoomData->screenLayers[i].depth = 0;
}
usedObjectIndex = 0;
while (_inventory[usedObjectIndex].code != 0) {
usedObjectIndex += 1;
}
_inventory[usedObjectIndex].bitmapIndex = _curObject->objectIconBitmap;
_inventory[usedObjectIndex].code = _curObject->code;
_inventory[usedObjectIndex].objectName = _curObject->name;
animatedSequence(4);
_mouse->show();
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
} break;
case 221: {
drawText(_curObject->useTextRef);
_curObject->used[0] = 9;
usedObjectIndex = 0;
while (_inventory[usedObjectIndex].code != 0) {
usedObjectIndex += 1;
}
_sceneObjectsData->seek(_curObject->code);
saveObjectsData(_curObject, _sceneObjectsData);
readObject(_sceneObjectsData, 221, _curObject);
_inventory[usedObjectIndex].bitmapIndex = _curObject->objectIconBitmap;
_inventory[usedObjectIndex].code = _curObject->code;
_inventory[usedObjectIndex].objectName = _curObject->name;
_mouse->hide();
animatePickup1(2, 0);
_sound->playVoc("TIJERAS", 252764, 5242);
_sound->waitForSoundEnd();
animatePickup2(2, 0);
drawInventory();
_mouse->show();
} break;
case 227: {
drawText(_curObject->useTextRef);
_mouse->hide();
_sound->playVoc("ALACENA", 319112, 11809);
animatePickup1(0, 2);
_sound->waitForSoundEnd();
animateOpen2(0, 2);
replaceBackpack(usedObjectIndex, 453);
drawInventory();
_mouse->show();
updateObject(_inventory[usedObjectIndex].code);
_isCupboardOpen = true;
} break;
case 274: {
drawText(_curObject->useTextRef);
_mouse->hide();
_sound->playVoc("CINCEL", 334779, 19490);
animatePickup1(_charFacingDirection, 2);
_sound->waitForSoundEnd();
animateOpen2(_charFacingDirection, 2);
_mouse->show();
updateObject(_curObject->code);
_isChestOpen = true;
} break;
case 416: {
updateObject(_curObject->code);
_mouse->hide();
_sound->playVoc("PUERTA", 186429, 4754);
animatePickup1(0, 1);
animateOpen2(0, 1);
_sound->waitForSoundEnd();
_sound->loadVoc("GOTA", 140972, 1029);
_mouse->show();
drawText(_curObject->useTextRef);
_currentRoomData->doors[2].openclosed = 0;
} break;
case 446: {
drawText(_curObject->useTextRef);
_mouse->hide();
_sound->playVoc("TAZA", 223698, 29066);
animateGive(0, 2);
_sound->waitForSoundEnd();
animatePickup2(0, 2);
replaceBackpack(usedObjectIndex, 204);
drawInventory();
_mouse->show();
} break;
case 507: {
_mouse->hide();
animatePickup1(0, 1);
_sound->playVoc("MAQUINA", 153470, 7378);
animateOpen2(0, 1);
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
_currentRoomData->mouseGrid[27][8] = 22;
} break;
case 549: {
updateObject(_curObject->code);
_mouse->hide();
_sound->playVoc("PUERTA", 186429, 4754);
animatePickup1(1, 1);
animateOpen2(1, 1);
_mouse->show();
drawText(_curObject->useTextRef);
_currentRoomData->doors[0].openclosed = 0;
} break;
case 562: { // put any object in the niches
switch (_currentRoomData->code) {
case 20: {
if (_niche[0][_niche[0][3]] == 0) {
if (_niche[0][3] == 0) {
_niche[0][0] = _curObject->code;
drawText(_curObject->useTextRef);
_mouse->hide();
_currentRoomData->screenObjectIndex[9]->objectName = " ";
animateGive(3, 1);
switch (_niche[0][0]) {
case 561: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(5);
readBitmap(1182652, _screenLayers[0], 892, 319);
_currentRoomData->screenLayers[1].bitmapPointer = 1182652;
} break;
case 615: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(7);
readBitmap(1181760, _screenLayers[0], 892, 319);
_currentRoomData->screenLayers[1].bitmapPointer = 1181760;
} break;
}
_currentRoomData->screenLayers[1].bitmapSize = 892;
_currentRoomData->screenLayers[1].coordx = 66;
_currentRoomData->screenLayers[1].coordy = 35;
_currentRoomData->screenLayers[1].depth = 1;
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animateOpen2(3, 1);
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
} else {
_niche[0][_niche[0][3]] = _curObject->code;
_niche[1][3] += 1;
_niche[0][3] -= 1;
drawText(_curObject->useTextRef);
_mouse->hide();
animateGive(3, 1);
switch (_curObject->code) {
case 561:
readBitmap(1182652, _screenLayers[0], 892, 319);
break;
case 615:
readBitmap(1181760, _screenLayers[0], 892, 319);
break;
}
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animateOpen2(3, 1);
updateInventory(usedObjectIndex);
drawInventory();
_currentRoomData->screenObjectIndex[9]->objectName = " ";
_sound->playVoc("PLATAF", 375907, 14724);
switch (_niche[0][_niche[0][3]]) {
case 0: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(4);
nicheAnimation(1, 1190768);
_currentRoomData->screenLayers[1].bitmapPointer = 1190768;
} break;
case 561: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(5);
nicheAnimation(1, 1182652);
_currentRoomData->screenLayers[1].bitmapPointer = 1182652;
} break;
case 563: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(6);
nicheAnimation(1, 1186044);
_currentRoomData->screenLayers[1].bitmapPointer = 1186044;
} break;
case 615: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(7);
nicheAnimation(1, 1181760);
_currentRoomData->screenLayers[1].bitmapPointer = 1181760;
} break;
}
_currentRoomData->screenLayers[1].bitmapSize = 892;
_currentRoomData->screenLayers[1].coordx = 66;
_currentRoomData->screenLayers[1].coordy = 35;
_currentRoomData->screenLayers[1].depth = 1;
_mouse->show();
updateAltScreen(24);
}
} else {
drawText(getRandom(11) + 1022);
}
} break;
case 24: {
if (_niche[1][_niche[1][3]] == 0) {
if (_niche[1][3] == 0) {
_niche[1][0] = _curObject->code;
drawText(_curObject->useTextRef);
_mouse->hide();
_currentRoomData->screenObjectIndex[8]->objectName = " ";
animateGive(0, 1);
switch (_niche[1][0]) {
case 561: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(5);
readBitmap(1381982, _screenLayers[0], 892, 319);
_currentRoomData->screenLayers[0].bitmapPointer = 1381982;
} break;
case 615: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(7);
readBitmap(1381090, _screenLayers[0], 892, 319);
_currentRoomData->screenLayers[0].bitmapPointer = 1381090;
} break;
}
_currentRoomData->screenLayers[0].bitmapSize = 892;
_currentRoomData->screenLayers[0].coordx = 217;
_currentRoomData->screenLayers[0].coordy = 48;
_currentRoomData->screenLayers[0].depth = 1;
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animateOpen2(0, 1);
updateInventory(usedObjectIndex);
drawInventory();
_mouse->show();
} else {
_niche[1][_niche[1][3]] = _curObject->code;
_niche[0][3] += 1;
_niche[1][3] -= 1;
drawText(_curObject->useTextRef);
_mouse->hide();
animateGive(0, 1);
switch (_curObject->code) {
case 561:
readBitmap(1381982, _screenLayers[_curObject->depth - 1],
892, 319);
break;
case 615:
readBitmap(1381090, _screenLayers[_curObject->depth - 1],
892, 319);
break;
}
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animateOpen2(0, 1);
updateInventory(usedObjectIndex);
drawInventory();
_currentRoomData->screenObjectIndex[8]->objectName = " ";
_sound->playVoc("PLATAF", 375907, 14724);
switch (_niche[1][_niche[1][3]]) {
case 0: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(4);
nicheAnimation(1, 1399610);
_currentRoomData->screenLayers[0].bitmapPointer = 1399610;
} break;
case 561: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(5);
nicheAnimation(1, 1381982);
_currentRoomData->screenLayers[0].bitmapPointer = 1381982;
} break;
case 615: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(7);
nicheAnimation(1, 1381090);
_currentRoomData->screenLayers[0].bitmapPointer = 1381090;
} break;
case 622: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(8);
nicheAnimation(1, 1400502);
_currentRoomData->screenLayers[0].bitmapPointer = 1400502;
} break;
case 623: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(9);
nicheAnimation(1, 1398718);
_currentRoomData->screenLayers[0].bitmapPointer = 1398718;
} break;
}
_currentRoomData->screenLayers[0].bitmapSize = 892;
_currentRoomData->screenLayers[0].coordx = 217;
_currentRoomData->screenLayers[0].coordy = 48;
_currentRoomData->screenLayers[0].depth = 1;
_mouse->show();
updateAltScreen(20);
}
} else {
drawText(getRandom(11) + 1022);
}
} break;
}
} break;
case 583: {
int32 offset = getOffsetsByCurrentLanguage()[20];
drawText(_curObject->useTextRef);
_mouse->hide();
drawFlc(140, 34, offset, 0, 9, 24, false, false, true, foobar);
_mouse->show();
updateObject(_curObject->code);
_currentRoomData->screenObjectIndex[7]->fileIndex = 716;
_currentRoomData->mouseGrid[19][9] = 14;
_currentRoomData->mouseGrid[22][16] = 15;
for (listIndex = 21; listIndex <= 22; listIndex++)
for (invIndex = 17; invIndex <= 20; invIndex++)
_currentRoomData->mouseGrid[listIndex][invIndex] = 17;
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[0];
with.bitmapPointer = 1243652;
with.bitmapSize = 2718;
with.coordx = 127;
with.coordy = 36;
with.depth = 6;
}
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[1];
with.bitmapPointer = 1240474;
with.bitmapSize = 344;
with.coordx = 168;
with.coordy = 83;
with.depth = 12;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[2];
with.bitmapPointer = 1240818;
with.bitmapSize = 116;
with.coordx = 177;
with.coordy = 82;
with.depth = 1;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
readBitmap(1243652, _screenLayers[5], 2718, 319);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
} break;
case 594: {
drawText(_curObject->useTextRef);
_mouse->hide();
animateGive(3, 2);
animatePickup2(3, 2);
replaceBackpack(usedObjectIndex, 607);
drawInventory();
_mouse->show();
} break;
case 608: {
drawText(_curObject->useTextRef);
goToObject(_currentRoomData->walkAreasGrid[correctedMouseX][correctedMouseY], 26);
_mouse->hide();
animateGive(2, 2);
animateOpen2(2, 2);
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[3];
with.bitmapPointer = 1546096;
with.bitmapSize = 372;
with.coordx = 208;
with.coordy = 105;
with.depth = 4;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
updateInventory(usedObjectIndex);
drawInventory();
_isTrapSet = true;
_mouse->show();
} break;
case 632: {
int32 offset = getOffsetsByCurrentLanguage()[21];
drawText(_curObject->useTextRef);
_mouse->hide();
animateGive(_charFacingDirection, 1);
// Show feather on pedestal
loadScreenLayer(187, 70, 104, 1545820, 8);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
_screen->update();
animateOpen2(_charFacingDirection, 1);
_mouse->show();
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], 14);
_mouse->hide();
_sound->playVoc("PUFF", 191183, 18001);
// Animate to scythe
drawFlc(180, 60, offset, 0, 9, 0, false, false, true, foobar);
// load Scythe
_currentRoomData->screenLayers[2].bitmapPointer = 1545820;
_currentRoomData->screenLayers[2].bitmapSize = 104;
_currentRoomData->screenLayers[2].coordx = 277;
_currentRoomData->screenLayers[2].coordy = 104;
_currentRoomData->screenLayers[2].depth = 1;
_depthMap[0].posy = 104;
readBitmap(1545820, _screenLayers[0], 104, 319);
_currentRoomData->screenLayers[4].bitmapPointer = 1447508;
_currentRoomData->screenLayers[4].bitmapSize = 464;
_currentRoomData->screenLayers[4].coordx = 186;
_currentRoomData->screenLayers[4].coordy = 64;
_currentRoomData->screenLayers[4].depth = 8;
loadScreenLayer(186, 63, 464, 1447508, 8);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
_mouse->show();
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], 18);
_mouse->hide();
animatePickup1(1, 1);
replaceBackpack(usedObjectIndex, 638);
_currentRoomData->screenLayers[4].bitmapPointer = 0;
_currentRoomData->screenLayers[4].bitmapSize = 0;
_currentRoomData->screenLayers[4].coordx = 0;
_currentRoomData->screenLayers[4].coordy = 0;
_currentRoomData->screenLayers[4].depth = 0;
clearScreenLayer(7);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(1, 1);
drawInventory();
_mouse->show();
for (listIndex = 35; listIndex <= 37; listIndex++)
for (invIndex = 21; invIndex <= 25; invIndex++)
_currentRoomData->mouseGrid[listIndex][invIndex] = 11;
_isScytheTaken = true;
if (_isTridentTaken)
_caves[3] = true;
} break;
case 633: { //Use ring!
int32 offset = getOffsetsByCurrentLanguage()[22];
drawText(_curObject->useTextRef);
_mouse->hide();
animateGive(3, 1);
loadScreenLayer(86, 55, 92, 1591272, 8);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animateOpen2(3, 1);
_mouse->show();
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], 10);
_mouse->hide();
_sound->playVoc("PUFF", 191183, 18001);
drawFlc(0, 47, offset, 0, 9, 0, false, false, true, foobar);
_currentRoomData->screenLayers[3].bitmapPointer = 1591272;
_currentRoomData->screenLayers[3].bitmapSize = 92;
_currentRoomData->screenLayers[3].coordx = 18;
_currentRoomData->screenLayers[3].coordy = 60;
_currentRoomData->screenLayers[3].depth = 3;
_depthMap[2].posx = 18;
_depthMap[2].posy = 60;
readBitmap(1591272, _screenLayers[2], 92, 319);
_currentRoomData->screenLayers[4].bitmapPointer = 1746554;
_currentRoomData->screenLayers[4].bitmapSize = 384;
_currentRoomData->screenLayers[4].coordx = 82;
_currentRoomData->screenLayers[4].coordy = 53;
_currentRoomData->screenLayers[4].depth = 8;
loadScreenLayer(82, 53, 384, 1746554, 8);
assembleScreen();
_graphics->drawScreen(_sceneBackground);
_mouse->show();
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], 15);
_mouse->hide();
animatePickup1(3, 1);
replaceBackpack(usedObjectIndex, 637);
_currentRoomData->screenLayers[4].bitmapPointer = 0;
_currentRoomData->screenLayers[4].bitmapSize = 0;
_currentRoomData->screenLayers[4].coordx = 0;
_currentRoomData->screenLayers[4].coordy = 0;
_currentRoomData->screenLayers[4].depth = 0;
clearScreenLayer(7);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animatePickup2(3, 1);
drawInventory();
_mouse->show();
for (listIndex = 0; listIndex <= 2; listIndex++)
for (invIndex = 10; invIndex <= 12; invIndex++)
_currentRoomData->mouseGrid[listIndex][invIndex] = 10;
_isTridentTaken = true;
if (_isScytheTaken)
_caves[3] = true;
} break;
case 643: { // Urn with altar
int32 offset = getOffsetsByCurrentLanguage()[23];
if (_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount] != 5)
drawText(_curObject->useTextRef);
_mouse->mouseClickX = 149 - 7;
_mouse->mouseClickY = 126 - 7;
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], 5);
_mouse->hide();
updateInventory(usedObjectIndex);
drawInventory();
drawFlc(133, 0, offset, 0, 9, 22, false, false, true, foobar);
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[2];
with.bitmapPointer = 1744230;
with.bitmapSize = 824;
with.coordx = 147;
with.coordy = 38;
with.depth = 9;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
updateAltScreen(31);
for (listIndex = 18; listIndex <= 20; listIndex++)
for (invIndex = 8; invIndex <= 14; invIndex++)
_currentRoomData->mouseGrid[listIndex][invIndex] = 12;
_isSealRemoved = true;
_caves[1] = false;
_caves[0] = false;
_caves[4] = false;
_mouse->show();
} break;
case 657: { // sharpen scythe
int32 offset = getOffsetsByCurrentLanguage()[24];
drawText(_curObject->useTextRef);
_mouse->mouseClickX = 178 - 7;
_mouse->mouseClickY = 71 - 7;
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], 3);
_mouse->hide();
_sound->playVoc("AFILAR", 0, 6433);
drawFlc(160, 15, offset, 0, 9, 23, false, false, true, foobar);
replaceBackpack(usedObjectIndex, 715);
drawInventory();
_mouse->show();
} break;
case 686: {
drawText(_curObject->useTextRef);
_isVasePlaced = true;
_caves[4] = false;
_mouse->hide();
animateGive(1, 1);
updateInventory(usedObjectIndex);
dropObjectInScreen(_curObject);
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
drawInventory();
animateOpen2(1, 1);
for (listIndex = 19; listIndex <= 21; listIndex++)
for (invIndex = 10; invIndex <= 13; invIndex++)
_currentRoomData->mouseGrid[listIndex][invIndex] = 13;
_mouse->show();
} break;
case 689: { // rope
int32 offset = getOffsetsByCurrentLanguage()[25];
drawText(_curObject->useTextRef);
_mouse->mouseClickX = 124 - 7;
_mouse->mouseClickY = 133 - 7;
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], 9);
_mouse->hide();
drawFlc(110, 79, offset, 0, 9, 0, false, false, true, foobar);
replaceBackpack(usedObjectIndex, 701);
drawInventory();
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
_mouse->show();
for (listIndex = 18; listIndex <= 20; listIndex++)
_currentRoomData->mouseGrid[listIndex][26] = 10;
for (listIndex = 17; listIndex <= 21; listIndex++)
_currentRoomData->mouseGrid[listIndex][27] = 10;
} break;
case 700: { // Trident
int32 offset = getOffsetsByCurrentLanguage()[26];
drawText(_curObject->useTextRef);
_mouse->mouseClickX = 224 - 7;
_mouse->mouseClickY = 91 - 7;
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], 7);
_mouse->hide();
drawFlc(208, 0, offset, 0, 9, 21, false, false, true, foobar);
_currentRoomData->screenLayers[0].bitmapPointer = 0;
_currentRoomData->screenLayers[0].bitmapSize = 0;
_currentRoomData->screenLayers[0].coordx = 0;
_currentRoomData->screenLayers[0].coordy = 0;
_currentRoomData->screenLayers[0].depth = 0;
clearScreenLayer(2);
for (invIndex = 6; invIndex <= 9; invIndex++)
_currentRoomData->mouseGrid[26][invIndex] = 3;
for (invIndex = 3; invIndex <= 5; invIndex++)
_currentRoomData->mouseGrid[27][invIndex] = 3;
for (invIndex = 6; invIndex <= 10; invIndex++)
_currentRoomData->mouseGrid[27][invIndex] = 4;
for (invIndex = 11; invIndex <= 12; invIndex++)
_currentRoomData->mouseGrid[27][invIndex] = 7;
for (invIndex = 2; invIndex <= 10; invIndex++)
_currentRoomData->mouseGrid[28][invIndex] = 4;
for (invIndex = 11; invIndex <= 12; invIndex++)
_currentRoomData->mouseGrid[28][invIndex] = 7;
_currentRoomData->mouseGrid[28][13] = 4;
for (invIndex = 1; invIndex <= 14; invIndex++)
_currentRoomData->mouseGrid[29][invIndex] = 4;
for (listIndex = 30; listIndex <= 32; listIndex++)
for (invIndex = 0; invIndex <= 15; invIndex++)
_currentRoomData->mouseGrid[listIndex][invIndex] = 4;
for (invIndex = 1; invIndex <= 14; invIndex++)
_currentRoomData->mouseGrid[33][invIndex] = 4;
for (invIndex = 2; invIndex <= 14; invIndex++)
_currentRoomData->mouseGrid[34][invIndex] = 4;
for (invIndex = 3; invIndex <= 8; invIndex++)
_currentRoomData->mouseGrid[35][invIndex] = 4;
for (invIndex = 9; invIndex <= 11; invIndex++)
_currentRoomData->mouseGrid[35][invIndex] = 7;
_currentRoomData->doors[1].openclosed = 1;
_mouse->show();
updateObject(_curObject->code);
} break;
case 709: { // rock with mural
int32 offset = getOffsetsByCurrentLanguage()[27];
if (_isSealRemoved) {
drawText(_curObject->useTextRef);
_mouse->hide();
animatePickup1(0, 1);
_sound->playVoc("TIZA", 390631, 18774);
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[1];
with.bitmapPointer = 1745054;
with.bitmapSize = 1500;
with.coordx = 39;
with.coordy = 16;
with.depth = 1;
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
_sound->waitForSoundEnd();
_sound->playVoc("PUFF", 191183, 18001);
animateOpen2(0, 1);
drawFlc(180, 50, offset, 0, 9, 22, false, false, true, foobar);
_shouldQuitGame = true;
} else
drawText(getRandom(11) + 1022);
} break;
}
} else {
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], _currentRoomData->walkAreasGrid[correctedMouseX][correctedMouseY]);
if (_curObject->code == 536 || _curObject->code == 220)
drawText(getRandom(6) + 1033);
else
drawText(getRandom(11) + 1022);
}
} else { //use object with something on the scene
if (sceneObject > 0) {
readObject(sceneObject);
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount], _currentRoomData->walkAreasGrid[correctedMouseX][correctedMouseY]);
switch (_curObject->used[0]) {
case 0: {
if (_curObject->useTextRef > 0)
drawText(_curObject->useTextRef);
} break;
case 9: {
if (_curObject->afterUseTextRef > 0)
drawText(_curObject->afterUseTextRef);
} break;
case 100: {
switch (_curObject->code) {
case 153: {
_mouse->hide();
animatedSequence(2);
_mouse->show();
} break;
case 154: {
_curObject->used[0] = 9;
if (_curObject->beforeUseTextRef > 0)
drawText(_curObject->beforeUseTextRef);
_mouse->hide();
animatedSequence(1);
_mouse->show();
drawText(1425);
_mouse->hide();
animatedSequence(3);
_mouse->show();
updateObject(_curObject->code);
readObject(152);
usedObjectIndex = 0;
while (_inventory[usedObjectIndex].code != 0) {
usedObjectIndex += 1;
}
_inventory[usedObjectIndex].bitmapIndex = _curObject->objectIconBitmap;
_inventory[usedObjectIndex].code = _curObject->code;
_inventory[usedObjectIndex].objectName = _curObject->name;
_mouse->hide();
drawInventory();
_mouse->show();
} break;
case 169: {
_mouse->hide();
animatePickup1(0, 1);
animateOpen2(0, 1);
_isTVOn = !(_isTVOn);
if (_isTVOn) {
_sound->playVoc("CLICK", 27742, 2458);
_sound->waitForSoundEnd();
_currentRoomData->paletteAnimationFlag = true;
_sound->autoPlayVoc("PARASITO", 355778, 20129);
} else {
_sound->stopVoc();
_sound->playVoc("CLICK", 27742, 2458);
_currentRoomData->paletteAnimationFlag = false;
for (int i = 195; i <= 200; i++) {
g_engine->_graphics->_pal[i * 3 + 0] = 2 << 2;
g_engine->_graphics->_pal[i * 3 + 1] = 2 << 2;
g_engine->_graphics->_pal[i * 3 + 2] = 2 << 2;
setRGBPalette(i, 2, 2, 2);
}
}
_mouse->show();
} break;
case 347: {
drawText(_curObject->useTextRef);
_sound->stopVoc();
_sound->playVoc("CLICK", 27742, 2458);
_mouse->hide();
animatePickup1(0, 0);
delay(100);
animateOpen2(0, 0);
_sound->stopVoc();
_sound->autoPlayVoc("CALDERA", 6433, 15386);
_graphics->turnLightOn();
_mouse->show();
_currentRoomData->palettePointer = 1536;
_currentRoomData->screenObjectIndex[1]->fileIndex = 424;
_currentRoomData->doors[1].openclosed = 1;
} break;
case 359: {
drawText(_curObject->useTextRef);
_sound->stopVoc();
_sound->playVoc("CARBON", 21819, 5923);
_mouse->hide();
animatePickup1(0, 0);
delay(100);
animateOpen2(0, 0);
_mouse->show();
updateObject(_curObject->code);
_currentRoomData->screenObjectIndex[16]->fileIndex = 362;
_currentRoomData->screenObjectIndex[16]->objectName = getObjectName(2);
_currentRoomData->screenObjectIndex[1]->fileIndex = 347;
_currentRoomData->screenObjectIndex[1]->objectName = getObjectName(3);
_sound->stopVoc();
_sound->autoPlayVoc("CALDERA", 6433, 15386);
} break;
case 682: {
int32 offsetWithJar = getOffsetsByCurrentLanguage()[28];
int32 offsetNoJar = getOffsetsByCurrentLanguage()[29];
_mouse->hide();
_sound->playVoc("CLICK", 27742, 2458);
animatePickup1(0, 1);
_sound->waitForSoundEnd();
animateOpen2(0, 1);
_sound->playVoc("FUEGO", 72598, 9789);
if (_isVasePlaced) {
drawFlc(108, 0, offsetWithJar, 0, 9, 0, false, false, true, foobar);
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[0];
with.bitmapPointer = 1636796;
with.bitmapSize = 628;
with.coordx = 153;
with.coordy = 48;
with.depth = 1;
}
for (listIndex = 19; listIndex <= 21; listIndex++)
for (invIndex = 10; invIndex <= 13; invIndex++)
_currentRoomData->mouseGrid[listIndex][invIndex] = 12;
} else
drawFlc(108, 0, offsetNoJar, 0, 9, 0, false, false, true, foobar);
_mouse->show();
} break;
}
if ((_curObject->beforeUseTextRef > 0) && (_curObject->code != 154))
drawText(_curObject->beforeUseTextRef);
} break;
default:
drawText(1022 + getRandom(11));
}
}
}
_oldGridX = 0;
_oldGridY = 0;
_actionCode = 0;
checkMouseGrid();
}
void TotEngine::openScreenObject() {
byte xIndex, yIndex;
bool shouldSpeak; //Whether the character should speak to reject the action or not
Common::Point p = _mouse->getClickCoordsWithinGrid();
uint correctedMouseX = p.x;
uint correctedMouseY = p.y;
uint screenObject = _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex;
if (screenObject == 0)
return;
readObject(screenObject);
debug("Read screen object = %s, with code = %d, depth=%d", _curObject->name.c_str(), _curObject->code, _curObject->depth);
goToObject(_currentRoomData->walkAreasGrid[(_characterPosX + kCharacterCorrectionX) / kXGridCount][(_characterPosY + kCharacerCorrectionY) / kYGridCount],
_currentRoomData->walkAreasGrid[correctedMouseX][correctedMouseY]);
if (_curObject->openable == false) {
drawText(getRandom(9) + 1059);
return;
} else {
shouldSpeak = false;
switch (_curObject->code) {
case 227:
if (_isCupboardOpen == false)
shouldSpeak = true;
break;
case 274:
if (_isChestOpen == false)
shouldSpeak = true;
break;
case 415:
if (_currentRoomData->doors[2].openclosed == 2)
shouldSpeak = true;
else {
_mouse->hide();
animatePickup1(0, 1);
clearScreenLayer(_curObject->depth - 1);
yIndex = 0;
while (yIndex < 14 && _currentRoomData->screenLayers[yIndex].depth != _curObject->depth) {
yIndex++;
}
_currentRoomData->screenLayers[yIndex].bitmapPointer = 0;
_currentRoomData->screenLayers[yIndex].bitmapSize = 0;
_currentRoomData->screenLayers[yIndex].coordx = 0;
_currentRoomData->screenLayers[yIndex].coordy = 0;
_currentRoomData->screenLayers[yIndex].depth = 0;
_currentRoomData->doors[2].openclosed = 1;
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animateOpen2(0, 1);
_mouse->show();
for (yIndex = 0; yIndex <= 12; yIndex++)
for (xIndex = 33; xIndex <= 36; xIndex++)
_currentRoomData->mouseGrid[xIndex][yIndex] = 43;
for (xIndex = 33; xIndex <= 35; xIndex++)
_currentRoomData->mouseGrid[xIndex][13] = 43;
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
_oldTargetZone = 0;
checkMouseGrid();
return;
}
break;
case 548:
if (_currentRoomData->doors[0].openclosed == 2)
shouldSpeak = true;
else {
_mouse->hide();
animatePickup1(1, 1);
clearScreenLayer(_curObject->depth - 1);
yIndex = 0;
while (_currentRoomData->screenLayers[yIndex].depth != _curObject->depth && yIndex != 14) {
yIndex++;
}
_currentRoomData->screenLayers[yIndex].bitmapPointer = 0;
_currentRoomData->screenLayers[yIndex].bitmapSize = 0;
_currentRoomData->screenLayers[yIndex].coordx = 0;
_currentRoomData->screenLayers[yIndex].coordy = 0;
_currentRoomData->screenLayers[yIndex].depth = 0;
_currentRoomData->doors[0].openclosed = 1;
_graphics->restoreBackground();
assembleScreen();
_graphics->drawScreen(_sceneBackground);
animateOpen2(1, 1);
_mouse->show();
xIndex = 30;
for (yIndex = 17; yIndex <= 18; yIndex++)
_currentRoomData->mouseGrid[xIndex][yIndex] = 8;
xIndex += 1;
for (yIndex = 4; yIndex <= 20; yIndex++)
_currentRoomData->mouseGrid[xIndex][yIndex] = 8;
xIndex += 1;
for (yIndex = 0; yIndex <= 20; yIndex++)
_currentRoomData->mouseGrid[xIndex][yIndex] = 8;
xIndex += 1;
for (yIndex = 0; yIndex <= 17; yIndex++)
_currentRoomData->mouseGrid[xIndex][yIndex] = 8;
xIndex += 1;
for (yIndex = 0; yIndex <= 12; yIndex++)
_currentRoomData->mouseGrid[xIndex][yIndex] = 8;
for (xIndex = 35; xIndex <= 39; xIndex++)
for (yIndex = 0; yIndex <= 10; yIndex++)
_currentRoomData->mouseGrid[xIndex][yIndex] = 8;
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
return;
}
break;
}
if (shouldSpeak) {
drawText(getRandom(9) + 1059);
return;
}
_currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex = _curObject->replaceWith;
_mouse->hide();
switch (_curObject->height) {
case 0: {
animatePickup1(_charFacingDirection, 0);
updateVideo();
animateOpen2(_charFacingDirection, 0);
} break;
case 1: {
animatePickup1(_charFacingDirection, 1);
updateVideo();
animateOpen2(_charFacingDirection, 1);
} break;
case 2: {
animatePickup1(_charFacingDirection, 2);
updateVideo();
animateOpen2(_charFacingDirection, 2);
} break;
}
_mouse->show();
for (yIndex = _curObject->ygrid1; yIndex <= _curObject->ygrid2; yIndex++)
for (xIndex = _curObject->xgrid1; xIndex <= _curObject->xgrid2; xIndex++) {
_currentRoomData->walkAreasGrid[xIndex][yIndex] = _curObject->walkAreasPatch[xIndex - _curObject->xgrid1][yIndex - _curObject->ygrid1];
_currentRoomData->mouseGrid[xIndex][yIndex] = _curObject->mouseGridPatch[xIndex - _curObject->xgrid1][yIndex - _curObject->ygrid1];
}
for (xIndex = 0; xIndex < 15; xIndex++)
if (_currentRoomData->screenLayers[xIndex].bitmapPointer == _curObject->bitmapPointer) {
_currentRoomData->screenLayers[xIndex].bitmapPointer = _curObject->dropOverlay;
_currentRoomData->screenLayers[xIndex].bitmapSize = _curObject->dropOverlaySize;
}
_actionCode = 0;
}
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
}
void TotEngine::closeScreenObject() {
byte xIndex, yIndex;
bool shouldSpeak;
uint sceneObject;
Common::Point p = _mouse->getClickCoordsWithinGrid();
uint correctedMouseX = p.x;
uint correctedMouseY = p.y;
sceneObject = _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex;
if (sceneObject == 0)
return;
readObject(sceneObject);
goToObject(_currentRoomData->walkAreasGrid[((_characterPosX + kCharacterCorrectionX) / kXGridCount)][((_characterPosY + kCharacerCorrectionY) / kYGridCount)],
_currentRoomData->walkAreasGrid[correctedMouseX][correctedMouseY]);
if (_curObject->closeable == false) {
drawText((getRandom(10) + 1068));
return;
} else {
shouldSpeak = false;
switch (_curObject->code) {
case 224:
case 226:
if (_isCupboardOpen == false)
shouldSpeak = true;
break;
case 275:
case 277:
if (_isChestOpen == false)
shouldSpeak = true;
break;
}
if (shouldSpeak) {
drawText(getRandom(10) + 1068);
return;
}
_currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[correctedMouseX][correctedMouseY]]->fileIndex = _curObject->replaceWith;
_mouse->hide();
switch (_curObject->height) {
case 0: {
animatePickup1(_charFacingDirection, 0);
updateVideo();
animateOpen2(_charFacingDirection, 0);
} break;
case 1: {
animatePickup1(_charFacingDirection, 1);
updateVideo();
animateOpen2(_charFacingDirection, 1);
} break;
case 2: {
animatePickup1(_charFacingDirection, 2);
updateVideo();
animateOpen2(_charFacingDirection, 2);
} break;
}
_mouse->show();
for (yIndex = _curObject->ygrid1; yIndex <= _curObject->ygrid2; yIndex++)
for (xIndex = _curObject->xgrid1; xIndex <= _curObject->xgrid2; xIndex++) {
_currentRoomData->walkAreasGrid[xIndex][yIndex] = _curObject->walkAreasPatch[xIndex - _curObject->xgrid1][yIndex - _curObject->ygrid1];
_currentRoomData->mouseGrid[xIndex][yIndex] = _curObject->mouseGridPatch[xIndex - _curObject->xgrid1][yIndex - _curObject->ygrid1];
}
for (xIndex = 0; xIndex < 15; xIndex++)
if (_currentRoomData->screenLayers[xIndex].bitmapPointer == _curObject->bitmapPointer) {
_currentRoomData->screenLayers[xIndex].bitmapPointer = _curObject->dropOverlay;
_currentRoomData->screenLayers[xIndex].bitmapSize = _curObject->dropOverlaySize;
}
_actionCode = 0;
}
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
}
void TotEngine::action() {
bar(0, 140, 319, 149, 0);
Common::String actionLine;
switch (_actionCode) {
case 0:
actionLine = getActionLineText(0);
break;
case 1:
actionLine = getActionLineText(1);
break;
case 2:
actionLine = getActionLineText(2);
break;
case 3:
actionLine = getActionLineText(3);
break;
case 4: {
actionLine = getActionLineText(4);
_inventoryObjectName = "";
} break;
case 5:
actionLine = getActionLineText(5);
break;
case 6:
actionLine = getActionLineText(6);
break;
}
actionLineText(actionLine);
}
void TotEngine::handleAction(byte invPos) {
bar(0, 140, 319, 149, 0);
switch (_actionCode) {
case 1: {
_mouse->hide();
actionLineText(getActionLineText(1) + _inventory[invPos].objectName);
_mouse->show();
drawText((getRandom(10) + 1039));
_actionCode = 0;
if (_cpCounter > 130)
showError(274);
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
} break;
case 2: {
_mouse->hide();
actionLineText(getActionLineText(2) + _inventory[invPos].objectName);
if (_cpCounter2 > 13)
showError(274);
_mouse->show();
drawText((getRandom(10) + 1049));
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
} break;
case 3: {
_mouse->hide();
actionLineText(getActionLineText(3) + _inventory[invPos].objectName);
_mouse->show();
_actionCode = 0;
lookAtObject(invPos);
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
} break;
case 4:
if (_inventoryObjectName == "") {
_mouse->hide();
actionLineText(getActionLineText(4) + _inventory[invPos].objectName + getActionLineText(7));
_mouse->show();
_inventoryObjectName = _inventory[invPos].objectName;
_backpackObjectCode = _inventory[invPos].code;
} else {
_actionCode = 0;
if (_cpCounter > 25)
showError(274);
useInventoryObjectWithInventoryObject(_backpackObjectCode, _inventory[invPos].code);
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
}
break;
case 5: {
_mouse->hide();
actionLineText(getActionLineText(5) + _inventory[invPos].objectName);
_mouse->show();
drawText(getRandom(9) + 1059);
_actionCode = 0;
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
} break;
case 6: {
_mouse->hide();
actionLineText(getActionLineText(6) + _inventory[invPos].objectName);
_mouse->show();
drawText(getRandom(10) + 1068);
_actionCode = 0;
if (_cpCounter2 > 35)
showError(274);
_oldGridX = 0;
_oldGridY = 0;
checkMouseGrid();
} break;
}
}
void TotEngine::loadInventory() {
Common::File objectFile;
switch (_gamePart) {
case 1:
objectFile.open("OBJMOCH.DAT");
break;
case 2:
objectFile.open("OBJMOCH.TWO");
break;
}
if (!objectFile.isOpen()) {
debug("Object file exists? %d, open? %d, gamepart? %d", objectFile.exists("OBJMOCH.DAT"), objectFile.isOpen(), _gamePart);
showError(312);
}
for (int i = 0; i < kInventoryIconCount; i++) {
_inventoryIconBitmaps[i] = (byte *)malloc(kInventoryIconSize);
objectFile.read(_inventoryIconBitmaps[i], kInventoryIconSize);
}
if (_cpCounter > 65)
showError(274);
const char *emptyName = getHardcodedTextsByCurrentLanguage()[10];
for (int i = 0; i < kInventoryIconCount; i++) {
_inventory[i].bitmapIndex = 34;
_inventory[i].code = 0;
_inventory[i].objectName = emptyName;
}
objectFile.close();
}
void TotEngine::obtainName(Common::String &playerName) {
uint16 namePromptBGSize;
byte *namePromptBG;
namePromptBGSize = imagesize(84, 34, 235, 80);
namePromptBG = (byte *)malloc(namePromptBGSize);
_graphics->getImg(84, 34, 235, 80, namePromptBG);
drawMenu(8);
_screen->update();
Common::String prompt;
readAlphaGraph(prompt, 8, 125, 62, 252);
playerName = prompt.c_str();
_graphics->putImg(84, 34, namePromptBG);
_screen->update();
free(namePromptBG);
}
/**
* Blits srcImage over dstImage on the zeroed pixels of dstImage
*/
static void blit(byte *srcImage, byte *dstImage) { // Near;
uint16 w = READ_LE_UINT16(dstImage) + 1;
uint16 h = READ_LE_UINT16(dstImage + 2) + 1;
uint size = w * h;
byte *dst = dstImage + 4;
byte *src = srcImage + 4;
for (uint i = 0; i < size; i++) {
if (dst[i] == 0) {
dst[i] = src[i];
}
}
}
/**
* Grabs the action area of the screen into a pointer
*/
static void getScreen(byte *bg) {
byte *screenBuf = (byte *)g_engine->_screen->getPixels();
Common::copy(screenBuf, screenBuf + (22400 * 2), bg + 4);
}
void TotEngine::scrollRight(uint horizontalPos) {
int characterPos = 25 + (320 - (_characterPosX + kCharacterCorrectionX * 2));
// We scroll 4 by 4 pixels so we divide by 4 to find out the number of necessary steps
uint stepCount = (320 - horizontalPos) >> 2;
byte *assembledCharacterFrame = (byte *)malloc(_mainCharFrameSize);
// Number of bytes to move
size_t numBytes = 44796;
for (uint i = 0; i < stepCount; i++) {
// move everything to the left
memmove(_sceneBackground + 4, _sceneBackground + 8, numBytes);
horizontalPos += 4;
for (int k = 0; k < 140; k++) {
for (int j = 0; j < 4; j++) {
_sceneBackground[320 + k * 320 + j] = _backgroundCopy[horizontalPos + k * 320 + j];
}
}
if (characterPos > 0) {
characterPos -= 2;
if (characterPos > 0 && _iframe < 15) {
_iframe++;
} else
_iframe = 0;
_characterPosX -= 2;
_curCharacterAnimationFrame = _mainCharAnimation.bitmap[1][_iframe];
// We need to copy the original frame as to not replace its black background for after
// the scroll ends. Original code would copy from XMS memory.
Common::copy(_curCharacterAnimationFrame, _curCharacterAnimationFrame + _mainCharFrameSize, assembledCharacterFrame);
// puts the original captured background back in the background for next iteration
_graphics->putImageArea(_characterPosX - 2, _characterPosY, _sceneBackground, _spriteBackground);
uint16 pasoframeW = READ_LE_UINT16(assembledCharacterFrame);
uint16 pasoframeH = READ_LE_UINT16(assembledCharacterFrame + 2);
// Grabs current area surrounding character (which might contain parts of A and B)
_graphics->getImageArea(_characterPosX, _characterPosY, _characterPosX + pasoframeW, _characterPosY + pasoframeH, _sceneBackground, _spriteBackground);
// blits over the character sprite, only on black pixels
blit(_spriteBackground, assembledCharacterFrame);
// puts it back in the background (character + piece of background)
_graphics->putImageArea(_characterPosX, _characterPosY, _sceneBackground, assembledCharacterFrame);
} else
_characterPosX -= 4;
_screen->addDirtyRect(Common::Rect(0, 0, 320, 140));
_screen->update();
_graphics->drawScreen(_sceneBackground);
}
free(assembledCharacterFrame);
}
void TotEngine::scrollLeft(uint horizontalPos) {
int characterPos = 25 + _characterPosX;
horizontalPos = 320 - horizontalPos;
// We scroll 4 by 4 pixels so we divide by 4 to find out the number of necessary steps
uint stepCount = horizontalPos >> 2;
byte *assembledCharacterFrame = (byte *)malloc(_mainCharFrameSize);
size_t numBytes = 44796;
for (int i = stepCount; i >= 1; i--) {
for (int j = numBytes; j > 0; j--) {
// move the previous background to the right
_sceneBackground[j + 4] = _sceneBackground[j];
}
horizontalPos -= 4;
for (int k = 0; k < 140; k++) {
for (int j = 0; j < 4; j++) {
_sceneBackground[4 + k * 320 + j] = _backgroundCopy[4 + horizontalPos + k * 320 + j];
}
}
if (characterPos > 0) {
characterPos -= 2;
if (characterPos > 0 && _iframe < 15)
_iframe++;
else
_iframe = 0;
_characterPosX += 2;
_curCharacterAnimationFrame = _mainCharAnimation.bitmap[3][_iframe];
Common::copy(_curCharacterAnimationFrame, _curCharacterAnimationFrame + _mainCharFrameSize, assembledCharacterFrame);
_graphics->putImageArea(_characterPosX + 2, _characterPosY, _sceneBackground, _spriteBackground);
uint16 pasoframeW = READ_LE_UINT16(assembledCharacterFrame);
uint16 pasoframeH = READ_LE_UINT16(assembledCharacterFrame + 2);
_graphics->getImageArea(_characterPosX, _characterPosY, _characterPosX + pasoframeW, _characterPosY + pasoframeH, _sceneBackground, _spriteBackground);
blit(_spriteBackground, assembledCharacterFrame);
_graphics->putImageArea(_characterPosX, _characterPosY, _sceneBackground, assembledCharacterFrame);
} else
_characterPosX += 4;
_screen->addDirtyRect(Common::Rect(0, 0, 320, 140));
_screen->update();
_graphics->drawScreen(_sceneBackground);
}
free(assembledCharacterFrame);
}
/**
* Scrolling happens between two screens. We grab the area surroudning the player from screen A,
* then transition to screen B.
*/
void TotEngine::loadScrollData(uint roomCode, bool rightScroll, uint horizontalPos, int scrollCorrection) {
_graphics->restoreBackground();
// background now contains background A, backgroundCopy contains background A
uint characterFrameW = READ_LE_UINT16(_curCharacterAnimationFrame);
uint characterFrameH = READ_LE_UINT16(_curCharacterAnimationFrame + 2);
/* Copy the area with the player from previous scren*/
_spriteBackground = (byte *)malloc(4 + (characterFrameW + 8) * (characterFrameH + 8));
_graphics->getImageArea(_characterPosX, _characterPosY, _characterPosX + characterFrameW, _characterPosY + characterFrameH, _sceneBackground, _spriteBackground);
// Start screen 2
_rooms->seek(roomCode * kRoomRegSize, SEEK_SET);
if (_currentRoomData) {
delete _currentRoomData;
}
_currentRoomData = readScreenDataFile(_rooms);
loadScreen();
// Background now contains background B, backgroundCopy contains background B
for (int i = 0; i < 15; i++) {
{
RoomBitmapRegister &with = _currentRoomData->screenLayers[i];
if (with.bitmapSize > 0)
loadScreenLayer(with.coordx, with.coordy, with.bitmapSize, with.bitmapPointer, with.depth);
}
}
// assembles the screen objects into background
assembleScreen(true);
// background contains background B + objects, backgroundCopy contains plain background B
// Copies the contents of background into backgroundCopy
Common::copy(_sceneBackground, _sceneBackground + 44804, _backgroundCopy);
// background contains background B + objects, backgroundCopy contains background B + objects
g_engine->_graphics->_paletteAnimFrame = 0;
getScreen(_sceneBackground);
// background now contains full background A again, backgroundCopy contains background B + objects
_graphics->drawScreen(_sceneBackground);
if (rightScroll)
scrollRight(horizontalPos);
else
scrollLeft(horizontalPos);
// After scroll is done, backgroundCopy will now contain the resulting background (background B + objects)
Common::copy(_backgroundCopy, _backgroundCopy + 44804, _sceneBackground);
_characterPosX += scrollCorrection;
assembleScreen();
_graphics->drawScreen(_sceneBackground);
free(_spriteBackground);
loadScreen();
_trajectory[_currentTrajectoryIndex].x = _characterPosX;
_trajectory[_currentTrajectoryIndex].y = _characterPosY;
}
void TotEngine::sayLine(
uint textRef,
byte textColor,
byte shadowColor,
uint &responseNumber,
/** Whether the text being said is part of a conversation or just descriptions */
bool isWithinConversation) {
TextEntry text;
uint charCounter;
byte insertName, lineBreakCount, width;
byte characterFacingDir;
uint talkAnimIndex, bgSize, posx, posy;
byte *backgroundtextht;
byte lineBreaks[15];
_mouse->hide();
switch (_currentRoomData->code) {
case 2: { // Leisure room
posx = 10;
posy = 2;
width = 28;
} break;
case 3: { // dining room
posx = 130;
posy = 2;
width = 30;
} break;
case 8: // patch
case 21: // p4
posx = 10;
posy = 100;
width = 50;
break;
case 10: { // well
posx = 10;
posy = 2;
width = 40;
} break;
case 11: { // pond
posx = 172;
posy = 2;
width = 26;
} break;
case 16: { // dorm. 1
posx = 140;
posy = 2;
width = 30;
} break;
case 17: { // dorm. 2
posx = 10;
posy = 2;
width = 30;
} break;
case 23: { // fountain
posx = 10;
posy = 2;
width = 19;
} break;
case 25: { // catacombs
posx = 10;
posy = 2;
width = 22;
} break;
case 28: { // storage room
posx = 180;
posy = 60;
width = 24;
} break;
case 31: { // prison
posx = 10;
posy = 2;
width = 25;
} break;
default: { // any other room
posx = 10;
posy = 2;
width = 50;
}
}
_verbFile.seek(textRef * kVerbRegSize);
do {
text = readTextRegister();
insertName = 0;
for (uint i = 0; i < text.text.size(); i++) {
text.text.setChar(_decryptionKey[i] ^ text.text[i], i);
if (text.text[i] == '@')
insertName = i;
}
if (insertName > 0) {
text.text.deleteChar(insertName);
text.text.insertString(_characterName, insertName);
}
if (text.text.size() < width) {
bgSize = imagesize(posx - 1, posy - 1, posx + (text.text.size() * 8) + 2, posy + 13);
backgroundtextht = (byte *)malloc(bgSize);
_graphics->getImg(posx - 1, posy - 1, posx + (text.text.size() * 8) + 2, posy + 13, backgroundtextht);
littText(posx - 1, posy, text.text, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(posx + 1, posy, text.text, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(posx, posy - 1, text.text, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(posx, posy + 1, text.text, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(posx, posy, text.text, textColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
} else {
charCounter = 0;
lineBreakCount = 0;
lineBreaks[0] = 0;
// Breaks text lines on the last space when reaching the [anchoht]
do {
charCounter += width;
lineBreakCount += 1;
do {
charCounter -= 1;
} while (text.text[charCounter] != ' ');
lineBreaks[lineBreakCount] = charCounter + 1;
} while (((int)charCounter + 1) <= ((int)text.text.size() - (int)width));
lineBreakCount += 1;
lineBreaks[lineBreakCount] = text.text.size();
// Grab patch of background behind where the text will be, to paste it back later
bgSize = imagesize(posx - 1, posy - 1, posx + (width * 8) + 2, posy + lineBreakCount * 13);
backgroundtextht = (byte *)malloc(bgSize);
_graphics->getImg(posx - 1, posy - 1, posx + (width * 8) + 2, posy + lineBreakCount * 13, backgroundtextht);
for (int i = 1; i <= lineBreakCount; i++) {
Common::String lineString = Common::String(text.text.c_str() + lineBreaks[i - 1], text.text.c_str() + lineBreaks[i]);
littText(posx + 1, posy + ((i - 1) * 11), lineString, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(posx - 1, posy + ((i - 1) * 11), lineString, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(posx, posy + ((i - 1) * 11) + 1, lineString, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(posx, posy + ((i - 1) * 11) - 1, lineString, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
littText(posx, posy + ((i - 1) * 11), lineString, textColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
}
}
talkAnimIndex = 0;
bool mouseClicked = false;
// Plays talk cycle if needed
do {
_chrono->updateChrono();
g_engine->_events->pollEvent();
if (g_engine->_events->_leftMouseButton || g_engine->_events->_rightMouseButton) {
mouseClicked = true;
}
if (_chrono->_gameTick) {
_chrono->_gameTick = false;
if (_chrono->_gameTickHalfSpeed) {
if (isWithinConversation) {
talkAnimIndex += 1;
if (textColor == 255) {
_iframe2 = 0;
if (_iframe >= 15)
_iframe = 0;
else
_iframe++;
} else {
_iframe = 0;
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
}
// Talk sprites are always put in facing direction 0
characterFacingDir = _charFacingDirection;
_charFacingDirection = 0;
sprites(true);
_charFacingDirection = characterFacingDir;
} else {
if (_currentSecondaryTrajectoryIndex >= _currentRoomData->secondaryTrajectoryLength)
_currentSecondaryTrajectoryIndex = 1;
else
_currentSecondaryTrajectoryIndex += 1;
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
if (_iframe2 >= _secondaryAnimationFrameCount - 1)
_iframe2 = 0;
else
_iframe2++;
sprites(false);
}
}
_graphics->advancePaletteAnim();
}
_screen->update();
g_system->delayMillis(10);
} while (talkAnimIndex <= (text.text.size() * 4) && !mouseClicked && !shouldQuit());
_graphics->putImg(posx - 1, posy - 1, backgroundtextht);
free(backgroundtextht);
g_system->delayMillis(10);
} while (text.continued && !shouldQuit());
responseNumber = text.response;
_mouse->show();
}
void TotEngine::initScreenPointers() {
_screenSize = 65520;
_sceneBackground = (byte *)malloc(_screenSize);
_backgroundCopy = (byte *)malloc(_screenSize);
}
void TotEngine::loadAnimationForDirection(Common::SeekableReadStream *stream, int direction) {
uint size = _secondaryAnimFrameSize;
for (int j = 0; j < _secondaryAnimationFrameCount; j++) {
if (_secondaryAnimation.bitmap[direction][j]) {
free(_secondaryAnimation.bitmap[direction][j]);
}
_secondaryAnimation.bitmap[direction][j] = (byte *)malloc(size);
stream->read(_secondaryAnimation.bitmap[direction][j], size);
Common::copy(_secondaryAnimation.bitmap[direction][j], _secondaryAnimation.bitmap[direction][j] + size, g_engine->_curSecondaryAnimationFrame);
}
}
void TotEngine::loadAnimation(const Common::String &animationName) {
Common::File animFile;
if (animationName == "PETER")
_isPeterCoughing = true;
else
_isPeterCoughing = false;
_isSecondaryAnimationEnabled = true;
if (!animFile.open(Common::Path(animationName + ".DAT"))) {
showError(265);
}
_secondaryAnimFrameSize = animFile.readUint16LE();
_secondaryAnimationFrameCount = animFile.readByte();
_secondaryAnimDirCount = animFile.readByte();
newSecondaryAnimationFrame();
if (_secondaryAnimDirCount != 0) {
_secondaryAnimationFrameCount = _secondaryAnimationFrameCount / 4;
for (int i = 0; i < 4; i++) {
loadAnimationForDirection(&animFile, i);
}
} else {
loadAnimationForDirection(&animFile, 0);
}
animFile.close();
_secondaryAnimWidth = READ_LE_UINT16(_secondaryAnimation.bitmap[0][1]) + 1;
_secondaryAnimHeight = READ_LE_UINT16(_secondaryAnimation.bitmap[0][1] + 2) + 1;
setRoomTrajectories(_secondaryAnimHeight, _secondaryAnimWidth, SET_WITH_ANIM, false);
readObject(_currentRoomData->secondaryAnimDirections[299]);
_maxXGrid = (_curObject->xgrid2 - _curObject->xgrid1 + 1);
_maxYGrid = (_curObject->ygrid2 - _curObject->ygrid1 + 1);
_oldposx = _curObject->xgrid1 + 1;
_oldposy = _curObject->ygrid1 + 1;
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++) {
_maskGridSecondaryAnim[i][j] = 0;
_maskMouseSecondaryAnim[i][j] = 0;
_movementGridForSecondaryAnim[i][j] = 0;
_mouseGridForSecondaryAnim[i][j] = 0;
}
for (int i = 0; i < _maxXGrid; i++)
for (int j = 0; j < _maxYGrid; j++) {
_maskGridSecondaryAnim[i][j] = _curObject->walkAreasPatch[i][j];
_maskMouseSecondaryAnim[i][j] = _curObject->mouseGridPatch[i][j];
_movementGridForSecondaryAnim[i][j] = _currentRoomData->walkAreasGrid[_oldposx + i][_oldposy + j];
_mouseGridForSecondaryAnim[i][j] = _currentRoomData->mouseGrid[_oldposx + i][_oldposy + j];
}
_iframe2 = 0;
}
void TotEngine::updateAltScreen(byte otherScreenNumber) {
uint i22;
uint i11;
if (_currentRoomData) {
byte currentScreen = _currentRoomData->code;
setRoomTrajectories(_secondaryAnimHeight, _secondaryAnimWidth, RESTORE);
// Save current room
saveRoomData(_currentRoomData, _rooms);
// Load other screen
_rooms->seek(otherScreenNumber * kRoomRegSize, SEEK_SET);
delete _currentRoomData;
_currentRoomData = readScreenDataFile(_rooms);
switch (otherScreenNumber) {
case 20: {
switch (_niche[0][_niche[0][3]]) {
case 0: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(4);
_currentRoomData->screenLayers[1].bitmapPointer = 1190768;
} break;
case 561: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(5);
_currentRoomData->screenLayers[1].bitmapPointer = 1182652;
} break;
case 563: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(6);
_currentRoomData->screenLayers[1].bitmapPointer = 1186044;
} break;
case 615: {
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(7);
_currentRoomData->screenLayers[1].bitmapPointer = 1181760;
} break;
}
_currentRoomData->screenLayers[1].bitmapSize = 892;
_currentRoomData->screenLayers[1].coordx = 66;
_currentRoomData->screenLayers[1].coordy = 35;
_currentRoomData->screenLayers[1].depth = 1;
} break;
case 24: {
switch (_niche[1][_niche[1][3]]) {
case 0: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(4);
_currentRoomData->screenLayers[0].bitmapPointer = 1399610;
} break;
case 561: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(5);
_currentRoomData->screenLayers[0].bitmapPointer = 1381982;
} break;
case 615: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(7);
_currentRoomData->screenLayers[0].bitmapPointer = 1381090;
} break;
case 622: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(8);
_currentRoomData->screenLayers[0].bitmapPointer = 1400502;
} break;
case 623: {
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(9);
_currentRoomData->screenLayers[0].bitmapPointer = 1398718;
} break;
}
_currentRoomData->screenLayers[0].bitmapSize = 892;
_currentRoomData->screenLayers[0].coordx = 217;
_currentRoomData->screenLayers[0].coordy = 48;
_currentRoomData->screenLayers[0].depth = 1;
} break;
case 31: {
for (i11 = 23; i11 <= 25; i11++)
for (i22 = 4; i22 <= 9; i22++)
_currentRoomData->mouseGrid[i11][i22] = 4;
for (i11 = 23; i11 <= 25; i11++)
for (i22 = 10; i22 <= 11; i22++)
_currentRoomData->mouseGrid[i11][i22] = 3;
_currentRoomData->screenLayers[0].bitmapSize = 0;
_currentRoomData->screenLayers[0].bitmapPointer = 0;
_currentRoomData->screenLayers[0].coordx = 0;
_currentRoomData->screenLayers[0].coordy = 0;
_currentRoomData->screenLayers[0].depth = 0;
} break;
}
// Save other screen
saveRoomData(_currentRoomData, _rooms);
// Restore current room again
_rooms->seek(currentScreen * kRoomRegSize, SEEK_SET);
if (_currentRoomData) {
delete _currentRoomData;
}
_currentRoomData = readScreenDataFile(_rooms);
setRoomTrajectories(_secondaryAnimHeight, _secondaryAnimWidth, SET_WITH_ANIM);
}
}
void TotEngine::loadTV() {
Common::File fichct;
if (!fichct.open("PALETAS.DAT")) {
showError(310);
}
fichct.seek(_currentRoomData->palettePointer + 603);
fichct.read(g_engine->_graphics->_palAnimSlice, 144);
for (int i = 0; i <= 48; i++) {
g_engine->_graphics->_palAnimSlice[i * 3 + 0] <<= 2;
g_engine->_graphics->_palAnimSlice[i * 3 + 1] <<= 2;
g_engine->_graphics->_palAnimSlice[i * 3 + 2] <<= 2;
}
fichct.close();
for (int ix = 195; ix <= 200; ix++) {
g_engine->_graphics->_pal[ix * 3 + 0] = 2 << 2;
g_engine->_graphics->_pal[ix * 3 + 1] = 2 << 2;
g_engine->_graphics->_pal[ix * 3 + 2] = 2 << 2;
setRGBPalette(ix, 2, 2, 2);
}
}
void TotEngine::loadScreen() {
Common::File paletteFile;
Palette palcp;
_screenSize = _currentRoomData->roomImageSize;
readBitmap(_currentRoomData->roomImagePointer, _sceneBackground, _screenSize, 316);
Common::copy(_sceneBackground, _sceneBackground + _screenSize, _backgroundCopy);
switch (_gamePart) {
case 1: {
if (!paletteFile.open("PALETAS.DAT")) {
showError(310);
}
paletteFile.seek(_currentRoomData->palettePointer);
paletteFile.read(palcp, 603);
if (_currentRoomData->paletteAnimationFlag) {
paletteFile.read(g_engine->_graphics->_palAnimSlice, 144);
for (int i = 0; i <= 48; i++) {
g_engine->_graphics->_palAnimSlice[i * 3 + 0] <<= 2;
g_engine->_graphics->_palAnimSlice[i * 3 + 1] <<= 2;
g_engine->_graphics->_palAnimSlice[i * 3 + 2] <<= 2;
}
}
paletteFile.close();
for (int i = 1; i <= 200; i++) {
g_engine->_graphics->_pal[i * 3 + 0] = palcp[i * 3 + 0] << 2;
g_engine->_graphics->_pal[i * 3 + 1] = palcp[i * 3 + 1] << 2;
g_engine->_graphics->_pal[i * 3 + 2] = palcp[i * 3 + 2] << 2;
}
_graphics->setPalette(g_engine->_graphics->_pal, 0, 201);
} break;
case 2: {
_graphics->loadPaletteFromFile("SEGUNDA");
_currentRoomData->paletteAnimationFlag = true;
} break;
}
}
void TotEngine::clearScreenLayers() {
for (int i = 0; i < kNumScreenOverlays; i++) {
clearScreenLayer(i);
}
}
void TotEngine::clearAnimation() {
if (_isSecondaryAnimationEnabled) {
_isSecondaryAnimationEnabled = false;
if (_curSecondaryAnimationFrame != nullptr) {
free(_curSecondaryAnimationFrame);
}
_curSecondaryAnimationFrame = nullptr;
for (int j = 0; j < _secondaryAnimDirCount; j++) {
for (int i = 0; i < _secondaryAnimationFrameCount; i++) {
if (_secondaryAnimation.bitmap[j][i] != nullptr) {
free(_secondaryAnimation.bitmap[j][i]);
}
_secondaryAnimation.bitmap[j][i] = nullptr;
}
}
}
}
void TotEngine::freeInventory() {
for (int i = 0; i < kInventoryIconCount; i++) {
free(_inventoryIconBitmaps[i]);
}
}
void TotEngine::loadScreenLayerWithDepth(uint coordx, uint coordy, uint bitmapSize, int32 bitmapIndex, uint depth) {
if (g_engine->_screenLayers[depth]) {
free(g_engine->_screenLayers[depth]);
}
_screenLayers[depth] = (byte *)malloc(bitmapSize);
readBitmap(bitmapIndex, _screenLayers[depth], bitmapSize, 319);
uint16 w, h;
w = READ_LE_UINT16(_screenLayers[depth]);
h = READ_LE_UINT16(_screenLayers[depth] + 2);
_depthMap[depth].posx = coordx;
_depthMap[depth].posy = coordy;
_depthMap[depth].posx2 = coordx + w + 1;
_depthMap[depth].posy2 = coordy + h + 1;
}
void TotEngine::loadScreenLayer(uint coordx, uint coordy, uint bitmapSize, int32 bitmapIndex, uint depth) {
loadScreenLayerWithDepth(coordx, coordy, bitmapSize, bitmapIndex, depth - 1);
}
void TotEngine::updateInventory(byte index) {
for (int i = index; i < (kInventoryIconCount - 1); i++) {
_inventory[i].bitmapIndex = _inventory[i + 1].bitmapIndex;
_inventory[i].code = _inventory[i + 1].code;
_inventory[i].objectName = _inventory[i + 1].objectName;
}
}
void TotEngine::drawLookAtItem(RoomObjectListEntry obj) {
_mouse->hide();
bar(0, 140, 319, 149, 0);
actionLineText(getActionLineText(3) + obj.objectName);
_mouse->show();
}
void TotEngine::putIcon(uint iconPosX, uint iconPosY, uint iconNum) {
// substract 1 to account for 1-based indices
_graphics->putImg(iconPosX, iconPosY, _inventoryIconBitmaps[_inventory[iconNum].bitmapIndex - 1]);
}
void TotEngine::drawInventory() {
putIcon(34, 169, _inventoryPosition);
putIcon(77, 169, _inventoryPosition + 1);
putIcon(120, 169, _inventoryPosition + 2);
putIcon(163, 169, _inventoryPosition + 3);
putIcon(206, 169, _inventoryPosition + 4);
putIcon(249, 169, _inventoryPosition + 5);
}
void lightUpLeft() {
line(10, 173, 29, 173, 255);
line(10, 173, 10, 189, 255);
line(30, 174, 30, 190, 249);
line(30, 190, 11, 190, 249);
}
void turnOffLeft() {
line(10, 173, 29, 173, 249);
line(10, 173, 10, 189, 249);
line(30, 174, 30, 190, 255);
line(30, 190, 11, 190, 255);
}
void lightUpRight() {
line(291, 173, 310, 173, 255);
line(291, 173, 291, 189, 255);
line(311, 174, 311, 190, 249);
line(311, 190, 292, 190, 249);
}
void turnOffRight() {
line(291, 173, 310, 173, 249);
line(291, 173, 291, 189, 249);
line(311, 174, 311, 190, 255);
line(311, 190, 292, 190, 255);
}
void TotEngine::drawInventory(byte dir, byte max) {
switch (dir) {
case 0:
if (_inventoryPosition > 0) {
_inventoryPosition -= 1;
drawInventory();
}
break;
case 1:
if (_inventoryPosition < (max - 6)) {
_inventoryPosition += 1;
drawInventory();
}
break;
}
_mouse->hide();
if (_inventoryPosition > 0)
lightUpLeft();
else
turnOffLeft();
if (_inventory[_inventoryPosition + 6].code > 0)
lightUpRight();
else
turnOffRight();
_mouse->show();
if (_cpCounter > 145)
showError(274);
}
void TotEngine::drawInventoryMask() {
buttonBorder(0, 140, 319, 149, 0, 0, 0, 0, 0);
for (int i = 1; i <= 25; i++)
buttonBorder(0, (175 - i), 319, (174 + i), 251, 251, 251, 251, 0);
drawMenu(1);
if (_inventoryPosition > 1)
lightUpLeft();
else
turnOffLeft();
if (_inventory[_inventoryPosition + 6].code > 0)
lightUpRight();
else
turnOffRight();
}
byte *getArrow(uint x, uint y) {
Common::File menuFile;
if (!menuFile.open("MENUS.DAT")) {
showError(258);
}
int32 menuOffset = isLanguageSpanish() ? menuOffsets_ES[0][0] : menuOffsets_EN[0][0];
uint w = 20;
uint h = 18;
uint size = 4 + w * h;
byte *bitmap = (byte *)malloc(size);
WRITE_LE_UINT16(bitmap, w - 1);
WRITE_LE_UINT16(bitmap + 2, h - 1);
menuFile.seek(menuOffset);
uint originalW = menuFile.readUint16LE() + 1;
for(uint i = 0; i < h; i++) {
menuFile.seek(menuOffset + 4 + + (y + i) * originalW + x);
menuFile.read(bitmap + 4 + i * w, w);
}
menuFile.close();
return bitmap;
}
void TotEngine::drawLeftArrow(uint x, uint y) {
byte *bitmap = getArrow(10, 23);
_graphics->putImg(x, y, bitmap);
free(bitmap);
}
void TotEngine::drawRightArrow(uint x, uint y) {
byte *bitmap = getArrow(291, 23);
_graphics->putImg(x, y, bitmap);
free(bitmap);
}
void TotEngine::drawMenu(byte menuNumber) {
byte *bitmap;
uint menuSize;
byte xmenu = 0, ymenu = 0;
int32 menuOffset;
Common::File menuFile;
if (!menuFile.open("MENUS.DAT")) {
showError(258);
}
menuOffset = isLanguageSpanish() ? menuOffsets_ES[menuNumber - 1][0] : menuOffsets_EN[menuNumber - 1][0];
menuSize = isLanguageSpanish() ? menuOffsets_ES[menuNumber - 1][1] : menuOffsets_EN[menuNumber - 1][1];
switch (menuNumber) {
case 1: {
xmenu = 0;
ymenu = 150;
} break;
case 2:
case 3:
case 6:
xmenu = 50;
ymenu = 10;
break;
case 4: {
if (_cpCounter2 > 20)
showError(274);
xmenu = 50;
ymenu = 10;
} break;
case 5: {
if (_cpCounter > 23)
showError(274);
xmenu = 0;
ymenu = 150;
} break;
case 7: {
xmenu = 58;
ymenu = 48;
} break;
case 8: {
xmenu = 84;
ymenu = 34;
} break;
}
bitmap = (byte *)malloc(menuSize);
menuFile.seek(menuOffset);
menuFile.read(bitmap, menuSize);
_graphics->putImg(xmenu, ymenu, bitmap);
free(bitmap);
menuFile.close();
}
static void loadDiploma(Common::String &photoName, Common::String &key) {
Palette auxPal;
byte *screen;
uint size;
byte *stamp;
Common::File dipFile;
if (!dipFile.open("DIPLOMA.PAN")) {
showError(318);
}
dipFile.read(auxPal, 768);
screen = (byte *)malloc(64000);
dipFile.read(screen, 64000);
dipFile.close();
if (!dipFile.open(Common::Path("DIPLOMA/SELLO.BMP")))
showError(271);
stamp = (byte *)malloc(2054);
dipFile.read(stamp, 2054);
dipFile.close();
g_engine->_graphics->drawFullScreen(screen);
free(screen);
if (dipFile.open(Common::Path("DIPLOMA/" + photoName + ".FOT"))) {
size = dipFile.size() - 768;
screen = (byte *)malloc(size);
dipFile.read(g_engine->_graphics->_pal, 768);
dipFile.read(screen, size);
dipFile.close();
g_engine->_graphics->putShape(10, 20, screen);
free(screen);
}
for (int i = 16; i <= 255; i++) {
auxPal[i * 3 + 0] = g_engine->_graphics->_pal[i * 3 + 0];
auxPal[i * 3 + 1] = g_engine->_graphics->_pal[i * 3 + 1];
auxPal[i * 3 + 2] = g_engine->_graphics->_pal[i * 3 + 2];
}
g_engine->_graphics->copyPalette(auxPal, g_engine->_graphics->_pal);
g_engine->_graphics->fixPalette(g_engine->_graphics->_pal, 768);
g_engine->_graphics->setPalette(g_engine->_graphics->_pal);
g_engine->_screen->markAllDirty();
g_engine->_screen->update();
char *passArray = new char[10];
for (int i = 0; i < 10; i++)
passArray[i] = (char)(getRandom(10) + 48);
key.append(passArray, passArray + 10);
const char *const *messages = getFullScreenMessagesByCurrentLanguage();
biosText(91, 16, messages[49] + key, 255);
biosText(90, 15, messages[49] + key, 13);
biosText(81, 61, messages[50], 0);
biosText(61, 81, messages[51], 0);
if(isLanguageSpanish()) {
biosText(31, 101, messages[52] + g_engine->_characterName, 0);
} else {
biosText(31, 101, messages[52], 0);
biosText(151, 101, g_engine->_characterName, 0);
}
biosText(31, 121, messages[53], 0);
biosText(31, 141, messages[54], 0);
biosText(31, 161, messages[55], 0);
biosText(80, 60, messages[50], 15);
biosText(60, 80, messages[51], 15);
biosText(30, 100, messages[52], 15);
biosText(150, 100, g_engine->_characterName, 13);
biosText(30, 120, messages[53], 15);
biosText(30, 140, messages[54], 15);
biosText(30, 160, messages[55], 15);
delay(1500);
g_engine->_sound->playVoc("PORTAZO", 434988, 932);
g_engine->_graphics->putShape(270, 159, stamp);
delete[] passArray;
free(stamp);
}
static void saveDiploma(Common::String &photoName, Common::String &key) {
Common::String name;
if (photoName != "")
name = "tot-diploma-" + photoName + ".png";
else
name = "tot-diploma-default.png";
Common::OutSaveFile *thumbnail = g_engine->getSaveFileManager()->openForSaving(name);
Graphics::Surface *surface = g_system->lockScreen();
assert(surface);
Image::writePNG(*thumbnail, *surface, g_engine->_graphics->getPalette());
g_system->unlockScreen();
thumbnail->finalize();
delete thumbnail;
}
void TotEngine::generateDiploma(Common::String &photoName) {
Common::String key;
_mouse->hide();
photoName.toUppercase();
_graphics->totalFadeOut(0);
loadDiploma(photoName, key);
do {
_screen->update();
g_engine->_events->pollEvent();
g_system->delayMillis(10);
} while (!g_engine->_events->_keyPressed && !shouldQuit());
saveDiploma(photoName, key);
_mouse->show();
}
void TotEngine::checkMouseGrid() {
uint xGrid, yGrid;
Common::String invObject;
if (_cpCounter2 > 120)
showError(274);
if (_mouse->mouseY <= 131) {
xGrid = _mouse->getMouseCoordsWithinGrid().x;
yGrid = _mouse->getMouseCoordsWithinGrid().y;
if (_currentRoomData->mouseGrid[xGrid][yGrid] != _currentRoomData->mouseGrid[_oldGridX][_oldGridY] || _oldInventoryObjectName != "") {
bar(0, 140, 319, 149, 0);
Common::String actionLine;
switch (_actionCode) {
case 0:
actionLine = getActionLineText(0) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
break;
case 1:
actionLine = getActionLineText(1) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
break;
case 2:
actionLine = getActionLineText(2) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
break;
case 3:
actionLine = getActionLineText(3) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
break;
case 4:
if (_inventoryObjectName != "")
actionLine = getActionLineText(4) + _inventoryObjectName + getActionLineText(7) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
else
actionLine = getActionLineText(4) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
break;
case 5:
actionLine = getActionLineText(5) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
break;
case 6:
actionLine = getActionLineText(6) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
break;
default:
actionLine = getActionLineText(0) + _currentRoomData->screenObjectIndex[_currentRoomData->mouseGrid[xGrid][yGrid]]->objectName;
}
actionLineText(actionLine);
_mouse->show();
_oldGridX = xGrid;
_oldGridY = yGrid;
}
_oldActionCode = 253;
_oldInventoryObjectName = "";
} else if (_mouse->mouseY <= 165) {
if (_actionCode != _oldActionCode) {
bar(0, 140, 319, 149, 0);
Common::String actionLine;
switch (_actionCode) {
case 0:
actionLine = getActionLineText(0);
break;
case 1:
actionLine = getActionLineText(1);
break;
case 2:
actionLine = getActionLineText(2);
break;
case 3:
actionLine = getActionLineText(3);
break;
case 4:
if (_inventoryObjectName != "")
actionLine = getActionLineText(4) + _inventoryObjectName + getActionLineText(7);
else
actionLine = getActionLineText(4);
break;
case 5:
actionLine = getActionLineText(5);
break;
case 6:
actionLine = getActionLineText(6);
break;
}
actionLineText(actionLine);
_mouse->show();
_oldActionCode = _actionCode;
_oldInventoryObjectName = "";
_oldGridX = 0;
_oldGridY = 0;
}
} else if (_mouse->mouseY <= 199) {
if (_mouse->mouseX >= 26 && _mouse->mouseX <= 65) {
invObject = _inventory[_inventoryPosition].objectName;
} else if (_mouse->mouseX >= 70 && _mouse->mouseX <= 108) {
invObject = _inventory[_inventoryPosition + 1].objectName;
} else if (_mouse->mouseX >= 113 && _mouse->mouseX <= 151) {
invObject = _inventory[_inventoryPosition + 2].objectName;
} else if (_mouse->mouseX >= 156 && _mouse->mouseX <= 194) {
invObject = _inventory[_inventoryPosition + 3].objectName;
} else if (_mouse->mouseX >= 199 && _mouse->mouseX <= 237) {
invObject = _inventory[_inventoryPosition + 4].objectName;
} else if (_mouse->mouseX >= 242 && _mouse->mouseX <= 280) {
invObject = _inventory[_inventoryPosition + 5].objectName;
} else {
invObject = ' ';
}
if (invObject != _oldInventoryObjectName || _oldGridX != 0) {
bar(0, 140, 319, 149, 0);
Common::String actionLine;
switch (_actionCode) {
case 1:
actionLine = getActionLineText(1) + invObject;
break;
case 2:
actionLine = getActionLineText(2) + invObject;
break;
case 3:
actionLine = getActionLineText(3) + invObject;
break;
case 4:
if (_inventoryObjectName == "")
actionLine = getActionLineText(4) + invObject;
else
actionLine = getActionLineText(4) + _inventoryObjectName + getActionLineText(7) + invObject;
break;
case 5:
actionLine = getActionLineText(5) + invObject;
break;
case 6:
actionLine = getActionLineText(6) + invObject;
break;
default:
euroText(160, 144, invObject, 255, Graphics::kTextAlignCenter);
}
actionLineText(actionLine);
_mouse->show();
_oldInventoryObjectName = invObject;
}
_oldActionCode = 255;
_oldGridX = 0;
_oldGridY = 0;
}
}
void TotEngine::readAlphaGraph(Common::String &output, int length, int posx, int posy, byte barColor) {
int pun = 1;
bar(posx, posy - 2, posx + length * 8, posy + 8, barColor);
biosText(posx, posy, "_", 0);
Common::Event e;
bool done = false;
g_system->getEventManager()->getKeymapper()->setEnabled(false);
while (!done && !shouldQuit()) {
while (g_system->getEventManager()->pollEvent(e)) {
if (e.type == Common::EVENT_KEYDOWN) {
int keycode = e.kbd.keycode;
int asciiCode = e.kbd.ascii;
// ENTER key
if (keycode == Common::KEYCODE_RETURN || keycode == Common::KEYCODE_KP_ENTER) {
if (output.size() > 0) {
done = true;
continue;
}
}
// Max 8 chars
if (pun > length && asciiCode != 8) {
_sound->beep(750, 60);
bar((posx + (output.size()) * 8), (posy - 2), (posx + (output.size() + 1) * 8), (posy + 8), barColor);
} else if (asciiCode == 8 && pun > 1) { // delete
output = output.substr(0, output.size() - 1);
bar(posx, (posy - 2), (posx + length * 8), (posy + 8), barColor);
biosText(posx, posy, output.c_str(), 0);
biosText((posx + (output.size()) * 8), posy, "_", 0);
pun -= 1;
} else if (
(asciiCode < 97 || asciiCode > 122) &&
(asciiCode < 65 || asciiCode > 90) &&
(asciiCode < 32 || asciiCode > 57) &&
(asciiCode < 164 || asciiCode > 165)) {
_sound->beep(1200, 60);
} else {
pun += 1;
output = output + (char)e.kbd.ascii;
bar(posx, (posy - 2), (posx + length * 8), (posy + 8), barColor);
biosText(posx, posy, output.c_str(), 0);
biosText((posx + (output.size()) * 8), posy, "_", 0);
}
}
}
g_system->delayMillis(10);
_screen->update();
}
g_system->getEventManager()->getKeymapper()->setEnabled(true);
}
bool getEvent(Common::Event &e, Common::Event &firstEvent) {
if (firstEvent.type != Common::EVENT_INVALID) {
e = firstEvent;
firstEvent.type = Common::EVENT_INVALID;
return true;
}
return g_system->getEventManager()->pollEvent(e);
}
void TotEngine::readAlphaGraphSmall(
Common::String &output,
int length,
int posx,
int posy,
byte barColor,
byte textColor,
Common::Event event) {
int pun = 1;
bool removeCaret = false;
g_system->getEventManager()->getKeymapper()->setEnabled(false);
output = "";
bar(posx, posy + 2, posx + length * 6, posy + 9, barColor);
euroText(posx, posy, "-", textColor);
Common::Event e;
bool done = false;
while (!done && !shouldQuit()) {
while (getEvent(e, event)) {
if (e.type == Common::EVENT_KEYDOWN) {
int keycode = e.kbd.keycode;
int asciiCode = e.kbd.ascii;
// ENTER key
if (keycode == Common::KEYCODE_RETURN || keycode == Common::KEYCODE_KP_ENTER) {
if (output.size() > 0) {
done = true;
removeCaret = true;
continue;
}
}
if (pun > length && asciiCode != 8) {
_sound->beep(750, 60);
bar((posx + (output.size()) * 6), (posy + 2), (posx + (output.size() + 1) * 6), (posy + 10), barColor);
} else if (asciiCode == 8 && pun > 1) {
output = output.substr(0, output.size() - 1);
bar(posx, (posy + 2), (posx + length * 6), (posy + 10), barColor);
euroText(posx, posy, output, textColor);
euroText(posx + _graphics->euroTextWidth(output), posy, "-", textColor);
pun -= 1;
removeCaret = true;
} else if (
(asciiCode < 97 || asciiCode > 122) &&
(asciiCode < 65 || asciiCode > 90) &&
(asciiCode < 32 || asciiCode > 57) &&
(asciiCode < 164 || asciiCode > 165)) {
_sound->beep(1200, 60);
removeCaret = false;
} else {
pun += 1;
output = output + (char)e.kbd.ascii;
bar(posx, (posy + 2), (posx + length * 6), (posy + 9), barColor);
euroText(posx, posy, output, textColor);
euroText(posx + _graphics->euroTextWidth(output), posy, "-", textColor);
removeCaret = true;
}
}
}
g_system->delayMillis(10);
_screen->update();
}
if (removeCaret) {
bar(posx + _graphics->euroTextWidth(output), posy + 2, (posx + _graphics->euroTextWidth(output)) + 6, posy + 9, barColor);
}
g_system->getEventManager()->getKeymapper()->setEnabled(true);
}
void TotEngine::displayObjectDescription(const Common::String &textString) {
uint xpos = 60;
uint ypos = 15;
byte maxWidth = 33;
byte textColor = 255;
byte shadowColor = 0;
uint ihc;
byte lineCounter;
byte newLineMatrix[10];
if (textString.size() < maxWidth) {
euroText((xpos + 1), (ypos + 1), textString, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
euroText(xpos, ypos, textString, textColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
} else {
ihc = 0;
lineCounter = 0;
newLineMatrix[0] = 0;
do {
ihc += maxWidth + 1;
lineCounter += 1;
do {
ihc -= 1;
} while (textString[ihc] != ' ');
newLineMatrix[lineCounter] = ihc + 1;
} while (ihc + 1 <= textString.size() - maxWidth);
lineCounter += 1;
newLineMatrix[lineCounter] = textString.size();
for (byte line = 1; line <= lineCounter; line++) {
Common::String lineString = textString.substr(newLineMatrix[line - 1], newLineMatrix[line] - newLineMatrix[line - 1]);
euroText((xpos + 1), (ypos + ((line - 1) * 11) + 1), lineString, shadowColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
euroText(xpos, (ypos + ((line - 1) * 11)), lineString, textColor);
_screen->update();
delay(kEnforcedTextAnimDelay);
}
}
}
void TotEngine::buttonBorder(uint x1, uint y1, uint x2, uint y2,
byte color1, byte color2, byte color3, byte color4, byte color5) {
bar(x1, y1, x2, y2, color4);
line(x1, y1, x1, y2, color1);
line(x1, y1, x2, y1, color1);
line(x2, y1, x2, y2, color2);
line(x2, y2, x1, y2, color2);
putpixel(x2, y1, color3);
putpixel(x1, y2, color3);
_screen->addDirtyRect(Common::Rect(x1, y1, x2, y2));
_screen->update();
}
static void buttonPress(uint xx1, uint yy1, uint xx2, uint yy2, bool pressed) {
g_engine->_mouse->hide();
uint color = 0;
if (pressed)
color = 249;
else
color = 255;
line(xx1, yy1, (xx2 - 1), yy1, color);
line(xx1, yy1, xx1, (yy2 - 1), color);
if (pressed)
color = 255;
else
color = 249;
line((xx1 + 1), yy2, xx2, yy2, color);
line(xx2, (yy1 + 1), xx2, yy2, color);
g_engine->_screen->addDirtyRect(Common::Rect(xx1, yy1, xx2, yy2));
g_engine->_screen->update();
g_engine->_mouse->show();
delay(100);
}
void TotEngine::copyProtection() {
if (!ConfMan.getBool("copy_protection") || isDemo()) {
return;
}
const char *message = isLanguageSpanish() ? hardcodedTexts_ES[12] : hardcodedTexts_EN[12];
int beepDelay = 100;
int chunkSize = 4;
uint inputPassword = 0;
byte cursorPos = 0, attempts = 0;
int32 diskPass = 0, protXor1 = 0, protXor2 = 0;
Common::File protectionFile;
if (!protectionFile.open("MCGA.DRV")) {
showError(260);
}
Common::String inputString = " ";
byte numRow = getRandom(95) + 1;
byte numColumn = getRandom(38) + 1;
protectionFile.seek(1 * chunkSize);
protXor1 = protectionFile.readUint32LE();
protectionFile.seek((((numRow - 1) * 38) + numColumn + 1) * chunkSize);
protXor2 = protectionFile.readUint32LE();
inputPassword = 0;
diskPass = protectionFile.readUint32LE();
uint correctPassword = ((diskPass ^ protXor1) - protXor2);
bool exitDialog = false;
protectionFile.close();
uint oldMouseX = _mouse->mouseX;
uint oldMouseY = _mouse->mouseY;
uint oldMouseMaskIndex = _mouse->mouseMaskIndex;
_mouse->hide();
uint bgSize = imagesize(50, 10, 270, 120);
byte *bgPointer = (byte *)malloc(bgSize);
_graphics->getImg(50, 10, 270, 120, bgPointer);
_mouse->mouseX = 150;
_mouse->mouseY = 60;
_mouse->mouseMaskIndex = 1;
_mouse->setMouseArea(Common::Rect(55, 13, 250, 105));
for (int i = 1; i <= 6; i++)
buttonBorder((120 - (i * 10)), (80 - (i * 10)), (200 + (i * 10)), (60 + (i * 10)), 251, 251, 251, 251, 0);
drawMenu(6);
euroText(65, 15, Common::String::format(message, numRow, numColumn), 255);
cursorPos = 0;
attempts = 0;
_mouse->warpMouse(1, _mouse->mouseX, _mouse->mouseY);
_screen->markAllDirty();
_screen->update();
Common::Event e;
do {
bool mouseClicked = false;
do {
_chrono->updateChrono();
if (_chrono->_gameTick) {
_mouse->animateMouseIfNeeded();
_chrono->_gameTick = false;
}
while (g_system->getEventManager()->pollEvent(e)) {
if (isMouseEvent(e)) {
_mouse->warpMouse(e.mouse);
_mouse->mouseX = e.mouse.x;
_mouse->mouseY = e.mouse.y;
}
if (e.type == Common::EVENT_LBUTTONUP) {
_mouse->mouseClickX = e.mouse.x;
_mouse->mouseClickY = e.mouse.y;
mouseClicked = true;
}
}
_screen->markAllDirty();
_screen->update();
g_system->delayMillis(10);
} while (!mouseClicked && !shouldQuit());
int correctedMouseX = _mouse->mouseClickX + 7;
int correctedMouseY = _mouse->mouseClickY + 7;
if ((correctedMouseX > 59 && correctedMouseX < 180) && (correctedMouseY > 28 && correctedMouseY < 119)) {
if (correctedMouseY <= 58) {
if (correctedMouseX <= 89) {
if (cursorPos < 50) {
_sound->beep(200, beepDelay);
buttonPress(60, 29, 89, 58, true);
euroText(205 + cursorPos, 44, "0", 255);
inputString = inputString + '0';
buttonPress(60, 29, 89, 58, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
} else if (correctedMouseX <= 119) {
if (cursorPos < 50) {
_sound->beep(250, beepDelay);
buttonPress(90, 29, 119, 58, true);
euroText((205 + cursorPos), 44, "1", 255);
inputString = inputString + '1';
buttonPress(90, 29, 119, 58, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
} else if (correctedMouseX <= 149) {
if (cursorPos < 50) {
_sound->beep(300, beepDelay);
buttonPress(120, 29, 149, 58, true);
euroText((205 + cursorPos), 44, "2", 255);
inputString = inputString + '2';
buttonPress(120, 29, 149, 58, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
} else {
if (cursorPos < 50) {
_sound->beep(350, beepDelay);
buttonPress(150, 29, 179, 58, true);
euroText((205 + cursorPos), 44, "3", 255);
inputString = inputString + '3';
buttonPress(150, 29, 179, 58, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
}
} else if (correctedMouseY <= 88) {
if (correctedMouseX <= 89) {
if (cursorPos < 50) {
_sound->beep(400, beepDelay);
buttonPress(60, 59, 89, 88, true);
euroText((205 + cursorPos), 44, "4", 255);
inputString = inputString + '4';
buttonPress(60, 59, 89, 88, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
} else if (correctedMouseX <= 119) {
if (cursorPos < 50) {
_sound->beep(450, beepDelay);
buttonPress(90, 59, 119, 88, true);
euroText((205 + cursorPos), 44, "5", 255);
inputString = inputString + '5';
buttonPress(90, 59, 119, 88, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
} else if (correctedMouseX <= 149) {
if (cursorPos < 50) {
_sound->beep(500, beepDelay);
buttonPress(120, 59, 149, 88, true);
euroText((205 + cursorPos), 44, "6", 255);
inputString = inputString + '6';
buttonPress(120, 59, 149, 88, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
} else {
if (cursorPos < 50) {
_sound->beep(550, beepDelay);
buttonPress(150, 59, 179, 88, true);
euroText((205 + cursorPos), 44, "7", 255);
inputString = inputString + '7';
buttonPress(150, 59, 179, 88, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
}
} else {
if (correctedMouseX <= 89) {
if (cursorPos < 50) {
_sound->beep(600, beepDelay);
buttonPress(60, 89, 89, 118, true);
euroText((205 + cursorPos), 44, "8", 255);
inputString = inputString + '8';
buttonPress(60, 89, 89, 118, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
} else if (correctedMouseX <= 119) {
if (cursorPos < 50) {
_sound->beep(650, beepDelay);
buttonPress(90, 89, 119, 118, true);
euroText((205 + cursorPos), 44, "9", 255);
inputString = inputString + '9';
buttonPress(90, 89, 119, 118, false);
cursorPos += 10;
} else {
_sound->beep(70, 250);
}
} else if (correctedMouseX <= 149) {
if (cursorPos > 0) {
_sound->beep(700, beepDelay);
buttonPress(120, 89, 149, 118, true);
cursorPos -= 10;
euroText((205 + cursorPos), 44, "\xDB", 250);
inputString = inputString.substr(0, inputString.size() - 1);
buttonPress(120, 89, 149, 118, false);
} else {
_sound->beep(70, 250);
}
} else {
if (cursorPos > 39) {
_sound->beep(750, beepDelay);
buttonPress(150, 89, 179, 118, true);
inputPassword = atoi(inputString.c_str());
buttonPress(150, 89, 179, 118, false);
if (attempts < 3) {
if (inputPassword == correctPassword)
exitDialog = true;
else {
attempts += 1;
_sound->beep(60, 250);
}
}
if (attempts >= 3)
showError(259);
} else {
_sound->beep(70, 250);
}
}
}
}
} while (!exitDialog && !shouldQuit());
_graphics->putImg(50, 10, bgPointer);
_mouse->mouseX = oldMouseX;
_mouse->mouseY = oldMouseY;
_mouse->mouseMaskIndex = oldMouseMaskIndex;
_mouse->warpMouse(_mouse->mouseMaskIndex, _mouse->mouseX, _mouse->mouseY);
if (_cpCounter > 8)
showError(274);
free(bgPointer);
_mouse->setMouseArea(Common::Rect(0, 0, 305, 185));
}
void TotEngine::soundControls() {
uint oldMouseX,
oldMouseY,
soundControlsSize,
sliderSize,
sliderBgSize,
sfxVol,
musicVol,
xfade,
oldxfade;
byte ytext, oldMouseMask;
bool exitSoundControls;
exitSoundControls = false;
oldMouseX = _mouse->mouseX;
oldMouseY = _mouse->mouseY;
oldMouseMask = _mouse->mouseMaskIndex;
_mouse->hide();
soundControlsSize = imagesize(50, 10, 270, 120);
// What was on the screen before blitting sound controls
byte *soundControlsBackground = (byte *)malloc(soundControlsSize);
_graphics->getImg(50, 10, 270, 120, soundControlsBackground);
_mouse->mouseX = 150;
_mouse->mouseY = 60;
_mouse->mouseMaskIndex = 1;
_mouse->setMouseArea(Common::Rect(55, 13, 250, 105));
for (ytext = 1; ytext <= 6; ytext++)
buttonBorder(120 - (ytext * 10), 80 - (ytext * 10), 200 + (ytext * 10), 60 + (ytext * 10), 251, 251, 251, 251, 0);
buttonBorder(86, 31, 94, 44, 0, 0, 0, 0, 0);
line(90, 31, 90, 44, 255);
sliderSize = imagesize(86, 31, 94, 44);
byte *slider = (byte *)malloc(sliderSize);
_graphics->getImg(86, 31, 94, 44, slider);
drawMenu(3);
sliderBgSize = imagesize(86, 31, 234, 44);
byte *sliderBackground1 = (byte *)malloc(sliderBgSize);
byte *sliderBackground2 = (byte *)malloc(sliderBgSize);
_graphics->getImg(86, 31, 234, 44, sliderBackground1);
_graphics->getImg(86, 76, 234, 89, sliderBackground2);
sfxVol = MIN(256, ConfMan.getInt("sfx_volume")) * 140 / 256;
musicVol = MIN(256, ConfMan.getInt("music_volume")) * 140 / 256;
_graphics->putImg(sfxVol + 86, 31, slider);
_graphics->putImg(musicVol + 86, 76, slider);
_mouse->warpMouse(1, _mouse->mouseX, _mouse->mouseY);
bool keyPressed = false;
bool mouseClicked = false;
do {
_chrono->updateChrono();
do {
_chrono->updateChrono();
_mouse->animateMouseIfNeeded();
g_engine->_events->pollEvent(true);
if (g_engine->_events->_keyPressed) {
keyPressed = true;
}
if (g_engine->_events->_leftMouseButton) {
debug("Mouse clicked!");
mouseClicked = true;
_mouse->mouseClickX = g_engine->_events->_mouseX;
_mouse->mouseClickY = g_engine->_events->_mouseY;
}
_screen->update();
} while ((!keyPressed && !mouseClicked) && !shouldQuit());
_chrono->updateChrono();
_mouse->animateMouseIfNeeded();
if (keyPressed) {
exitSoundControls = true;
}
if (mouseClicked) {
if (_mouse->mouseClickY >= 22 && _mouse->mouseClickY <= 37) {
_mouse->hide();
xfade = 86 + sfxVol;
bool mouseReleased = false;
do {
oldxfade = xfade;
g_engine->_events->pollEvent(true);
if (g_engine->_events->_leftMouseButton == 0) {
mouseReleased = true;
} else {
xfade = g_engine->_events->_mouseX;
}
if (xfade < 86) {
xfade = 86;
} else if (xfade > 226) {
xfade = 226;
}
if (oldxfade != xfade) {
_graphics->putImg(86, 31, sliderBackground1);
_graphics->putImg(xfade, 31, slider);
// This yields a volume between 0 and 140
sfxVol = xfade - 86;
ConfMan.setInt("sfx_volume", sfxVol * 256 / 140);
g_engine->syncSoundSettings();
}
_screen->update();
} while (!mouseReleased);
_mouse->show();
} else if (_mouse->mouseClickY >= 67 && _mouse->mouseClickY <= 82) {
_mouse->hide();
xfade = 86 + musicVol;
bool mouseReleased = false;
do {
oldxfade = xfade;
g_engine->_events->pollEvent(true);
if (g_engine->_events->_leftMouseButton == 0) {
mouseReleased = true;
} else {
xfade = g_engine->_events->_mouseX;
}
if (xfade < 86) {
xfade = 86;
} else if (xfade > 226) {
xfade = 226;
}
if (oldxfade != xfade) {
_graphics->putImg(86, 76, sliderBackground2);
_graphics->putImg(xfade, 76, slider);
musicVol = xfade - 86;
ConfMan.setInt("music_volume", musicVol * 256 / 140);
g_engine->syncSoundSettings();
}
_screen->update();
} while (!mouseReleased);
_mouse->show();
} else if (_mouse->mouseClickY >= 97 && _mouse->mouseClickY <= 107) {
exitSoundControls = true;
}
mouseClicked = false;
}
g_system->delayMillis(10);
_screen->update();
} while (!exitSoundControls && !shouldQuit());
_graphics->putImg(50, 10, soundControlsBackground);
_mouse->mouseX = oldMouseX;
_mouse->mouseY = oldMouseY;
_mouse->mouseMaskIndex = oldMouseMask;
_mouse->warpMouse(_mouse->mouseMaskIndex, _mouse->mouseX, _mouse->mouseY);
free(soundControlsBackground);
free(slider);
free(sliderBackground1);
free(sliderBackground2);
if (_cpCounter > 7)
showError(274);
_mouse->setMouseArea(Common::Rect(0, 0, 305, 185));
}
void TotEngine::loadBat() {
Common::File animFile;
_isSecondaryAnimationEnabled = true;
if (!animFile.open("MURCIE.DAT")) {
showError(265);
}
_secondaryAnimFrameSize = animFile.readUint16LE();
_secondaryAnimationFrameCount = animFile.readByte();
_secondaryAnimDirCount = animFile.readByte();
newSecondaryAnimationFrame();
loadAnimationForDirection(&animFile, 0);
animFile.close();
}
void TotEngine::loadDevil() {
Common::File animFile;
_isSecondaryAnimationEnabled = true;
if (!animFile.open("ROJOMOV.DAT")) {
showError(265);
}
_secondaryAnimFrameSize = animFile.readUint16LE();
_secondaryAnimationFrameCount = animFile.readByte();
_secondaryAnimDirCount = animFile.readByte();
newSecondaryAnimationFrame();
if (_secondaryAnimDirCount != 0) {
_secondaryAnimationFrameCount = _secondaryAnimationFrameCount / 4;
for (int i = 0; i <= 3; i++) {
loadAnimationForDirection(&animFile, i);
}
}
animFile.close();
}
void TotEngine::assembleCompleteBackground(byte *image, uint coordx, uint coordy) {
uint16 w, h;
uint16 wFondo;
w = READ_LE_UINT16(image);
h = READ_LE_UINT16(image + 2);
wFondo = READ_LE_UINT16(_sceneBackground);
wFondo++;
w++;
h++;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int color = image[4 + j * w + i];
if (color != 0) {
_sceneBackground[4 + (coordy + j) * wFondo + (coordx + i)] = color;
}
}
}
}
/**
* Assemble the screen for scroll assembles only the objects because scrolling screens
* never have secondary animations and character animation is assembled elsewhere.
*/
void TotEngine::assembleScreen(bool scroll) {
for (int indice = 0; indice < kDepthLevelCount; indice++) {
if (_screenLayers[indice] != nullptr) {
assembleCompleteBackground(_screenLayers[indice], _depthMap[indice].posx, _depthMap[indice].posy);
}
if (!scroll && _mainCharAnimation.depth == indice) {
assembleCompleteBackground(_mainCharAnimation.bitmap[_charFacingDirection][_iframe], _characterPosX, _characterPosY);
}
if (!scroll && _currentRoomData->animationFlag && _secondaryAnimation.depth == indice) {
assembleCompleteBackground(_curSecondaryAnimationFrame, _secondaryAnimation.posx, _secondaryAnimation.posy);
}
}
}
void TotEngine::disableSecondAnimation() {
setRoomTrajectories(_secondaryAnimHeight, _secondaryAnimWidth, RESTORE);
_currentRoomData->animationFlag = false;
clearAnimation();
_graphics->restoreBackground();
assembleScreen();
}
void TotEngine::setRoomTrajectories(int animationHeight, int animationWidth, TRAJECTORIES_OP op, bool fixGrids) {
// add to restore the room, subtract to adjust before loading the screen
if (_currentRoomData->animationFlag && _currentRoomData->animationName != "QQQQQQQQ") {
for (int i = 0; i < _currentRoomData->secondaryTrajectoryLength; i++) {
if (op == RESTORE) {
_currentRoomData->secondaryAnimTrajectory[i].x = _currentRoomData->secondaryAnimTrajectory[i].x + (animationWidth >> 1);
_currentRoomData->secondaryAnimTrajectory[i].y = _currentRoomData->secondaryAnimTrajectory[i].y + animationHeight;
} else {
_currentRoomData->secondaryAnimTrajectory[i].x = _currentRoomData->secondaryAnimTrajectory[i].x - (animationWidth >> 1);
_currentRoomData->secondaryAnimTrajectory[i].y = _currentRoomData->secondaryAnimTrajectory[i].y - animationHeight;
}
}
if (fixGrids) {
for (int i = 0; i < _maxXGrid; i++) {
for (int j = 0; j < _maxYGrid; j++) {
if (op == RESTORE) {
_currentRoomData->walkAreasGrid[_oldposx + i][_oldposy + j] = _movementGridForSecondaryAnim[i][j];
_currentRoomData->mouseGrid[_oldposx + i][_oldposy + j] = _mouseGridForSecondaryAnim[i][j];
} else {
if (_maskGridSecondaryAnim[i][j] > 0)
_currentRoomData->walkAreasGrid[_oldposx + i][_oldposy + j] = _maskGridSecondaryAnim[i][j];
if (_maskMouseSecondaryAnim[i][j] > 0)
_currentRoomData->mouseGrid[_oldposx + i][_oldposy + j] = _maskMouseSecondaryAnim[i][j];
}
}
}
}
}
}
} // End of namespace Tot