diff options
Diffstat (limited to 'engines/prince/hero.cpp')
-rw-r--r-- | engines/prince/hero.cpp | 1004 |
1 files changed, 1004 insertions, 0 deletions
diff --git a/engines/prince/hero.cpp b/engines/prince/hero.cpp new file mode 100644 index 0000000000..8c13c6d1f9 --- /dev/null +++ b/engines/prince/hero.cpp @@ -0,0 +1,1004 @@ +/* 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 "common/debug.h" +#include "common/random.h" + +#include "prince/hero.h" +#include "prince/hero_set.h" +#include "prince/animation.h" +#include "prince/resource.h" +#include "prince/prince.h" +#include "prince/graphics.h" +#include "prince/flags.h" +#include "prince/script.h" + +namespace Prince { + +Hero::Hero(PrinceEngine *vm, GraphicsMan *graph) : _vm(vm), _graph(graph), + _number(0), _visible(false), _state(kHeroStateStay), _middleX(0), _middleY(0), + _boreNum(1), _currHeight(0), _moveDelay(0), _shadMinus(0), _moveSetType(0), _zoomedHeroSurface(nullptr), + _lastDirection(kHeroDirDown), _destDirection(kHeroDirDown), _talkTime(0), _boredomTime(0), _phase(0), + _specAnim(nullptr), _drawX(0), _drawY(0), _drawZ(0), + _frameXSize(0), _frameYSize(0), _scaledFrameXSize(0), _scaledFrameYSize(0), _color(0), + _coords(nullptr), _dirTab(nullptr), _currCoords(nullptr), _currDirTab(nullptr), _step(0), + _maxBoredom(200), _leftRightMainDir(0), _upDownMainDir(0), _animSetNr(0) +{ +} + +Hero::~Hero() { + freeHeroAnim(); + freeOldMove(); + freeZoomedSurface(); +} + +bool Hero::loadAnimSet(uint32 animSetNr) { + _animSetNr = animSetNr; + + if (animSetNr > sizeof(heroSetTable)) { + return false; + } + + _shadMinus = heroSetBack[animSetNr]; + + for (uint32 i = 0; i < _moveSet.size(); i++) { + delete _moveSet[i]; + } + + const HeroSetAnimNames &animSet = *heroSetTable[animSetNr]; + + _moveSet.resize(kMoveSetSize); + for (uint32 i = 0; i < kMoveSetSize; i++) { + debug("Anim set item %d %s", i, animSet[i]); + Animation *anim = nullptr; + if (animSet[i] != nullptr) { + anim = new Animation(); + Resource::loadResource(anim, animSet[i], false); + } + _moveSet[i] = anim; + } + + return true; +} + +Graphics::Surface *Hero::getSurface() { + Animation *heroAnim = nullptr; + if (_specAnim != nullptr) { + heroAnim = _specAnim; + } else { + heroAnim = _moveSet[_moveSetType]; + } + + if (heroAnim != nullptr) { + int16 phaseFrameIndex = heroAnim->getPhaseFrameIndex(_phase); + Graphics::Surface *heroFrame = heroAnim->getFrame(phaseFrameIndex); + return heroFrame; + } + return nullptr; +} + +uint16 Hero::getData(AttrId dataId) { + switch (dataId) { + case kHeroLastDir: + return _lastDirection; + case kHeroAnimSet: + return _animSetNr; + default: + assert(false); + return 0; + } +} + +int Hero::getScaledValue(int size) { + int newSize = 0; + int16 initScaleValue = _vm->_scaleValue; + if (_vm->_scaleValue != 10000) { + for (int i = 0; i < size; i++) { + initScaleValue -= 100; + if (initScaleValue >= 0) { + newSize++; + } else { + initScaleValue += _vm->_scaleValue; + } + } + return newSize; + } else { + return size; + } +} + +Graphics::Surface *Hero::zoomSprite(Graphics::Surface *heroFrame) { + Graphics::Surface *zoomedFrame = new Graphics::Surface(); + zoomedFrame->create(_scaledFrameXSize, _scaledFrameYSize, Graphics::PixelFormat::createFormatCLUT8()); + + int sprZoomX; + int sprZoomY = _vm->_scaleValue; + uint xSource = 0; + uint ySource = 0; + uint xDest = 0; + uint yDest = 0; + + for (int i = 0; i < _scaledFrameYSize; i++) { + // linear_loop: + while (1) { + sprZoomY -= 100; + if (sprZoomY >= 0 || _vm->_scaleValue == 10000) { + // all_r_y + sprZoomX = _vm->_scaleValue; + break; // to loop_lin + } else { + sprZoomY += _vm->_scaleValue; + xSource = 0; + ySource++; + } + } + // loop_lin: + for (int j = 0; j < _scaledFrameXSize; j++) { + sprZoomX -= 100; + if (sprZoomX >= 0) { + // its_all_r + memcpy(zoomedFrame->getBasePtr(xDest, yDest), heroFrame->getBasePtr(xSource, ySource), 1); + xDest++; + } else { + sprZoomX += _vm->_scaleValue; + j--; + } + xSource++; + } + xDest = 0; + yDest++; + xSource = 0; + ySource++; + } + return zoomedFrame; +} + +void Hero::countDrawPosition() { + Animation *heroAnim = nullptr; + if (_specAnim != nullptr) { + heroAnim = _specAnim; + } else { + heroAnim = _moveSet[_moveSetType]; + } + if (heroAnim != nullptr) { + int phaseFrameIndex = heroAnim->getPhaseFrameIndex(_phase); + Graphics::Surface *heroSurface = heroAnim->getFrame(phaseFrameIndex); + + _frameXSize = heroSurface->w; + _frameYSize = heroSurface->h; + _scaledFrameXSize = getScaledValue(_frameXSize); + _scaledFrameYSize = getScaledValue(_frameYSize); + + if (_vm->_scaleValue != 10000) { + //notfullSize + _drawX = _middleX - _scaledFrameXSize / 2; + _drawY = _middleY + 1 - _scaledFrameYSize; + _vm->checkMasks(_drawX, _drawY - 1, _scaledFrameXSize, _scaledFrameYSize, _middleY); + } else { + //fullSize + _drawX = _middleX - _frameXSize / 2; + _drawY = _middleY + 1 - _frameYSize; + _vm->checkMasks(_drawX, _drawY - 1, _frameXSize, _frameYSize, _middleY); + } + _drawZ = _middleY; + } +} + +void Hero::showHeroShadow(Graphics::Surface *screen, DrawNode *drawNode) { + PrinceEngine *vm = (PrinceEngine *)drawNode->data; + int16 heroSurfaceWidth = drawNode->s->w; + int16 heroSurfaceHeight = drawNode->s->h; + + Graphics::Surface *makeShadow = new Graphics::Surface(); + makeShadow->create(heroSurfaceWidth, heroSurfaceHeight, Graphics::PixelFormat::createFormatCLUT8()); + + for (int y = 0; y < heroSurfaceHeight; y++) { + byte *src = (byte *)drawNode->s->getBasePtr(0, y); + byte *dst = (byte *)makeShadow->getBasePtr(0, y); + for (int x = 0; x < heroSurfaceWidth; x++, dst++, src++) { + if (*src != 0xFF) { + *dst = GraphicsMan::kShadowColor; + } else { + *dst = *src; + } + } + } + + if (drawNode->posY > 1 && drawNode->posY < PrinceEngine::kMaxPicHeight) { + int shadDirection; + if (vm->_lightY > drawNode->posY) { + shadDirection = 1; + } else { + shadDirection = 0; + } + + vm->_shadLineLen = 0; + Graphics::drawLine(vm->_lightX, vm->_lightY, drawNode->posX, drawNode->posY, 0, &vm->plotShadowLinePoint, vm); + + byte *sprShadow = vm->_graph->_shadowTable70; + + int shadDrawX = drawNode->posX - vm->_picWindowX; + int shadDrawY = drawNode->posY - vm->_picWindowY; + + int shadPosX = shadDrawX; + int shadPosY = shadDrawY; + int shadBitAddr = drawNode->posY * PrinceEngine::kMaxPicWidth / 8 + drawNode->posX / 8; + int shadBitMask = 128 >> (drawNode->posX % 8); + + int shadZoomY2 = vm->_shadScaleValue; + int shadZoomY = drawNode->scaleValue; + + int diffX = 0; + int diffY = 0; + + int shadowHeroX = 0; + int shadowHeroY = heroSurfaceHeight - 1; + + int shadLastY = 0; + + byte *shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY); // first pixel from last row of shadow hero + byte *background = (byte *)screen->getBasePtr(shadDrawX, shadDrawY); // pixel of background where shadow sprite starts + + // banked2 + byte *shadowLineStart = vm->_shadowLine + 8; + + int shadWallDown = 0; + int shadWallBitAddr = 0; + int shadWallBitMask = 0; + byte *shadWallDestAddr = 0; + int shadWallPosY = 0; + int shadWallSkipX = 0; + int shadWallModulo = 0; + + // linear_loop + for (int i = 0; i < heroSurfaceHeight; i++) { + int shadSkipX = 0; + int ctLoop = 0; + int sprModulo = 0; + + int j; + //retry_line: + for (j = heroSurfaceHeight - i; j > 0; j--) { + shadZoomY -= 100; + if (shadZoomY < 0 && drawNode->scaleValue != 10000) { + shadZoomY += drawNode->scaleValue; + shadowHeroY--; + if (shadowHeroY < 0) { + break; + } + } else { + break; + } + } + if (!j) { + break; + } + if (shadowHeroY < 0) { + break; + } + + bool skipLineFlag = false; + //line_y_ok + if (shadLastY != shadPosY && shadPosY >= 0 && shadPosY < 480 && shadPosX < 640) { + shadLastY = shadPosY; + if (shadPosX < 0) { + shadSkipX = -1 * shadPosX; + if (heroSurfaceWidth > shadSkipX) { + ctLoop = heroSurfaceWidth - shadSkipX; + shadowHeroX = shadSkipX; + } else { + //skip_line + skipLineFlag = true; + } + } else { + //x1_ok + if (shadPosX + heroSurfaceWidth > 640) { + ctLoop = 640 - shadPosX; + sprModulo = shadPosX + heroSurfaceWidth - 640; + } else { + //draw_line + ctLoop = heroSurfaceWidth; + } + } + + if (!skipLineFlag) { + //draw_line1 + //retry_line2 + int k; + for (k = j; k > 0; k--) { + shadZoomY2 -= 100; + if (shadZoomY2 < 0 && vm->_shadScaleValue != 10000) { + shadZoomY2 += vm->_shadScaleValue; + shadowHeroY--; + if (shadowHeroY < 0) { + break; + } + } else { + break; + } + } + if (shadowHeroY < 0) { + break; + } + if (!k) { + break; + } + //line_y_ok_2: + //copy_trans + bool shadWDFlag = false; + int shadZoomX = drawNode->scaleValue; + int backgroundDiff = shadSkipX; + int shadBitMaskCopyTrans = shadBitMask; + int shadBitAddrCopyTrans = shadBitAddr; + shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY); + background = (byte *)screen->getBasePtr(shadDrawX + diffX + backgroundDiff, shadDrawY + diffY); + + if (shadPosX < 0) { + if (heroSurfaceWidth > shadSkipX) { + shadBitAddrCopyTrans += shadSkipX / 8; + if ((shadSkipX % 8)) { + //loop_rotate: + for (int a = 0; a < (shadSkipX % 8); a++) { + if (shadBitMaskCopyTrans == 1) { + shadBitMaskCopyTrans = 128; + shadBitAddrCopyTrans++; + } else { + shadBitMaskCopyTrans >>= 1; + } + } + } + } + } + + //ct_loop: + for (int l = 0; l < ctLoop; l++) { + shadZoomX -= 100; + if (shadZoomX < 0 && drawNode->scaleValue != 10000) { + shadZoomX += drawNode->scaleValue; + } else { + if (*shadowHero == GraphicsMan::kShadowColor) { + if ((shadBitMaskCopyTrans & vm->_shadowBitmap[shadBitAddrCopyTrans])) { + if (shadWallDown == 0) { + if ((shadBitMaskCopyTrans & vm->_shadowBitmap[shadBitAddrCopyTrans + PrinceEngine::kShadowBitmapSize])) { + shadWDFlag = true; + //shadow + *background = *(sprShadow + *background); + } + } + } else { + //shadow + *background = *(sprShadow + *background); + } + } + //ct_next + if (shadBitMaskCopyTrans == 1) { + shadBitMaskCopyTrans = 128; + shadBitAddrCopyTrans++; + } else { + shadBitMaskCopyTrans >>= 1; + } + //okok + backgroundDiff++; + background = (byte *)screen->getBasePtr(shadDrawX + diffX + backgroundDiff, shadDrawY + diffY); + } + shadowHeroX++; + shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY); + } + //byebyebye + if (!shadWallDown && shadWDFlag) { + shadWallDown = shadPosX; + shadWallBitAddr = shadBitAddr; + shadWallDestAddr = (byte *)screen->getBasePtr(shadDrawX + diffX, shadDrawY + diffY); + shadWallBitMask = shadBitMask; + shadWallPosY = shadPosY; + shadWallSkipX = shadSkipX; + shadWallModulo = sprModulo; + } + //byebye + if (shadDirection && shadWallDown) { + int shadBitMaskWallCopyTrans = shadWallBitMask; + int shadBitAddrWallCopyTrans = shadWallBitAddr; + background = shadWallDestAddr; + shadowHero = (byte *)makeShadow->getBasePtr(shadWallSkipX, shadowHeroY); + + if (ctLoop > shadWallSkipX && ctLoop - shadWallSkipX > shadWallModulo) { + //WALL_copy_trans + shadWDFlag = false; + int shadZoomXWall = drawNode->scaleValue; + int backgroundDiffWall = 0; + int shadowHeroXWall = 0; + //ct_loop: + for (int m = 0; m < ctLoop; m++) { + shadZoomXWall -= 100; + if (shadZoomXWall < 0 && drawNode->scaleValue != 10000) { + shadZoomXWall += drawNode->scaleValue; + } else { + //point_ok: + if (*shadowHero == GraphicsMan::kShadowColor) { + if ((shadBitMaskWallCopyTrans & vm->_shadowBitmap[shadBitAddrWallCopyTrans + PrinceEngine::kShadowBitmapSize])) { + *background = *(sprShadow + *background); + } + } + //ct_next + if (shadBitMaskWallCopyTrans == 1) { + shadBitMaskWallCopyTrans = 128; + shadBitAddrWallCopyTrans++; + } else { + shadBitMaskWallCopyTrans >>= 1; + } + //okok + backgroundDiffWall++; + background = shadWallDestAddr + backgroundDiffWall; + } + shadowHeroXWall++; + shadowHero = (byte *)makeShadow->getBasePtr(shadWallSkipX + shadowHeroXWall, shadowHeroY); + } + } + //krap2 + shadWallDestAddr -= PrinceEngine::kNormalWidth; + shadWallBitAddr -= PrinceEngine::kMaxPicWidth / 8; + shadWallPosY--; + } + } + } + //skip_line + //next_line + if (READ_LE_UINT16(shadowLineStart + 2) < READ_LE_UINT16(shadowLineStart - 2)) { + //minus_y + shadBitAddr -= PrinceEngine::kMaxPicWidth / 8; + shadPosY--; + diffY--; + } else if (READ_LE_UINT16(shadowLineStart + 2) > READ_LE_UINT16(shadowLineStart - 2)) { + shadBitAddr += PrinceEngine::kMaxPicWidth / 8; + shadPosY++; + diffY++; + } + //no_change_y + if (READ_LE_UINT16(shadowLineStart) < READ_LE_UINT16(shadowLineStart - 4)) { + //minus_x + shadPosX--; + //rol + if (shadBitMask == 128) { + shadBitMask = 1; + shadBitAddr--; + } else { + shadBitMask <<= 1; + } + diffX--; + } else if (READ_LE_UINT16(shadowLineStart) > READ_LE_UINT16(shadowLineStart - 4)) { + shadPosX++; + //ror + if (shadBitMask == 1) { + shadBitMask = 128; + shadBitAddr++; + } else { + shadBitMask >>= 1; + } + diffX++; + } + //no_change_x + shadowLineStart += 4; + shadowHeroY--; + if (shadowHeroY < 0) { + break; + } + shadowHeroX = 0; + background = (byte *)screen->getBasePtr(shadDrawX + diffX, shadDrawY + diffY); + shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY); + } + //koniec_bajki - end_of_a_story + } + makeShadow->free(); + delete makeShadow; +} + +void Hero::setScale(int8 zoomBitmapValue) { + if (!zoomBitmapValue) { + _vm->_scaleValue = 10000; + } else { + _vm->_scaleValue = 10000 / zoomBitmapValue; + } +} + +void Hero::selectZoom() { + int8 zoomBitmapValue = *(_vm->_zoomBitmap + _middleY / 4 * _vm->kZoomBitmapWidth + _middleX / 4); + setScale(zoomBitmapValue); +} + +int Hero::rotateHero(int oldDirection, int newDirection) { + switch (oldDirection) { + case kHeroDirLeft: + switch (newDirection) { + case kHeroDirRight: + return kMove_MLR; + case kHeroDirUp: + return kMove_MLU; + case kHeroDirDown: + return kMove_MLD; + } + break; + case kHeroDirRight: + switch (newDirection) { + case kHeroDirLeft: + return kMove_MRL; + case kHeroDirUp: + return kMove_MRU; + case kHeroDirDown: + return kMove_MRD; + } + break; + case kHeroDirUp: + switch (newDirection) { + case kHeroDirLeft: + return kMove_MUL; + case kHeroDirRight: + return kMove_MUR; + case kHeroDirDown: + return kMove_MUD; + } + break; + case kHeroDirDown: + switch (newDirection) { + case kHeroDirLeft: + return kMove_MDL; + case kHeroDirRight: + return kMove_MDR; + case kHeroDirUp: + return kMove_MDU; + } + break; + } + error("rotateHero - wrong directions - old %d, new %d", oldDirection, newDirection); +} + +void Hero::heroStanding() { + _phase = 0; + switch (_lastDirection) { + case kHeroDirLeft: + _moveSetType = kMove_SL; + break; + case kHeroDirRight: + _moveSetType = kMove_SR; + break; + case kHeroDirUp: + _moveSetType = kMove_SU; + break; + case kHeroDirDown: + _moveSetType = kMove_SD; + break; + } +} + +void Hero::showHero() { + if (_visible && !_vm->_flags->getFlagValue(Flags::NOHEROATALL)) { + + if (_talkTime != 0) { + _talkTime--; + } + + // Scale of hero + selectZoom(); + + if (_state != kHeroStateStay) { + _boredomTime = 0; + } + + if (_state == kHeroStateSpec) { + if (_specAnim != nullptr) { + if (_phase < _specAnim->getPhaseCount() - 1) { + _phase++; + } else { + if (!_talkTime) { + _state = kHeroStateStay; + } else { + _state = kHeroStateTalk; + } + countDrawPosition(); + return; + } + } else { + _state = kHeroStateStay; + } + } else { + freeHeroAnim(); + } + + if (_state == kHeroStateTalk) { + if (_talkTime) { + switch (_lastDirection) { + case kHeroDirLeft: + _moveSetType = kMove_TL; + break; + case kHeroDirRight: + _moveSetType = kMove_TR; + break; + case kHeroDirUp: + _moveSetType = kMove_TU; + break; + case kHeroDirDown: + _moveSetType = kMove_TD; + break; + } + if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 1) { + _phase++; + } else { + _phase = _moveSet[_moveSetType]->getLoopCount(); + } + } else { + _state = kHeroStateStay; + } + } + + if (_state == kHeroStateBore) { + switch (_boreNum) { + case 0: + _moveSetType = kMove_BORED1; + break; + case 1: + _moveSetType = kMove_BORED2; + break; + } + if (_moveSet[_moveSetType] != nullptr) { + if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 1) { + _phase++; + } else { + _phase = 0; + _lastDirection = kHeroDirDown; + _state = kHeroStateStay; + } + } else { + _state = kHeroStateStay; + } + } + + if (_state == kHeroStateStay) { + if (!_vm->_optionsFlag) { + if (!_vm->_interpreter->getLastOPCode() || !_vm->_interpreter->getFgOpcodePC()) { + _boredomTime++; + if (_boredomTime == _maxBoredom) { + _boreNum =_vm->_randomSource.getRandomNumber(1); // rand one of two 'bored' animation + _phase = 0; + _state = kHeroStateBore; + if (_lastDirection == kHeroDirUp) { + _lastDirection = kHeroDirLeft; + } else { + _lastDirection = kHeroDirDown; + } + } + } else { + _boredomTime = 0; + } + } else { + _boredomTime = 0; + } + heroStanding(); + } + + if (_state == kHeroStateTurn) { + if (_destDirection && (_lastDirection != _destDirection)) { + _phase = 0; + int rotateDir = rotateHero(_lastDirection, _destDirection); + _lastDirection = _destDirection; + if (rotateDir) { + _moveSetType = rotateDir; + _state = kHeroStateTran; + } else { + _state = kHeroStateStay; + heroStanding(); + } + } else { + _state = kHeroStateStay; + heroStanding(); + } + } + + if (_state == kHeroStateTran) { + if (_moveSet[_moveSetType] != nullptr) { + // only in bear form + if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 2) { + _phase += 2; + } else { + _state = kHeroStateStay; + heroStanding(); + } + } else { + _state = kHeroStateStay; + heroStanding(); + } + } + + if (_state == kHeroStateMvan) { + if (_moveSet[_moveSetType] != nullptr) { + // only in bear form + if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 2) { + _phase += 2; + } else { + _state = kHeroStateMove; + } + } else { + _state = kHeroStateMove; + } + } + + if (_state == kHeroStateDelayMove) { + _moveDelay--; + if (!_moveDelay) { + _state = kHeroStateMove; + } + } + + int x, y, dir; + + if (_state == kHeroStateMove || _state == kHeroStateRun) { + //go_for_it: + while (1) { + if (_currCoords != nullptr) { + if (READ_LE_UINT32(_currCoords) != 0xFFFFFFFF) { + x = READ_LE_UINT16(_currCoords); + y = READ_LE_UINT16(_currCoords + 2); + _currCoords += 4; + dir = *_currDirTab; + _currDirTab++; + if (_lastDirection != dir) { + _phase = 0; + int rotateDir = rotateHero(_lastDirection, dir); + _lastDirection = dir; + if (_moveSet[rotateDir] != nullptr) { + // only in bear form + _state = kHeroStateMvan; + _moveSetType = rotateDir; + if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 2) { + _phase += 2; + break; + } else { + _state = kHeroStateMove; + continue; + } + } else { + continue; + } + } + //no_need_direction_change + if (dir == kHeroDirLeft) { + if (_middleX - x >= _step) { + heroMoveGotIt(x, y, dir); + break; + } + } else if (dir == kHeroDirRight) { + if (x - _middleX >= _step) { + heroMoveGotIt(x, y, dir); + break; + } + } else if (dir == kHeroDirUp) { + if (_middleY - y >= _step) { + heroMoveGotIt(x, y, dir); + break; + } + } else if (dir == kHeroDirDown) { + if (y - _middleY >= _step) { + heroMoveGotIt(x, y, dir); + break; + } + } + } else { + //finito + _middleX = READ_LE_UINT16(_currCoords - 4); + _middleY = READ_LE_UINT16(_currCoords - 2); + selectZoom(); + + if (_coords != nullptr) { + free(_coords); + _coords = nullptr; + _currCoords = nullptr; + } + + if (_dirTab != nullptr) { + free(_dirTab); + _dirTab = nullptr; + _currDirTab = nullptr; + } + + _boredomTime = 0; + _phase = 0; + _state = kHeroStateTurn; + + if (!_destDirection) { + _destDirection = _lastDirection; + } + + heroStanding(); + + break; + } + } else { + heroStanding(); + break; + } + } + } + countDrawPosition(); + } +} + +void Hero::drawHero() { + if (_visible && !_vm->_flags->getFlagValue(Flags::NOHEROATALL)) { + freeZoomedSurface(); + Graphics::Surface *mainHeroSurface = getSurface(); + if (mainHeroSurface) { + DrawNode newDrawNode; + newDrawNode.posX = _drawX; + newDrawNode.posY = _drawY; + newDrawNode.posZ = _drawZ; + newDrawNode.width = 0; + newDrawNode.height = 0; + newDrawNode.originalRoomSurface = nullptr; + newDrawNode.data = _vm->_transTable; + newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode; + + if (_vm->_scaleValue != 10000) { + _zoomedHeroSurface = zoomSprite(mainHeroSurface); + newDrawNode.s = _zoomedHeroSurface; + } else { + newDrawNode.s = mainHeroSurface; + } + _vm->_drawNodeList.push_back(newDrawNode); + + drawHeroShadow(mainHeroSurface); + + } + } +} + +void Hero::drawHeroShadow(Graphics::Surface *heroFrame) { + DrawNode newDrawNode; + newDrawNode.posX = _middleX - _scaledFrameXSize / 2; + newDrawNode.posY = _middleY - _shadMinus - 1; + newDrawNode.posZ = kHeroShadowZ; + newDrawNode.width = 0; + newDrawNode.height = 0; + newDrawNode.scaleValue = _vm->_scaleValue; + newDrawNode.originalRoomSurface = nullptr; + newDrawNode.data = _vm; + newDrawNode.drawFunction = &showHeroShadow; + newDrawNode.s = heroFrame; + _vm->_drawNodeList.push_back(newDrawNode); +} + +void Hero::heroMoveGotIt(int x, int y, int dir) { + _middleX = x; + _middleY = y; + selectZoom(); + + switch (dir) { + case kHeroDirLeft: + _moveSetType = kMove_ML; + break; + case kHeroDirRight: + _moveSetType = kMove_MR; + break; + case kHeroDirUp: + _moveSetType = kMove_MU; + break; + case kHeroDirDown: + _moveSetType = kMove_MD; + break; + } + + if (_vm->_flags->getFlagValue(Flags::HEROFAST) || _state == kHeroStateRun) { + if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 2) { + _phase += 2; + } else { + _phase = 0; + } + } else { + if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 1) { + _phase++; + } else { + _phase = 0; + } + } + + _step = kStepLeftRight; + if (_moveSetType == kMove_MU || _moveSetType == kMove_MD) { + _step = kStepUpDown; + } + if (_vm->_flags->getFlagValue(Flags::HEROFAST)) { + _step *= 2.5; + } else if (_state == kHeroStateRun) { + _step *= 2; + } +} + +void Hero::scrollHero() { + int scrollType = _vm->_flags->getFlagValue(Flags::SCROLLTYPE); + int position = _middleX; + int scrollValue, scrollValue2; + + switch (scrollType) { + case 0: + position = _middleX; + break; + case 1: + scrollValue = _vm->_flags->getFlagValue(Flags::SCROLLVALUE); + position = _vm->_normAnimList[scrollValue]._currX + _vm->_normAnimList[scrollValue]._currW / 2; + break; + case 2: + scrollValue = _vm->_flags->getFlagValue(Flags::SCROLLVALUE); + scrollValue2 = _vm->_flags->getFlagValue(Flags::SCROLLVALUE2); + position = scrollValue; + if (scrollValue < scrollValue2) { + _vm->_flags->setFlagValue(Flags::SCROLLVALUE, 0); + } else { + _vm->_flags->setFlagValue(Flags::SCROLLVALUE, scrollValue - scrollValue2); + } + break; + } + + int locationWidth = _vm->_sceneWidth; + int difference = locationWidth - _vm->kNormalWidth / 2; + + int destValue = 0; + if (position > _vm->kNormalWidth / 2) { + destValue = difference - _vm->kNormalWidth / 2; + } + if (position < difference) { + destValue = position - _vm->kNormalWidth / 2; + } + + if(destValue < 0) { + destValue = 0; + } + _vm->_picWindowX = destValue; + _drawX -= destValue; +} + +void Hero::freeOldMove() { + if (_coords != nullptr) { + free(_coords); + _coords = nullptr; + } + if (_dirTab != nullptr) { + free(_dirTab); + _dirTab = nullptr; + } + _step = 0; + _phase = 0; + _moveDelay = 0; + _state = Hero::kHeroStateStay; +} + +void Hero::freeHeroAnim() { + if (_specAnim != nullptr) { + delete _specAnim; + _specAnim = nullptr; + } +} + +void Hero::freeZoomedSurface() { + if (_zoomedHeroSurface != nullptr) { + _zoomedHeroSurface->free(); + delete _zoomedHeroSurface; + _zoomedHeroSurface = nullptr; + } +} + +} // End of namespace Prince |