/* 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 >= ARRAYSIZE(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(5, "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) { int16 initScaleValue = _vm->_scaleValue; if (_vm->_scaleValue != 10000) { int newSize = 0; 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 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; } //line_y_ok if (shadLastY != shadPosY && shadPosY >= 0 && shadPosY < 480 && shadPosX < 640) { shadLastY = shadPosY; bool skipLineFlag = false; int shadSkipX = 0; int ctLoop = 0; int sprModulo = 0; 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; default: break; } break; case kHeroDirRight: switch (newDirection) { case kHeroDirLeft: return kMove_MRL; case kHeroDirUp: return kMove_MRU; case kHeroDirDown: return kMove_MRD; default: break; } break; case kHeroDirUp: switch (newDirection) { case kHeroDirLeft: return kMove_MUL; case kHeroDirRight: return kMove_MUR; case kHeroDirDown: return kMove_MUD; default: break; } break; case kHeroDirDown: switch (newDirection) { case kHeroDirLeft: return kMove_MDL; case kHeroDirRight: return kMove_MDR; case kHeroDirUp: return kMove_MDU; default: break; } break; default: 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; default: 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; default: 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; default: 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; } } if (_state == kHeroStateMove || _state == kHeroStateRun) { //go_for_it: while (1) { if (_currCoords != nullptr) { if (READ_LE_UINT32(_currCoords) != 0xFFFFFFFF) { int x = READ_LE_UINT16(_currCoords); int y = READ_LE_UINT16(_currCoords + 2); _currCoords += 4; int 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; default: 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; default: 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