diff options
Diffstat (limited to 'engines/m4/mads_player.cpp')
-rw-r--r-- | engines/m4/mads_player.cpp | 789 |
1 files changed, 0 insertions, 789 deletions
diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp deleted file mode 100644 index 73480088ee..0000000000 --- a/engines/m4/mads_player.cpp +++ /dev/null @@ -1,789 +0,0 @@ -/* 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 "m4/m4.h" -#include "m4/mads_player.h" -#include "m4/mads_scene.h" - -namespace M4 { - -const int MadsPlayer::_directionListIndexes[32] = { - 0, 7, 4, 3, 6, 0, 2, 5, 0, 1, 9, 4, 1, 2, 7, 9, 3, 8, 9, 6, 7, 2, 3, 6, 1, 7, 9, 4, 7, 8, 0, 0 -}; - -MadsPlayer::MadsPlayer() { - _playerPos = Common::Point(160, 78); - _ticksAmount = 3; - _forceRefresh = true; - _stepEnabled = true; - _visible = true; - _yScale = 0; - _moving = false; - - _spriteListStart = 0; - //TODO:unknown vars - _special = 0; - _next = 0; - _unk4 = false; - - _spritesChanged = true; - - _direction = 0; - _newDirection = 0; - _priorTimer = 0; - _priorVisible = false; - _visible3 = false; - _spriteListIdx = 0; - _currentScale = 0; - strcpy(_spritesPrefix, ""); - for (int idx = 0; idx < 8; ++idx) - _spriteSetsPresent[idx] = false; - _frameNum = 0; - _frameOffset = 0; - _unk1 = 0; - _frameCount = 0; - _frameListIndex = 0; - _actionIndex = 0; - _routeCount = 0; - - resetActionList(); -} - -/** - * Loads the sprite set for the player - */ -bool MadsPlayer::loadSprites(const char *prefix) { - const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' }; - char setName[80]; - bool result = true; - - if (prefix) - strcpy(_spritesPrefix, prefix); - - _spriteSetCount = 0; - int prefixLen = strlen(_spritesPrefix); - - if (prefixLen == 0) { - // No player sprites at at all - for (int idx = 0; idx < 8; ++idx) - _spriteSetsPresent[idx] = false; - } else { - strcpy(setName, "*"); - strcat(setName, _spritesPrefix); - strcat(setName, "_0.SS"); - - char *digitP = strchr(setName, '_') + 1; - - for (int idx = 0; idx < 8; ++idx) { - *digitP = suffixList[idx]; - _spriteSetsPresent[idx] = true; - - int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true, SPRITE_SET_CHAR_INFO); - if (setIndex < 0) { - if (idx < 5) - break; - _spriteSetsPresent[idx] = false; - } else { - ++_spriteSetCount; - } - - if (idx == 0) - _spriteListStart = setIndex; - } - - result = 0; - // TODO: Unknown flag - _spritesChanged = false; - } - - return result; -} - -/** - * Called each frame to update the display of the player - */ -void MadsPlayer::update() { - if (_forceRefresh || (_visible != _priorVisible)) { - // If there's an existing player sprite visible, flag it for expiry - int slotIndex = getSpriteSlot(); - if (slotIndex >= 0) - _madsVm->scene()->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE; - - // Figure out the depth for the sprite - int newDepth = 1; - int yp = MIN(_playerPos.y, (int16)155); - - for (int idx = 1; idx < 15; ++idx) { - if (_madsVm->scene()->getSceneResources()._depthBands[newDepth] >= yp) - newDepth = idx + 1; - } - _currentDepth = newDepth; - - // Get the scale - int newScale = getScale(_playerPos.y); - _currentScale = MIN(newScale, 100); - - if (_visible) { - // Player sprite needs to be rendered - MadsSpriteSlot slot; - slot.spriteType = FOREGROUND_SPRITE; - slot.seqIndex = PLAYER_SEQ_INDEX; - slot.spriteListIndex = _spriteListStart + _spriteListIdx; - slot.frameNumber = _frameOffset + _frameNum; - slot.xp = _playerPos.x; - slot.yp = _playerPos.y + (_yScale * newScale) / 100; - slot.depth = newDepth; - slot.scale = newScale; - - if (slotIndex >= 0) { - // Check if the existing player slot has the same details, and can be re-used - MadsSpriteSlot &s2 = _madsVm->scene()->_spriteSlots[slotIndex]; - bool equal = (s2.seqIndex == slot.seqIndex) && (s2.spriteListIndex == slot.spriteListIndex) - && (s2.frameNumber == slot.frameNumber) && (s2.xp == slot.xp) && (s2.yp == slot.yp) - && (s2.depth == slot.depth) && (s2.scale == slot.scale); - - if (equal) - // Undo the prior expiry of the player sprite - s2.spriteType = SPRITE_ZERO; - else - slotIndex = -1; - } - - if (slotIndex < 0) { - // New slot needed, so allocate one and copy the slot data - slotIndex = _madsVm->scene()->_spriteSlots.getIndex(); - _madsVm->scene()->_spriteSlots[slotIndex] = slot; - } - - // TODO: Meaning of _v844c0 block - - } - } - - _visible3 = _priorVisible = _visible; - _forceRefresh = false; -} - -/** - * Updates the animation frame for the player - */ -void MadsPlayer::updateFrame() { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - - if (!spriteSet._charInfo->_numEntries) { - _frameNum = 1; - } else { - _frameListIndex = _actionList[_actionIndex]; - - if (!_visible) { - _unk2 = 0; - } else { - _unk2 = _actionList2[_actionIndex]; - - if (_actionIndex > 0) - --_actionIndex; - } - - // Set the player frame number - int frameIndex = ABS(_frameListIndex); - _frameNum = (_frameListIndex <= 0) ? spriteSet._charInfo->_frameList[frameIndex] : - spriteSet._charInfo->_frameList2[frameIndex]; - - // Set next waiting period in ticks - if (frameIndex == 0) - setTicksAmount(); - else - _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksList[frameIndex]; - } -} - -void MadsPlayer::setupFrame() { - resetActionList(); - _frameOffset = 0; - _spriteListIdx = _directionListIndexes[_direction]; - if (!_spriteSetsPresent[_spriteListIdx]) { - // Direction isn't present, so use alternate direction, with entries flipped - _spriteListIdx -= 4; - _frameOffset = 0x8000; - } - - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - _unk1 = MAX(spriteSet._charInfo->_unk1, 100); - setTicksAmount(); - - _frameCount = spriteSet._charInfo->_totalFrames; - if (_frameCount == 0) - _frameCount = spriteSet.getCount(); - - _yScale = spriteSet._charInfo->_yScale; - - if ((_frameNum <= 0) || (_frameNum > _frameCount)) - _frameNum = 1; - _forceRefresh = true; -} - -void MadsPlayer::step() { - if (_visible && _stepEnabled && !_moving && (_direction == _newDirection) && (_madsVm->_currentTimer >= GET_GLOBAL32(2))) { - if (_actionIndex == 0) { - int randVal = _vm->_random->getRandomNumber(29999); - - if (GET_GLOBAL(0) == SEX_MALE) { - switch (_direction) { - case 1: - case 3: - case 7: - case 9: - if (randVal < 200) { - queueAction(-1, 0); - queueAction(1, 0); - } - break; - - case 2: - if (randVal < 500) { - for (int i = 0; i < 10; ++i) - queueAction((randVal < 250) ? 1 : 2, 0); - } else if (randVal < 750) { - for (int i = 0; i < 5; ++i) - queueAction(1, 0); - queueAction(0, 0); - for (int i = 0; i < 5; ++i) - queueAction(2, 0); - } - break; - - case 4: - case 6: - if (randVal < 500) { - for (int i = 0; i < 10; ++i) - queueAction(1, 0); - } - break; - - case 5: - case 8: - if (randVal < 200) { - queueAction(-1, 0); - queueAction(1, 0); - } - break; - } - } - } - - SET_GLOBAL32(2, GET_GLOBAL32(2) + 6); - } - - if (GET_GLOBAL(138) == 1) { - uint32 diff = _madsVm->_currentTimer - GET_GLOBAL32(142); - if (diff > 60) { - SET_GLOBAL32(144, GET_GLOBAL32(144) + 1); - } else { - SET_GLOBAL32(144, GET_GLOBAL32(144) + diff); - } - - SET_GLOBAL32(142, _madsVm->_currentTimer); - } -} - -void MadsPlayer::nextFrame() { - if (_madsVm->_currentTimer >= (_priorTimer + _ticksAmount)) { - _priorTimer = _madsVm->_currentTimer; - - if (_moving) - move(); - else - idle(); - - // Post update logic - if (_moving) { - ++_frameNum; - if (_frameNum > _frameCount) - _frameNum = 1; - _forceRefresh = true; - } else if (!_forceRefresh) { - idle(); - } - - // Final update - update(); - } -} - -void MadsPlayer::setDest(int destX, int destY, int facing) { - resetActionList(); - setTicksAmount(); - _moving = true; - _destFacing = facing; - - _madsVm->scene()->getSceneResources().setRouteNode(_madsVm->scene()->getSceneResources()._nodes.size() - 2, - _playerPos, _madsVm->scene()->_depthSurface); - _madsVm->scene()->getSceneResources().setRouteNode(_madsVm->scene()->getSceneResources()._nodes.size() - 1, - Common::Point(destX, destY), _madsVm->scene()->_depthSurface); - - bool v = _madsVm->scene()->getDepthHighBit(Common::Point(destX, destY)); - setupRoute(v); - _next = 0; - - if (_routeCount > 0) { - Common::Point srcPos = _playerPos; - for (int routeCtr = _routeCount - 1; (routeCtr >= 0) && (_next == 0); --routeCtr) { - int idx = _routeIndexes[routeCtr]; - const Common::Point &pt = _madsVm->scene()->getSceneResources()._nodes[idx].pt; - - _next = scanPath(_madsVm->scene()->_depthSurface, srcPos, pt); - srcPos = pt; - } - } -} - - -int MadsPlayer::getScale(int yp) { - MadsSceneResources &r = _madsVm->scene()->getSceneResources(); - - int scale = (r.bandsRange() == 0) ? r._maxScale : (yp - r._yBandsStart) * r.scaleRange() / r.bandsRange() - + r._minScale; - - return MIN(scale, 100); -} - -/** - * Scans through the scene's sprite slot list to find any sprite displaying the player - */ -int MadsPlayer::getSpriteSlot() { - MadsSpriteSlots &slots = _madsVm->scene()->_spriteSlots; - for (int i = 0; i < slots.startIndex; ++i) { - if ((slots[i].seqIndex == PLAYER_SEQ_INDEX) && (slots[i].spriteType >= SPRITE_ZERO)) - return i; - } - return -1; -} - -void MadsPlayer::setTicksAmount() { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksAmount; - if (_madsVm->_player._ticksAmount == 0) - _madsVm->_player._ticksAmount = 6; -} - -void MadsPlayer::resetActionList() { - _actionList[0] = 0; - _actionList2[0] = 0; - _actionIndex = 0; - _unk2 = 0; - _unk3 = 0; -} - -int MadsPlayer::queueAction(int action1, int action2) { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - - if ((action1 < spriteSet._charInfo->_numEntries) && (_actionIndex < 11)) { - ++_actionIndex; - _actionList[_actionIndex] = action1; - _actionList2[_actionIndex] = action2; - return false; - } - - return true; -} - -void MadsPlayer::idle() { - if (_direction != _newDirection) { - // The direction has changed, so reset for new direction - dirChanged(); - return; - } - - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - if (spriteSet._charInfo->_numEntries == 0) - // No entries, so exit immediately - return; - - int frameIndex = ABS(_frameListIndex); - int direction = (_frameListIndex < 0) ? -1 : 1; - - if (frameIndex >= spriteSet._charInfo->_numEntries) - // Reset back to the start of the list - _frameListIndex = 0; - else { - _frameNum += direction; - _forceRefresh = true; - - if (spriteSet._charInfo->_frameList2[frameIndex] < _frameNum) { - _unk3 = _unk2; - updateFrame(); - } - if (spriteSet._charInfo->_frameList[frameIndex] < _frameNum) { - _unk3 = _unk2; - updateFrame(); - } - } -} - -void MadsPlayer::move() { - bool routeFlag = false; - - if (_moving) { - int idx = _routeCount; - while (!_v844C0 && (_destPos.x == _playerPos.x) && (_destPos.y == _playerPos.y)) { - if (idx != 0) { - --idx; - SceneNode &node = _madsVm->scene()->getSceneResources()._nodes[_routeIndexes[idx]]; - _destPos = node.pt; - routeFlag = true; - } else if (_v844BE == idx) { - // End of walking path - _routeCount = 0; - _moving = false; - turnToDestFacing(); - routeFlag = true; - idx = _routeCount; - } else { - _v844C0 = _v844BE; - _v844BC = true; - _v844BE = 0; - _stepEnabled = true; - routeFlag = false; - } - - if (!_moving) - break; - } - _routeCount = idx; - } - - if (routeFlag && _moving) - startMovement(); - - if (_newDirection != _direction) - dirChanged(); - else if (!_moving) - updateFrame(); - - int var1 = _unk1; - if (_unk4 && (_hypotenuse > 0)) { - int v1 = -(_currentScale - 100) * (_posDiff.x - 1) / _hypotenuse + _currentScale; - var1 = MAX(1, 10000 / (v1 * _currentScale * var1)); - } - - if (!_moving || (_direction != _newDirection)) - return; - - Common::Point newPos = _playerPos; - - if (_v8452E < var1) { - do { - if (_v8452C < _posDiff.x) - _v8452C += _posDiff.y; - if (_v8452C >= _posDiff.x) { - if ((_posChange.y > 0) || (_v844C0 != 0)) - newPos.y += _yDirection; - --_posChange.y; - _v8452C -= _posDiff.x; - } - - if (_v8452C < _posDiff.x) { - if ((_posChange.x > 0) || (_v844C0 != 0)) - newPos.x += _xDirection; - --_posChange.x; - } - - if ((_v844BC == 0) && (_v844C0 == 0) && (_v844BE == 0)) { - routeFlag = _madsVm->scene()->getDepthHighBit(newPos); - - if (_special == 0) - _special = _madsVm->scene()->getDepthHighBits(newPos); - } - - _v8452E += _v84530; - - } while ((_v8452E < var1) && !routeFlag && ((_posChange.x > 0) || (_posChange.y > 0) || (_v844C0 != 0))); - } - - _v8452E -= var1; - - if (routeFlag) - moveComplete(); - else { - if (!_v844C0) { - // If the move is complete, make sure the position is exactly on the given destination - if (_posChange.x == 0) - newPos.x = _destPos.x; - if (_posChange.y == 0) - newPos.y = _destPos.y; - } - - _playerPos = newPos; - } -} - -void MadsPlayer::dirChanged() { - int dirIndex = 0, dirIndex2 = 0; - int newDir = 0, newDir2 = 0; - - if (_direction != _newDirection) { - // Find the index for the given direction in the player direction list - int tempDir = _direction; - do { - ++dirIndex; - newDir += tempDir; - tempDir = _directionListIndexes[tempDir + 10]; - } while (tempDir != _newDirection); - } - - - if (_direction != _newDirection) { - // Find the index for the given direction in the player direction list - int tempDir = _direction; - do { - ++dirIndex2; - newDir2 += tempDir; - tempDir = _directionListIndexes[tempDir + 20]; - } while (tempDir != _newDirection); - } - - int diff = dirIndex - dirIndex2; - if (diff == 0) - diff = newDir - newDir2; - - _direction = (diff >= 0) ? _directionListIndexes[_direction + 20] : _directionListIndexes[_direction + 10]; - setupFrame(); - if ((_direction == _newDirection) && !_moving) - updateFrame(); - - _priorTimer += 1; -} - -void MadsPlayer::moveComplete() { - reset(); - //todo: Unknown flag -} - -void MadsPlayer::reset() { - _destPos = _playerPos; - _destFacing = 5; - _newDirection = _direction; - - _madsVm->scene()->_action._startWalkFlag = false; - _madsVm->scene()->_action._walkFlag = false; - _moving = false; - _v844BC = false; - _v844C0 = false; - _v844BE = 0; - _next = 0; - _routeCount = 0; -} - -/** - * Scans along an edge connecting two points within the depths/walk surface, and returns the information of the first - * pixel high nibble encountered with a non-zero value - */ -int MadsPlayer::scanPath(M4Surface *depthSurface, const Common::Point &srcPos, const Common::Point &destPos) { - // For compressed depth surfaces, always return 0 - if (_madsVm->scene()->getSceneResources()._depthStyle != 2) - return 0; - - int yDiff = destPos.y - srcPos.y; - int yAmount = MADS_SURFACE_WIDTH; - - if (yDiff < 0) { - yDiff = -yDiff; - yAmount = -yAmount; - } - - int xDiff = destPos.x - srcPos.y; - int xDirection = 1; - int xAmount = 0; - if (xDiff < 0) { - xDiff = -xDiff; - xDirection = -xDirection; - xAmount = MIN(yDiff, xDiff); - } - - ++xDiff; - ++yDiff; - - const byte *srcP = depthSurface->getBasePtr(srcPos.x, srcPos.y); - int index = xAmount; - - // Outer horizontal movement loop - for (int yIndex = 0; yIndex < yDiff; ++yIndex) { - index += yDiff; - int v = (*srcP & 0x7F) >> 4; - if (v) - return v; - - // Inner loop for handling vertical movement - while (index >= xDiff) { - index -= xDiff; - - v = (*srcP & 0x7F) >> 4; - if (v) - return v; - - srcP += yAmount; - } - - srcP += xDirection; - } - - return 0; -} - -/** - * Starts a player moving to a given destination - */ -void MadsPlayer::startMovement() { - int xDiff = _destPos.x - _playerPos.x; - int yDiff = _destPos.y - _playerPos.y; - int srcScale = getScale(_playerPos.y); - int destScale = getScale(_destPos.y); - - // Sets the X direction - if (xDiff > 0) - _xDirection = 1; - else if (xDiff < 0) - _xDirection = -1; - else - _xDirection = 0; - - // Sets the Y direction - if (yDiff > 0) - _yDirection = 1; - else if (yDiff < 0) - _yDirection = -1; - else - _yDirection = 0; - - xDiff = ABS(xDiff); - yDiff = ABS(yDiff); - int scaleDiff = ABS(srcScale - destScale); - - int xAmt100 = xDiff * 100; - int yAmt100 = yDiff * 100; - int xAmt33 = xDiff * 33; - - int scaleAmount = (_unk4 ? scaleDiff * 3 : 0) + 100 * yDiff / 100; - int scaleAmount100 = scaleAmount * 100; - - // Figure out direction that will need to be moved in - int majorDir; - if (xDiff == 0) - majorDir = 1; - else if (yDiff == 0) - majorDir = 3; - else { - if ((scaleAmount < xDiff) && ((xAmt33 / scaleAmount) >= 141)) - majorDir = 3; - else if (yDiff <= xDiff) - majorDir = 2; - else if ((scaleAmount100 / xDiff) >= 141) - majorDir = 1; - else - majorDir = 2; - } - - switch (majorDir) { - case 1: - _newDirection = (_yDirection <= 0) ? 8 : 2; - break; - case 2: { - _newDirection = ((_yDirection <= 0) ? 9 : 3) - ((_xDirection <= 0) ? 2 : 0); - break; - } - case 3: - _newDirection = (_xDirection <= 0) ? 4 : 6; - break; - default: - break; - } - - _hypotenuse = SqrtF16(xAmt100 * xAmt100 + yAmt100 * yAmt100); - _posDiff.x = xDiff + 1; - _posDiff.y = yDiff + 1; - _posChange.x = xDiff; - _posChange.y = yDiff; - - int majorChange = MAX(xDiff, yDiff); - _v84530 = (majorChange == 0) ? 0 : _hypotenuse / majorChange; - - if (_playerPos.x > _destPos.x) - _v8452C = MAX(_posChange.x, _posChange.y); - else - _v8452C = 0; - - _hypotenuse /= 100; - _v8452E = -_v84530; -} - -void MadsPlayer::turnToDestFacing() { - if (_destFacing != 5) - _newDirection = _destFacing; -} - -void MadsPlayer::setupRoute(bool bitFlag) { - // Reset the flag set of nodes in use - SceneNodeList &nodes = _madsVm->scene()->getSceneResources()._nodes; - for (uint i = 0; i < nodes.size(); ++i) - nodes[i].active = false; - - // Start constructing route node list - _routeLength = 0x3FFF; - _routeCount = 0; - - setupRouteNode(_tempRoute, nodes.size() - 1, bitFlag ? 0xC000 : 0x8000, 0); -} - -void MadsPlayer::setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength) { - SceneNodeList &nodes = _madsVm->scene()->getSceneResources()._nodes; - SceneNode ¤tNode = nodes[nodeIndex]; - currentNode.active = true; - - *routeIndexP++ = nodeIndex; - - int subIndex = nodes.size() - 2; - int indexVal = nodes[nodeIndex].indexes[subIndex]; - if (indexVal & flags) { - routeLength += indexVal & 0x3FFF; - if (routeLength < _routeLength) { - // Found a new shorter route to destination, so set up the route with the found one - Common::copy(_tempRoute, routeIndexP, _routeIndexes); - _routeCount = routeIndexP - _tempRoute; - _routeLength = indexVal & 0x3FFF; - } - } else { - for (int idx = nodes.size() - 2; idx > 0; --idx) { - int nodePos = idx - 1; - if (!nodes[nodePos].active && ((currentNode.indexes[nodePos] & flags) != 0)) - setupRouteNode(routeIndexP, nodePos, 0x8000, indexVal & 0x3fff); - } - } - - currentNode.active = false; -} - -} // End of namespace M4 |