aboutsummaryrefslogtreecommitdiff
path: root/engines/access/player.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/access/player.cpp')
-rw-r--r--engines/access/player.cpp872
1 files changed, 872 insertions, 0 deletions
diff --git a/engines/access/player.cpp b/engines/access/player.cpp
new file mode 100644
index 0000000000..0162491aee
--- /dev/null
+++ b/engines/access/player.cpp
@@ -0,0 +1,872 @@
+/* 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/algorithm.h"
+#include "common/textconsole.h"
+#include "access/player.h"
+#include "access/access.h"
+#include "access/resources.h"
+#include "access/amazon/amazon_player.h"
+#include "access/martian/martian_player.h"
+
+namespace Access {
+
+Player *Player::init(AccessEngine *vm) {
+ switch (vm->getGameID()) {
+ case GType_Amazon:
+ vm->_playerDataCount = 8;
+ return new Amazon::AmazonPlayer(vm);
+ case GType_MartianMemorandum:
+ vm->_playerDataCount = 10;
+ return new Martian::MartianPlayer(vm);
+ default:
+ vm->_playerDataCount = 8;
+ return new Player(vm);
+ }
+}
+
+Player::Player(AccessEngine *vm) : Manager(vm), ImageEntry() {
+ _playerSprites = nullptr;
+ _playerSprites1 = nullptr;
+ _manPal1 = nullptr;
+ _frameNumber = 0;
+ _rawTempL = 0;
+ _rawXTemp = 0;
+ _rawYTempL = 0;
+ _rawYTemp = 0;
+ _playerXLow = 0;
+ _playerX = 0;
+ _playerYLow = 0;
+ _playerY = 0;
+ _frame = 0;
+ _playerOff = false;
+ _playerMove = false;
+ _leftDelta = _rightDelta = 0;
+ _upDelta = _downDelta = 0;
+ _scrollConst = 0;
+ _scrollFlag = false;
+ _scrollThreshold = 0;
+ _scrollAmount = 0;
+ _scrollEnd = 0;
+ _roomNumber = 0;
+ _collideFlag = false;
+ _move = NONE;
+ _playerDirection = NONE;
+ _xFlag = _yFlag = 0;
+ _inactiveYOff = 0;
+
+ _sideWalkMin = _sideWalkMax = 0;
+ _upWalkMin = _upWalkMax = 0;
+ _downWalkMin = _downWalkMax = 0;
+ _diagUpWalkMin = _diagUpWalkMax = 0;
+ _diagDownWalkMin = _diagDownWalkMax = 0;
+ _walkOffRight = _walkOffLeft = nullptr;
+ _walkOffUp = _walkOffDown = nullptr;
+ _walkOffUR = _walkOffDR = nullptr;
+ _walkOffUL = _walkOffDL = nullptr;
+}
+
+Player::~Player() {
+ delete _playerSprites;
+ delete[] _manPal1;
+ delete[] _walkOffRight;
+ delete[] _walkOffLeft;
+ delete[] _walkOffUp;
+ delete[] _walkOffDown;
+ delete[] _walkOffUR;
+ delete[] _walkOffDR;
+ delete[] _walkOffUL;
+ delete[] _walkOffDL;
+}
+
+void Player::load() {
+ int dataCount = _vm->_playerDataCount;
+ _walkOffRight = new int[dataCount];
+ _walkOffLeft = new int[dataCount];
+ _walkOffUp = new int[dataCount];
+ _walkOffDown = new int[dataCount];
+ _walkOffUR = new Common::Point[dataCount];
+ _walkOffDR = new Common::Point[dataCount];
+ _walkOffUL = new Common::Point[dataCount];
+ _walkOffDL = new Common::Point[dataCount];
+
+ _playerOffset.x = _vm->_screen->_scaleTable1[25];
+ _playerOffset.y = _vm->_screen->_scaleTable1[67];
+ _leftDelta = -3;
+ _rightDelta = 33;
+ _upDelta = 5;
+ _downDelta = -10;
+ _scrollConst = 5;
+
+ _sideWalkMin = 0;
+ _sideWalkMax = 7;
+ _upWalkMin = 16;
+ _upWalkMax = 23;
+ _downWalkMin = 8;
+ _downWalkMax = 15;
+ _diagUpWalkMin = 0;
+ _diagUpWalkMax = 7;
+ _diagDownWalkMin = 0;
+ _diagDownWalkMax = 7;
+
+ _playerSprites = _playerSprites1;
+ if (_manPal1) {
+ // Those values are from MM as Amazon doesn't use it
+ Common::copy(_manPal1 + 0x2A0, _manPal1 + 0x2A0 + 0x42, _vm->_screen->_manPal);
+ } else {
+ Common::fill(_vm->_screen->_manPal, _vm->_screen->_manPal + 0x60, 0);
+ }
+}
+
+void Player::loadTexPalette() {
+ Resource *texPal = _vm->_files->loadFile("TEXPAL.COL");
+ int size = texPal->_size;
+ assert(size == 768);
+ _manPal1 = new byte[size];
+ memcpy(_manPal1, texPal->data(), size);
+}
+
+void Player::loadSprites(const Common::String &name) {
+ freeSprites();
+
+ Resource *data = _vm->_files->loadFile(name);
+
+#if 0
+ Common::DumpFile *outFile = new Common::DumpFile();
+ Common::String outName = name + ".dump";
+ outFile->open(outName);
+ outFile->write(data->data(), data->_size);
+ outFile->finalize();
+ outFile->close();
+#endif
+
+ _playerSprites1 = new SpriteResource(_vm, data);
+ delete data;
+}
+
+void Player::freeSprites() {
+ delete _playerSprites;
+ _playerSprites1 = nullptr;
+ _playerSprites = nullptr;
+}
+
+void Player::removeSprite1() {
+ if (_playerSprites1) {
+ delete _playerSprites1;
+ _playerSprites1 = nullptr;
+ }
+}
+
+void Player::calcManScale() {
+ if (!_vm->_manScaleOff) {
+ _vm->_scale = ((((_rawPlayer.y - _vm->_scaleMaxY + _vm->_scaleN1) *
+ _vm->_scaleT1 + (_vm->_scaleH2 << 8)) & 0xff00) / _vm->_scaleH1 * _vm->_scaleI) >> 8;
+ _vm->_screen->setScaleTable(_vm->_scale);
+
+ _playerOffset.x = _vm->_screen->_scaleTable1[20];
+ _playerOffset.y = _vm->_screen->_scaleTable1[67];
+ _inactiveYOff = _playerOffset.y;
+ }
+}
+
+void Player::walk() {
+ _collideFlag = false;
+ _playerDirection = NONE;
+
+ if (_playerOff)
+ return;
+ else if (_vm->_timers[0]._flag) {
+ plotCom3();
+ return;
+ }
+
+ ++_vm->_timers[0]._flag;
+ switch (_move) {
+ case UP:
+ _playerMove = false;
+ walkUp();
+ break;
+ case DOWN:
+ _playerMove = false;
+ walkDown();
+ break;
+ case LEFT:
+ _playerMove = false;
+ walkLeft();
+ break;
+ case RIGHT:
+ _playerMove = false;
+ walkRight();
+ break;
+ case UPLEFT:
+ _playerMove = false;
+ walkUpLeft();
+ break;
+ case DOWNLEFT:
+ _playerMove = false;
+ walkDownLeft();
+ break;
+ case UPRIGHT:
+ _playerMove = false;
+ walkUpRight();
+ break;
+ case DOWNRIGHT:
+ _playerMove = false;
+ walkDownRight();
+ break;
+ default:
+ checkMove();
+ break;
+ }
+}
+
+void Player::calcPlayer() {
+ Screen &scr = *_vm->_screen;
+ scr._bufferStart.x = (_vm->_scrollCol << 4) + _vm->_scrollX;
+ scr._bufferStart.y = (_vm->_scrollRow << 4) + _vm->_scrollY;
+ _playerX = _rawPlayer.x - scr._bufferStart.x;
+ _playerY = _rawPlayer.y - scr._bufferStart.y;
+}
+
+void Player::walkUp() {
+ if (_frame > _upWalkMax || _frame < _upWalkMin)
+ _frame = _upWalkMin;
+
+ _playerDirection = UP;
+ int walkOff = _walkOffUp[_frame - _upWalkMin];
+ int tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOff];
+ _rawYTempL = (byte)tempL;
+ int yTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOff] -
+ (tempL < 0 ? 1 : 0);
+ _rawYTemp = yTemp;
+ _rawXTemp = _rawPlayer.x;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.y = _rawYTempL;
+
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom
+ //if (_vm->_currentMan != 3 && (_frame == 17 || _frame == 21))
+ // warning("TODO: walkUp - si = 0?");
+
+ if (++_frame > _upWalkMax)
+ _frame = _upWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::walkDown() {
+ if (_frame > _downWalkMax || _frame < _downWalkMin)
+ _frame = _downWalkMin;
+
+ _playerDirection = DOWN;
+ int walkOff = _walkOffDown[_frame - _downWalkMin];
+ int tempL = _vm->_screen->_scaleTable2[walkOff] + _rawPlayerLow.y;
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _vm->_screen->_scaleTable1[walkOff] + _rawPlayer.y + (tempL >= 0x100 ? 1 : 0);
+ _rawXTemp = _rawPlayer.x;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.y = _rawYTempL;
+
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom
+ //if (_vm->_currentMan != 3 && (_frame == 10 || _frame == 14))
+ // warning("TODO: walkDown - si = 0?");
+
+ if (++_frame > _downWalkMax)
+ _frame = _downWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::walkLeft() {
+ if (_frame > _sideWalkMax || _frame < _sideWalkMin)
+ _frame = _sideWalkMin;
+
+ _playerDirection = LEFT;
+
+ bool flag = _scrollEnd == 1;
+ if (!flag) {
+ calcPlayer();
+ flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ int walkOffset = _walkOffLeft[_frame - _sideWalkMin];
+ int tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst];
+ }
+ _rawYTemp = _rawPlayer.y;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayerLow.x = _rawTempL;
+ ++_frame;
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom1
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkLeft - si = 0?");
+
+ if (_frame > _sideWalkMax)
+ _frame = _sideWalkMin;
+
+ plotCom1();
+ }
+}
+
+void Player::walkRight() {
+ if (_frame > _sideWalkMax || _frame < _sideWalkMin)
+ _frame = _sideWalkMin;
+
+ _playerDirection = RIGHT;
+
+ bool flag = _scrollEnd == 2;
+ if (!flag) {
+ calcPlayer();
+ flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ int walkOffset = _walkOffRight[_frame - _sideWalkMin];
+ int tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst];
+ }
+ _rawYTemp = _rawPlayer.y;
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayerLow.x = _rawTempL;
+ ++_frame;
+
+ // Useless check removed
+ if (_frame > _sideWalkMax)
+ _frame = _sideWalkMin;
+
+ plotCom0();
+ }
+}
+
+void Player::walkUpLeft() {
+ if (_frame > _diagUpWalkMax || _frame < _diagUpWalkMin)
+ _frame = _diagUpWalkMin;
+
+ _playerDirection = UPLEFT;
+
+ int walkOffset, tempL;
+ bool flag = _scrollEnd == 1;
+ if (!flag) {
+ calcPlayer();
+ flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ walkOffset = _walkOffUL[_frame - _diagUpWalkMin].x;
+ tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst];
+ }
+
+ walkOffset = _walkOffUL[_frame - _diagUpWalkMin].y;
+ tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOffset];
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.x = _rawTempL;
+ _rawPlayerLow.y = _rawYTempL;
+
+ ++_frame;
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom1
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkUpLeft - si = 0?");
+
+ if (_frame > _diagUpWalkMax)
+ _frame = _diagUpWalkMin;
+
+ plotCom1();
+ }
+}
+
+void Player::walkDownLeft() {
+ if (_frame > _diagDownWalkMax || _frame < _diagDownWalkMin)
+ _frame = _diagDownWalkMin;
+
+ _playerDirection = DOWNLEFT;
+
+ int walkOffset, tempL;
+ bool flag = _scrollEnd == 1;
+ if (!flag) {
+ calcPlayer();
+ flag = (_playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ walkOffset = _walkOffDL[_frame - _sideWalkMin].x;
+ tempL = _rawPlayerLow.x - _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x - _vm->_screen->_scaleTable1[_scrollConst];
+ }
+
+ walkOffset = _walkOffDL[_frame - _diagDownWalkMin].y;
+ tempL = _rawPlayerLow.y + _vm->_screen->_scaleTable2[walkOffset];
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _rawPlayer.y + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.x = _rawTempL;
+ _rawPlayerLow.y = _rawYTempL;
+
+ ++_frame;
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom1
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkDownLeft - si = 0?");
+
+ if (_frame > _diagDownWalkMax)
+ _frame = _diagDownWalkMin;
+
+ plotCom1();
+ }
+}
+
+void Player::walkUpRight() {
+ if (_frame > _diagUpWalkMax || _frame < _diagUpWalkMin)
+ _frame = _diagUpWalkMin;
+
+ _playerDirection = UPRIGHT;
+
+ int walkOffset, tempL;
+ bool flag = _scrollEnd == 1;
+ if (!flag) {
+ calcPlayer();
+ flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ walkOffset = _walkOffUR[_frame - _diagUpWalkMin].x;
+ tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst];
+ }
+
+ walkOffset = _walkOffUL[_frame - _diagUpWalkMin].y;
+ tempL = _rawPlayerLow.y - _vm->_screen->_scaleTable2[walkOffset];
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _rawPlayer.y - _vm->_screen->_scaleTable1[walkOffset] -
+ (tempL < 0 ? 1 : 0);
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.x = _rawTempL;
+ _rawPlayerLow.y = _rawYTempL;
+
+ ++_frame;
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkUpRight - si = 0?");
+
+ if (_frame > _diagUpWalkMax)
+ _frame = _diagUpWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::walkDownRight() {
+ if (_frame > _diagDownWalkMax || _frame < _diagDownWalkMin)
+ _frame = _diagDownWalkMin;
+
+ _playerDirection = DOWNRIGHT;
+
+ int walkOffset, tempL;
+ bool flag = _scrollEnd == 2;
+ if (!flag) {
+ calcPlayer();
+ flag = (_vm->_screen->_clipWidth - _playerX - _vm->_screen->_scaleTable1[_scrollConst] -
+ _vm->_player->_scrollThreshold) > 0;
+ }
+ if (flag) {
+ walkOffset = _walkOffUR[_frame - _diagDownWalkMin].x;
+ tempL = _rawPlayerLow.x + _vm->_screen->_scaleTable2[walkOffset];
+ _rawTempL = (byte)tempL;
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+ } else {
+ _rawXTemp = _rawPlayer.x + _vm->_screen->_scaleTable1[_scrollConst];
+ }
+
+ walkOffset = _walkOffDR[_frame - _diagDownWalkMin].y;
+ tempL = _rawPlayerLow.y + _vm->_screen->_scaleTable2[walkOffset];
+ _rawYTempL = (byte)tempL;
+ _rawYTemp = _rawPlayer.y + _vm->_screen->_scaleTable1[walkOffset] +
+ (tempL >= 0x100 ? 1 : 0);
+
+ if (_vm->_room->codeWalls()) {
+ plotCom2();
+ } else {
+ _rawPlayer.x = _rawXTemp;
+ _rawPlayer.y = _rawYTemp;
+ _rawPlayerLow.x = _rawTempL;
+ _rawPlayerLow.y = _rawYTempL;
+
+ calcManScale();
+
+ // This code looks totally useless as 'si' is unconditionally set in plotCom1
+ //if (_vm->_currentMan != 3 && (_frame == 1 || _frame == 5))
+ // warning("TODO: walkDownRight - si = 0?");
+
+ ++_frame;
+ if (_frame > _diagDownWalkMax)
+ _frame = _diagDownWalkMin;
+
+ plotCom(0);
+ }
+}
+
+void Player::checkMove() {
+ if (_playerMove) {
+ if (_xFlag == 0 && _yFlag == 0) {
+ int xp = (_playerOffset.x / 2) + _rawPlayer.x - _moveTo.x;
+ if (xp < 0)
+ xp = -xp;
+ int yp = _rawPlayer.y - _moveTo.y;
+ if (yp < 0)
+ yp = -yp;
+
+ if (xp >= yp)
+ _xFlag = 1;
+ else
+ _yFlag = 1;
+ }
+
+ if (_yFlag == 1) {
+ int yd = _rawPlayer.y - _moveTo.y;
+ if ((yd >= 0 && yd <= _upDelta) || (yd < 0 && -yd <= _upDelta)) {
+ ++_yFlag;
+ if (_xFlag) {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ } else {
+ ++_xFlag;
+ }
+ } else {
+ if (yd >= 0)
+ walkUp();
+ else
+ walkDown();
+
+ if (_collideFlag) {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ }
+ }
+ } else if (_xFlag == 1) {
+ int xd = (_playerOffset.x / 2) + _rawPlayer.x - _moveTo.x;
+ if ((xd >= 0 && xd <= -_leftDelta) || (xd < 0 && -xd <= -_leftDelta)) {
+ ++_xFlag;
+
+ if (_yFlag) {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ }
+ } else {
+ if (xd >= 0)
+ walkLeft();
+ else
+ walkRight();
+
+ if (_collideFlag) {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ }
+ }
+ } else if (!_yFlag) {
+ ++_yFlag;
+ } else {
+ _playerMove = false;
+ _xFlag = _yFlag = 0;
+ }
+ }
+
+ plotCom3();
+}
+
+void Player::plotCom(int flags) {
+ _flags &= ~IMGFLAG_BACKWARDS;
+ _flags &= ~IMGFLAG_UNSCALED;
+ _flags |= flags;
+
+ plotCom3();
+}
+
+void Player::plotCom0() {
+ plotCom(_vm->getGameID() == GType_Amazon ? 0 : IMGFLAG_BACKWARDS);
+}
+
+void Player::plotCom1() {
+ plotCom(_vm->getGameID() == GType_Amazon ? IMGFLAG_BACKWARDS : 0);
+}
+
+void Player::plotCom2() {
+ // WORKAROUND: Amazon has at least one cutscene with the player not properly turned off
+ if (!_playerOff && _spritesPtr != nullptr)
+ _vm->_images.addToList(*this);
+}
+
+void Player::plotCom3() {
+ // Update the base ImageEntry fields for the player
+ _position.x = _rawPlayer.x;
+ _position.y = _rawPlayer.y - _playerOffset.y;
+ _offsetY = _playerOffset.y;
+ _spritesPtr = _playerSprites;
+ _frameNumber = _frame;
+
+ plotCom2();
+}
+
+void Player::checkScrollUp() {
+ if ((_playerDirection == DOWNRIGHT || _playerDirection == DOWNLEFT ||
+ _playerDirection == DOWN) && (_vm->_screen->_clipHeight -
+ _playerY - _scrollThreshold) <= 0) {
+ // Scroll up
+ if (scrollUp()) {
+ _scrollEnd = 4;
+ _vm->_scrollY &= TILE_HEIGHT;
+ _scrollFlag = true;
+ }
+ }
+}
+
+void Player::checkScroll() {
+ _scrollFlag = false;
+ if (_playerDirection == NONE)
+ return;
+
+ if ((_playerDirection == UPLEFT || _playerDirection == DOWNLEFT ||
+ _playerDirection == LEFT) && _playerX <= _scrollThreshold) {
+ // Scroll right
+ if (!scrollRight()) {
+ if (_playerDirection == DOWNLEFT)
+ checkScrollUp();
+
+ return;
+ }
+ } else if ((_playerDirection == UPRIGHT || _playerDirection == DOWNRIGHT ||
+ _playerDirection == RIGHT) && (_vm->_screen->_clipWidth -
+ _playerX - _scrollThreshold) <= 0) {
+ // Scroll left
+ if (!scrollLeft()) {
+ if (_playerDirection == DOWNRIGHT)
+ checkScrollUp();
+
+ return;
+ }
+ }
+
+ if ((_playerDirection == UPRIGHT || _playerDirection == UPLEFT ||
+ _playerDirection == UP) && _playerY <= _scrollThreshold) {
+ scrollDown();
+ } else {
+ checkScrollUp();
+ }
+}
+
+bool Player::scrollUp(int forcedAmount) {
+ if (forcedAmount == -1)
+ _scrollAmount = -(_vm->_screen->_clipHeight - _playerY - _scrollThreshold);
+ else
+ _scrollAmount = forcedAmount;
+
+ if ((_vm->_scrollRow + _vm->_screen->_vWindowHeight) >=
+ _vm->_room->_playFieldHeight)
+ return true;
+
+ _scrollFlag = true;
+ _vm->_scrollY = _vm->_scrollY + _scrollAmount;
+
+ while (_vm->_scrollY >= TILE_HEIGHT && !_vm->shouldQuit()) {
+ _vm->_scrollY -= TILE_HEIGHT;
+ ++_vm->_scrollRow;
+ _vm->_buffer1.moveBufferUp();
+
+ _vm->_room->buildRow(_vm->_scrollRow + _vm->_screen->_vWindowHeight,
+ _vm->_screen->_vWindowLinesTall);
+
+ if ((_vm->_scrollRow + _vm->_screen->_vWindowHeight) >=
+ _vm->_room->_playFieldHeight)
+ return true;
+
+ if (_vm->_scrollY <= TILE_HEIGHT)
+ return false;
+ }
+
+ return false;
+}
+
+bool Player::scrollDown(int forcedAmount) {
+ if (forcedAmount == -1)
+ _scrollAmount = -(_playerY - _scrollThreshold);
+ else
+ _scrollAmount = forcedAmount;
+
+ _scrollFlag = true;
+ _vm->_scrollY -= _scrollAmount;
+ if (_vm->_scrollY >= 0)
+ return true;
+
+ do {
+ _vm->_scrollY += TILE_HEIGHT;
+ if (--_vm->_scrollRow < 0)
+ break;
+
+ _vm->_buffer1.moveBufferDown();
+ _vm->_room->buildRow(_vm->_scrollRow, 0);
+
+ if (_vm->_scrollY >= 0)
+ return false;
+ } while (!_vm->shouldQuit());
+
+ _scrollEnd = 3;
+ _vm->_scrollY = 0;
+ _vm->_scrollRow = 0;
+ return true;
+}
+
+bool Player::scrollLeft(int forcedAmount) {
+ Screen &screen = *_vm->_screen;
+ if (forcedAmount == -1)
+ _scrollAmount = -(_vm->_screen->_clipWidth - _playerX - _scrollThreshold);
+ else
+ _scrollAmount = forcedAmount;
+
+ if ((_vm->_scrollCol + screen._vWindowWidth) == _vm->_room->_playFieldWidth) {
+ _scrollEnd = 2;
+ _vm->_scrollX = 0;
+ _scrollFlag = true;
+ return true;
+ } else {
+ _scrollFlag = true;
+ _vm->_scrollX = _vm->_scrollX + _scrollAmount;
+
+ do {
+ if (_vm->_scrollX < TILE_WIDTH)
+ return true;
+
+ _vm->_scrollX -= TILE_WIDTH;
+ ++_vm->_scrollCol;
+ _vm->_buffer1.moveBufferLeft();
+ _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth,
+ screen._vWindowBytesWide);
+ } while (!_vm->shouldQuit() && (_vm->_scrollX >= TILE_WIDTH));
+
+ return (_playerDirection == UPRIGHT);
+ }
+}
+
+bool Player::scrollRight(int forcedAmount) {
+ if (forcedAmount == -1)
+ _scrollAmount = -(_playerX - _scrollThreshold);
+ else
+ _scrollAmount = forcedAmount;
+
+ _scrollFlag = true;
+ _vm->_scrollX -= _scrollAmount;
+
+ if (_vm->_scrollX < 0) {
+ do {
+ _vm->_scrollX += TILE_WIDTH;
+ if (--_vm->_scrollCol < 0) {
+ _scrollEnd = true;
+ _vm->_scrollX = 0;
+ _vm->_scrollCol = 0;
+ return true;
+ }
+
+ _vm->_buffer1.moveBufferRight();
+ _vm->_room->buildColumn(_vm->_scrollCol, 0);
+ } while (!_vm->shouldQuit() && (_vm->_scrollX < 0));
+
+ return false;
+ }
+
+ return true;
+}
+
+void Player::synchronize(Common::Serializer &s) {
+ s.syncAsUint16LE(_roomNumber);
+ s.syncAsSint16LE(_rawPlayerLow.x);
+ s.syncAsSint16LE(_rawPlayer.x);
+ s.syncAsSint16LE(_rawPlayerLow.y);
+ s.syncAsSint16LE(_rawPlayer.y);
+}
+
+} // End of namespace Access