mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-29 21:24:53 +00:00
766 lines
22 KiB
C++
766 lines
22 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "graphics/palette.h"
|
|
|
|
#include "prince/prince.h"
|
|
|
|
#include "prince/animation.h"
|
|
#include "prince/graphics.h"
|
|
#include "prince/hero.h"
|
|
#include "prince/script.h"
|
|
|
|
namespace Prince {
|
|
|
|
bool PrinceEngine::spriteCheck(int sprWidth, int sprHeight, int destX, int destY) {
|
|
destX -= _picWindowX;
|
|
destY -= _picWindowY;
|
|
|
|
// if x1 is on visible part of screen
|
|
if (destX < 0) {
|
|
if (destX + sprWidth < 1) {
|
|
//x2 is negative - out of window
|
|
return false;
|
|
}
|
|
}
|
|
// if x1 is outside of screen on right side
|
|
if (destX >= kNormalWidth) {
|
|
return false;
|
|
}
|
|
|
|
if (destY < 0) {
|
|
if (destY + sprHeight < 1) {
|
|
//y2 is negative - out of window
|
|
return false;
|
|
}
|
|
}
|
|
if (destY >= kNormalHeight) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// CheckNak
|
|
void PrinceEngine::checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z) {
|
|
int x2 = x1 + sprWidth - 1;
|
|
int y2 = y1 + sprHeight - 1;
|
|
if (x1 < 0) {
|
|
x1 = 0;
|
|
}
|
|
for (uint i = 0; i < _maskList.size(); i++) {
|
|
if (!_maskList[i]._state && !_maskList[i]._flags) {
|
|
if (_maskList[i]._z > z) {
|
|
if (_maskList[i]._x1 <= x2 && _maskList[i]._x2 >= x1) {
|
|
if (_maskList[i]._y1 <= y2 && _maskList[i]._y2 >= y1) {
|
|
_maskList[i]._state = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ClsNak
|
|
void PrinceEngine::clsMasks() {
|
|
for (uint i = 0; i < _maskList.size(); i++) {
|
|
if (_maskList[i]._state) {
|
|
_maskList[i]._state = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// InsertNakladki
|
|
void PrinceEngine::insertMasks(Graphics::Surface *originalRoomSurface) {
|
|
for (uint i = 0; i < _maskList.size(); i++) {
|
|
if (_maskList[i]._state) {
|
|
if (_maskList[i]._data != nullptr) {
|
|
showMask(i, originalRoomSurface);
|
|
} else {
|
|
error("insertMasks() - Wrong mask data- nr %d", i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ShowNak
|
|
void PrinceEngine::showMask(int maskNr, Graphics::Surface *originalRoomSurface) {
|
|
if (!_maskList[maskNr]._flags) {
|
|
if (spriteCheck(_maskList[maskNr]._width, _maskList[maskNr]._height, _maskList[maskNr]._x1, _maskList[maskNr]._y1)) {
|
|
int destX = _maskList[maskNr]._x1 - _picWindowX;
|
|
int destY = _maskList[maskNr]._y1 - _picWindowY;
|
|
DrawNode newDrawNode;
|
|
newDrawNode.posX = destX;
|
|
newDrawNode.posY = destY;
|
|
newDrawNode.posZ = _maskList[maskNr]._z;
|
|
newDrawNode.width = _maskList[maskNr]._width;
|
|
newDrawNode.height = _maskList[maskNr]._height;
|
|
newDrawNode.s = nullptr;
|
|
newDrawNode.originalRoomSurface = originalRoomSurface;
|
|
newDrawNode.data = _maskList[maskNr].getMask();
|
|
newDrawNode.drawFunction = &_graph->drawMaskDrawNode;
|
|
_drawNodeList.push_back(newDrawNode);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ) {
|
|
if (spriteCheck(spriteSurface->w, spriteSurface->h, destX, destY)) {
|
|
destX -= _picWindowX;
|
|
destY -= _picWindowY;
|
|
DrawNode newDrawNode;
|
|
newDrawNode.posX = destX;
|
|
newDrawNode.posY = destY;
|
|
newDrawNode.posZ = destZ;
|
|
newDrawNode.width = 0;
|
|
newDrawNode.height = 0;
|
|
newDrawNode.s = spriteSurface;
|
|
newDrawNode.originalRoomSurface = nullptr;
|
|
newDrawNode.data = _transTable;
|
|
newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
|
|
_drawNodeList.push_back(newDrawNode);
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ) {
|
|
if (spriteCheck(shadowSurface->w, shadowSurface->h, destX, destY)) {
|
|
destX -= _picWindowX;
|
|
destY -= _picWindowY;
|
|
DrawNode newDrawNode;
|
|
newDrawNode.posX = destX;
|
|
newDrawNode.posY = destY;
|
|
newDrawNode.posZ = destZ;
|
|
newDrawNode.width = 0;
|
|
newDrawNode.height = 0;
|
|
newDrawNode.s = shadowSurface;
|
|
newDrawNode.originalRoomSurface = nullptr;
|
|
newDrawNode.data = _graph->_shadowTable70;
|
|
newDrawNode.drawFunction = &_graph->drawAsShadowDrawNode;
|
|
_drawNodeList.push_back(newDrawNode);
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::showAnim(Anim &anim) {
|
|
//ShowFrameCode
|
|
//ShowAnimFrame
|
|
int phase = anim._showFrame;
|
|
int phaseFrameIndex = anim._animData->getPhaseFrameIndex(phase);
|
|
int x = anim._x + anim._animData->getPhaseOffsetX(phase);
|
|
int y = anim._y + anim._animData->getPhaseOffsetY(phase);
|
|
int animFlag = anim._flags;
|
|
int checkMaskFlag = (animFlag & 1);
|
|
int maxFrontFlag = (animFlag & 2);
|
|
int specialZFlag = anim._nextAnim;
|
|
int z = anim._nextAnim;
|
|
Graphics::Surface *animSurface = anim._animData->getFrame(phaseFrameIndex);
|
|
int frameWidth = animSurface->w;
|
|
int frameHeight = animSurface->h;
|
|
int shadowZ = 0;
|
|
|
|
if (checkMaskFlag) {
|
|
if (!anim._nextAnim) {
|
|
z = y + frameHeight - 1;
|
|
}
|
|
checkMasks(x, y, frameWidth, frameHeight, z);
|
|
}
|
|
|
|
if (specialZFlag) {
|
|
z = specialZFlag;
|
|
} else if (maxFrontFlag) {
|
|
z = kMaxPicHeight + 1;
|
|
} else {
|
|
z = y + frameHeight - 1;
|
|
}
|
|
shadowZ = z;
|
|
|
|
anim._currX = x;
|
|
anim._currY = y;
|
|
anim._currW = frameWidth;
|
|
anim._currH = frameHeight;
|
|
showSprite(animSurface, x, y, z);
|
|
|
|
// make_special_shadow
|
|
if ((anim._flags & 0x80)) {
|
|
DrawNode newDrawNode;
|
|
newDrawNode.posX = x;
|
|
newDrawNode.posY = y + animSurface->h - anim._shadowBack;
|
|
newDrawNode.posZ = Hero::kHeroShadowZ;
|
|
newDrawNode.width = 0;
|
|
newDrawNode.height = 0;
|
|
newDrawNode.scaleValue = _scaleValue;
|
|
newDrawNode.originalRoomSurface = nullptr;
|
|
newDrawNode.data = this;
|
|
newDrawNode.drawFunction = &Hero::showHeroShadow;
|
|
newDrawNode.s = animSurface;
|
|
_drawNodeList.push_back(newDrawNode);
|
|
}
|
|
|
|
//ShowFrameCodeShadow
|
|
//ShowAnimFrameShadow
|
|
if (anim._shadowData != nullptr) {
|
|
int shadowPhaseFrameIndex = anim._shadowData->getPhaseFrameIndex(phase);
|
|
int shadowX = anim._shadowData->getBaseX() + anim._shadowData->getPhaseOffsetX(phase);
|
|
int shadowY = anim._shadowData->getBaseY() + anim._shadowData->getPhaseOffsetY(phase);
|
|
Graphics::Surface *shadowSurface = anim._shadowData->getFrame(shadowPhaseFrameIndex);
|
|
int shadowFrameWidth = shadowSurface->w;
|
|
int shadowFrameHeight = shadowSurface->h;
|
|
|
|
if (checkMaskFlag) {
|
|
checkMasks(shadowX, shadowY, shadowFrameWidth, shadowFrameHeight, shadowY + shadowFrameWidth - 1);
|
|
}
|
|
|
|
if (!shadowZ) {
|
|
if (maxFrontFlag) {
|
|
shadowZ = kMaxPicHeight + 1;
|
|
} else {
|
|
shadowZ = shadowY + shadowFrameWidth - 1;
|
|
}
|
|
}
|
|
showSpriteShadow(shadowSurface, shadowX, shadowY, shadowZ);
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::showNormAnims() {
|
|
for (int i = 0; i < kMaxNormAnims; i++) {
|
|
Anim &anim = _normAnimList[i];
|
|
if (anim._animData != nullptr) {
|
|
int phaseCount = anim._animData->getPhaseCount();
|
|
if (!anim._state) {
|
|
if (anim._frame == anim._lastFrame - 1) {
|
|
if (anim._loopType) {
|
|
if (anim._loopType == 1) {
|
|
anim._frame = anim._loopFrame;
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
} else {
|
|
anim._frame++;
|
|
}
|
|
anim._showFrame = anim._frame;
|
|
if (anim._showFrame >= phaseCount) {
|
|
anim._showFrame = phaseCount - 1;
|
|
}
|
|
showAnim(anim);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::setBackAnim(Anim &backAnim) {
|
|
int start = backAnim._basaData._start;
|
|
if (start != -1) {
|
|
backAnim._frame = start;
|
|
backAnim._showFrame = start;
|
|
backAnim._loopFrame = start;
|
|
}
|
|
int end = backAnim._basaData._end;
|
|
if (end != -1) {
|
|
backAnim._lastFrame = end;
|
|
}
|
|
backAnim._state = 0;
|
|
}
|
|
|
|
void PrinceEngine::showBackAnims() {
|
|
for (int i = 0; i < kMaxBackAnims; i++) {
|
|
BAS &seq = _backAnimList[i]._seq;
|
|
int activeSubAnim = seq._currRelative;
|
|
if (!_backAnimList[i].backAnims.empty()) {
|
|
if (_backAnimList[i].backAnims[activeSubAnim]._animData != nullptr) {
|
|
if (!_backAnimList[i].backAnims[activeSubAnim]._state) {
|
|
seq._counter++;
|
|
if (seq._type == 2) {
|
|
if (!seq._currRelative) {
|
|
if (seq._counter >= seq._data) {
|
|
if (seq._anims > 2) {
|
|
seq._currRelative = _randomSource.getRandomNumber(seq._anims - 2) + 1;
|
|
activeSubAnim = seq._currRelative;
|
|
seq._current = _backAnimList[i].backAnims[activeSubAnim]._basaData._num;
|
|
}
|
|
setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
|
seq._counter = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (seq._type == 3) {
|
|
if (!seq._currRelative) {
|
|
if (seq._counter < seq._data2) {
|
|
continue;
|
|
} else {
|
|
setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_backAnimList[i].backAnims[activeSubAnim]._frame == _backAnimList[i].backAnims[activeSubAnim]._lastFrame - 1) {
|
|
_backAnimList[i].backAnims[activeSubAnim]._frame = _backAnimList[i].backAnims[activeSubAnim]._loopFrame;
|
|
switch (seq._type) {
|
|
case 1:
|
|
if (seq._anims > 1) {
|
|
int rnd;
|
|
do {
|
|
rnd = _randomSource.getRandomNumber(seq._anims - 1);
|
|
} while (rnd == seq._currRelative);
|
|
seq._currRelative = rnd;
|
|
seq._current = _backAnimList[i].backAnims[rnd]._basaData._num;
|
|
activeSubAnim = rnd;
|
|
setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
|
seq._counter = 0;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (seq._currRelative) {
|
|
seq._currRelative = 0;
|
|
seq._current = _backAnimList[i].backAnims[0]._basaData._num;
|
|
activeSubAnim = 0;
|
|
setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
|
seq._counter = 0;
|
|
}
|
|
break;
|
|
case 3:
|
|
seq._currRelative = 0;
|
|
seq._current = _backAnimList[i].backAnims[0]._basaData._num;
|
|
seq._counter = 0;
|
|
seq._data2 = _randomSource.getRandomNumber(seq._data - 1);
|
|
continue; // for bug in original game
|
|
break;
|
|
}
|
|
} else {
|
|
_backAnimList[i].backAnims[activeSubAnim]._frame++;
|
|
}
|
|
_backAnimList[i].backAnims[activeSubAnim]._showFrame = _backAnimList[i].backAnims[activeSubAnim]._frame;
|
|
showAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::removeSingleBackAnim(int slot) {
|
|
if (!_backAnimList[slot].backAnims.empty()) {
|
|
for (uint j = 0; j < _backAnimList[slot].backAnims.size(); j++) {
|
|
if (_backAnimList[slot].backAnims[j]._animData != nullptr) {
|
|
delete _backAnimList[slot].backAnims[j]._animData;
|
|
_backAnimList[slot].backAnims[j]._animData = nullptr;
|
|
}
|
|
if (_backAnimList[slot].backAnims[j]._shadowData != nullptr) {
|
|
delete _backAnimList[slot].backAnims[j]._shadowData;
|
|
_backAnimList[slot].backAnims[j]._shadowData = nullptr;
|
|
}
|
|
}
|
|
_backAnimList[slot].backAnims.clear();
|
|
_backAnimList[slot]._seq._currRelative = 0;
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::clearBackAnimList() {
|
|
for (int i = 0; i < kMaxBackAnims; i++) {
|
|
removeSingleBackAnim(i);
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::grabMap() {
|
|
_graph->_frontScreen->copyFrom(*_roomBmp->getSurface());
|
|
showObjects();
|
|
runDrawNodes();
|
|
_graph->_mapScreen->copyFrom(*_graph->_frontScreen);
|
|
}
|
|
|
|
void PrinceEngine::initZoomIn(int slot) {
|
|
freeZoomObject(slot);
|
|
Object *object = _objList[slot];
|
|
if (object != nullptr) {
|
|
Graphics::Surface *zoomSource = object->getSurface();
|
|
if (zoomSource != nullptr) {
|
|
object->_flags |= 0x8000;
|
|
object->_zoomSurface = new Graphics::Surface();
|
|
object->_zoomSurface->create(zoomSource->w, zoomSource->h, Graphics::PixelFormat::createFormatCLUT8());
|
|
object->_zoomSurface->fillRect(Common::Rect(zoomSource->w, zoomSource->h), 0xFF);
|
|
object->_zoomTime = 20;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::initZoomOut(int slot) {
|
|
freeZoomObject(slot);
|
|
Object *object = _objList[slot];
|
|
if (object != nullptr) {
|
|
Graphics::Surface *zoomSource = object->getSurface();
|
|
if (zoomSource != nullptr) {
|
|
object->_flags |= 0x4000;
|
|
object->_zoomSurface = new Graphics::Surface();
|
|
object->_zoomSurface->copyFrom(*zoomSource);
|
|
object->_zoomTime = 10;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::doZoomIn(int slot) {
|
|
Object *object = _objList[slot];
|
|
if (object != nullptr) {
|
|
Graphics::Surface *orgSurface = object->getSurface();
|
|
if (orgSurface != nullptr) {
|
|
byte *src1 = (byte *)orgSurface->getBasePtr(0, 0);
|
|
byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
|
|
int x = 0;
|
|
int surfaceHeight = orgSurface->h;
|
|
for (int y = 0; y < surfaceHeight; y++) {
|
|
byte *src2 = src1;
|
|
byte *dst2 = dst1;
|
|
int w = orgSurface->w - x;
|
|
src2 += x;
|
|
dst2 += x;
|
|
while (w > 0) {
|
|
int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
|
|
if (randVal < w) {
|
|
*(dst2 + randVal) = *(src2 + randVal);
|
|
src2 += zoomInStep;
|
|
dst2 += zoomInStep;
|
|
} else if (y + 1 != surfaceHeight) {
|
|
*(dst1 + orgSurface->pitch + randVal - w) = *(src1 + orgSurface->pitch + randVal - w);
|
|
}
|
|
w -= zoomInStep;
|
|
}
|
|
x = -1 * w;
|
|
src1 += orgSurface->pitch;
|
|
dst1 += orgSurface->pitch;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::doZoomOut(int slot) {
|
|
Object *object = _objList[slot];
|
|
if (object != nullptr) {
|
|
Graphics::Surface *orgSurface = object->getSurface();
|
|
if (orgSurface != nullptr) {
|
|
byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
|
|
int x = 0;
|
|
int surfaceHeight = orgSurface->h;
|
|
for (int y = 0; y < surfaceHeight; y++) {
|
|
byte *dst2 = dst1;
|
|
int w = orgSurface->w - x;
|
|
dst2 += x;
|
|
while (w > 0) {
|
|
int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
|
|
if (randVal < w) {
|
|
*(dst2 + randVal) = 255;
|
|
dst2 += zoomInStep;
|
|
} else if (y + 1 != surfaceHeight) {
|
|
*(dst1 + orgSurface->pitch + randVal - w) = 255;
|
|
}
|
|
w -= zoomInStep;
|
|
}
|
|
x = -1 * w;
|
|
dst1 += orgSurface->pitch;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::freeZoomObject(int slot) {
|
|
Object *object = _objList[slot];
|
|
if (object != nullptr) {
|
|
if (object->_zoomSurface != nullptr) {
|
|
object->_zoomSurface->free();
|
|
delete object->_zoomSurface;
|
|
object->_zoomSurface = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::showObjects() {
|
|
for (int i = 0; i < kMaxObjects; i++) {
|
|
int nr = _objSlot[i];
|
|
if (nr != 0xFF) {
|
|
Graphics::Surface *objSurface = nullptr;
|
|
if ((_objList[nr]->_flags & 0x8000)) {
|
|
_objList[nr]->_zoomTime--;
|
|
if (!_objList[nr]->_zoomTime) {
|
|
freeZoomObject(nr);
|
|
_objList[nr]->_flags &= 0x7FFF;
|
|
objSurface = _objList[nr]->getSurface();
|
|
} else {
|
|
doZoomIn(nr);
|
|
objSurface = _objList[nr]->_zoomSurface;
|
|
}
|
|
} else if ((_objList[nr]->_flags & 0x4000)) {
|
|
_objList[nr]->_zoomTime--;
|
|
if (!_objList[nr]->_zoomTime) {
|
|
freeZoomObject(nr);
|
|
_objList[nr]->_flags &= 0xBFFF;
|
|
objSurface = _objList[nr]->getSurface();
|
|
} else {
|
|
doZoomOut(nr);
|
|
objSurface = _objList[nr]->_zoomSurface;
|
|
}
|
|
} else {
|
|
objSurface = _objList[nr]->getSurface();
|
|
}
|
|
|
|
if (objSurface != nullptr) {
|
|
if (spriteCheck(objSurface->w, objSurface->h, _objList[nr]->_x, _objList[nr]->_y)) {
|
|
int destX = _objList[nr]->_x - _picWindowX;
|
|
int destY = _objList[nr]->_y - _picWindowY;
|
|
DrawNode newDrawNode;
|
|
newDrawNode.posX = destX;
|
|
newDrawNode.posY = destY;
|
|
newDrawNode.posZ = _objList[nr]->_z;
|
|
newDrawNode.width = 0;
|
|
newDrawNode.height = 0;
|
|
newDrawNode.s = objSurface;
|
|
newDrawNode.originalRoomSurface = nullptr;
|
|
if ((_objList[nr]->_flags & 0x2000)) {
|
|
newDrawNode.data = nullptr;
|
|
newDrawNode.drawFunction = &_graph->drawBackSpriteDrawNode;
|
|
} else {
|
|
newDrawNode.data = _transTable;
|
|
if (_flags->getFlagValue(Flags::NOANTIALIAS)) {
|
|
newDrawNode.drawFunction = &_graph->drawTransparentDrawNode;
|
|
} else {
|
|
newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
|
|
}
|
|
}
|
|
_drawNodeList.push_back(newDrawNode);
|
|
}
|
|
|
|
if ((_objList[nr]->_flags & 1)) {
|
|
checkMasks(_objList[nr]->_x, _objList[nr]->_y, objSurface->w, objSurface->h, _objList[nr]->_z);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::showParallax() {
|
|
if (!_pscrList.empty()) {
|
|
for (uint i = 0; i < _pscrList.size(); i++) {
|
|
Graphics::Surface *pscrSurface = _pscrList[i]->getSurface();
|
|
if (pscrSurface != nullptr) {
|
|
int x = _pscrList[i]->_x - (_pscrList[i]->_step * _picWindowX / 4);
|
|
int y = _pscrList[i]->_y;
|
|
int z = PScr::kPScrZ;
|
|
if (spriteCheck(pscrSurface->w, pscrSurface->h, x, y)) {
|
|
showSprite(pscrSurface, x, y, z);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool PrinceEngine::compareDrawNodes(DrawNode d1, DrawNode d2) {
|
|
if (d1.posZ < d2.posZ) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void PrinceEngine::runDrawNodes() {
|
|
Common::sort(_drawNodeList.begin(), _drawNodeList.end(), compareDrawNodes);
|
|
|
|
for (uint i = 0; i < _drawNodeList.size(); i++) {
|
|
(*_drawNodeList[i].drawFunction)(_graph->_frontScreen, &_drawNodeList[i]);
|
|
}
|
|
_graph->change();
|
|
}
|
|
|
|
void PrinceEngine::drawScreen() {
|
|
if (!_showInventoryFlag || _inventoryBackgroundRemember) {
|
|
clsMasks();
|
|
|
|
_mainHero->showHero();
|
|
_mainHero->scrollHero();
|
|
_mainHero->drawHero();
|
|
|
|
_secondHero->showHero();
|
|
_secondHero->_drawX -= _picWindowX;
|
|
_secondHero->drawHero();
|
|
|
|
const Graphics::Surface *roomSurface;
|
|
if (_locationNr != 50) {
|
|
roomSurface = _roomBmp->getSurface();
|
|
} else {
|
|
roomSurface = _graph->_mapScreen;
|
|
}
|
|
Graphics::Surface visiblePart;
|
|
if (roomSurface) {
|
|
visiblePart = roomSurface->getSubArea(Common::Rect(_picWindowX, 0, roomSurface->w, roomSurface->h));
|
|
_graph->draw(_graph->_frontScreen, &visiblePart);
|
|
}
|
|
|
|
showBackAnims();
|
|
|
|
showNormAnims();
|
|
|
|
playNextFLCFrame();
|
|
|
|
showObjects();
|
|
|
|
if (roomSurface) {
|
|
insertMasks(&visiblePart);
|
|
}
|
|
|
|
showParallax();
|
|
|
|
runDrawNodes();
|
|
|
|
_drawNodeList.clear();
|
|
|
|
if (!_inventoryBackgroundRemember && !_dialogFlag) {
|
|
if (!_optionsFlag) {
|
|
_selectedMob = checkMob(_graph->_frontScreen, _mobList, true);
|
|
}
|
|
showTexts(_graph->_frontScreen);
|
|
checkOptions();
|
|
} else {
|
|
_inventoryBackgroundRemember = false;
|
|
}
|
|
|
|
showPower();
|
|
|
|
getDebugger()->onFrame();
|
|
|
|
} else {
|
|
displayInventory();
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::blackPalette() {
|
|
byte *paletteBackup = (byte *)malloc(256 * 3);
|
|
byte *blackPalette1 = (byte *)malloc(256 * 3);
|
|
|
|
int fadeStep = kFadeStep - 1;
|
|
for (int i = 0; i < kFadeStep; i++) {
|
|
_system->getPaletteManager()->grabPalette(paletteBackup, 0, 256);
|
|
for (int j = 0; j < 256; j++) {
|
|
blackPalette1[3 * j] = paletteBackup[3 * j] * fadeStep / 4;
|
|
blackPalette1[3 * j + 1] = paletteBackup[3 * j + 1] * fadeStep / 4;
|
|
blackPalette1[3 * j + 2] = paletteBackup[3 * j + 2] * fadeStep / 4;
|
|
}
|
|
fadeStep--;
|
|
_graph->setPalette(blackPalette1);
|
|
_system->updateScreen();
|
|
Common::Event event;
|
|
Common::EventManager *eventMan = _system->getEventManager();
|
|
eventMan->pollEvent(event);
|
|
if (shouldQuit()) {
|
|
free(paletteBackup);
|
|
free(blackPalette1);
|
|
return;
|
|
}
|
|
pausePrinceEngine();
|
|
}
|
|
free(paletteBackup);
|
|
free(blackPalette1);
|
|
}
|
|
|
|
void PrinceEngine::setPalette(const byte *palette) {
|
|
if (palette != nullptr) {
|
|
byte *blackPalette_ = (byte *)malloc(256 * 3);
|
|
int fadeStep = 0;
|
|
for (int i = 0; i <= kFadeStep; i++) {
|
|
for (int j = 0; j < 256; j++) {
|
|
blackPalette_[3 * j] = palette[3 * j] * fadeStep / 4;
|
|
blackPalette_[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
|
|
blackPalette_[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
|
|
}
|
|
fadeStep++;
|
|
_graph->setPalette(blackPalette_);
|
|
_system->updateScreen();
|
|
Common::Event event;
|
|
Common::EventManager *eventMan = _system->getEventManager();
|
|
eventMan->pollEvent(event);
|
|
if (shouldQuit()) {
|
|
_graph->setPalette(palette);
|
|
free(blackPalette_);
|
|
return;
|
|
}
|
|
pausePrinceEngine();
|
|
}
|
|
_graph->setPalette(palette);
|
|
free(blackPalette_);
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::doTalkAnim(int animNumber, int slot, AnimType animType) {
|
|
Text &text = _textSlots[slot];
|
|
int lines = calcTextLines((const char *)_interpreter->getString());
|
|
int time = lines * 30;
|
|
if (animType == kNormalAnimation) {
|
|
Anim &normAnim = _normAnimList[animNumber];
|
|
if (normAnim._animData != nullptr) {
|
|
if (!normAnim._state) {
|
|
if (normAnim._currW && normAnim._currH) {
|
|
text._color = _flags->getFlagValue(Flags::KOLOR);
|
|
text._x = normAnim._currX + normAnim._currW / 2;
|
|
text._y = normAnim._currY - 10;
|
|
}
|
|
}
|
|
}
|
|
} else if (animType == kBackgroundAnimation) {
|
|
if (!_backAnimList[animNumber].backAnims.empty()) {
|
|
int currAnim = _backAnimList[animNumber]._seq._currRelative;
|
|
Anim &backAnim = _backAnimList[animNumber].backAnims[currAnim];
|
|
if (backAnim._animData != nullptr) {
|
|
if (!backAnim._state) {
|
|
if (backAnim._currW && backAnim._currH) {
|
|
text._color = _flags->getFlagValue(Flags::KOLOR);
|
|
text._x = backAnim._currX + backAnim._currW / 2;
|
|
text._y = backAnim._currY - 10;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
error("doTalkAnim() - wrong animType: %d", animType);
|
|
}
|
|
text._time = time;
|
|
if (getLanguage() == Common::DE_DEU) {
|
|
correctStringDEU((char *)_interpreter->getString());
|
|
}
|
|
text._str = (const char *)_interpreter->getString();
|
|
_interpreter->increaseString();
|
|
}
|
|
|
|
void PrinceEngine::freeNormAnim(int slot) {
|
|
if (!_normAnimList.empty()) {
|
|
_normAnimList[slot]._state = 1;
|
|
if (_normAnimList[slot]._animData != nullptr) {
|
|
delete _normAnimList[slot]._animData;
|
|
_normAnimList[slot]._animData = nullptr;
|
|
}
|
|
if (_normAnimList[slot]._shadowData != nullptr) {
|
|
delete _normAnimList[slot]._shadowData;
|
|
_normAnimList[slot]._shadowData = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrinceEngine::freeAllNormAnims() {
|
|
for (int i = 0; i < kMaxNormAnims; i++) {
|
|
freeNormAnim(i);
|
|
}
|
|
}
|
|
|
|
} // End of namespace Prince
|