scummvm/engines/prince/hero.cpp

985 lines
23 KiB
C++
Raw Normal View History

/* 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.
*
*/
2013-12-05 00:02:31 +00:00
#include "common/debug.h"
#include "common/random.h"
#include "prince/hero.h"
2013-12-05 00:02:31 +00:00
#include "prince/hero_set.h"
#include "prince/animation.h"
#include "prince/resource.h"
2014-05-04 16:02:53 +00:00
#include "prince/prince.h"
2014-05-11 11:57:52 +00:00
#include "prince/graphics.h"
2014-07-18 13:35:43 +00:00
#include "prince/flags.h"
#include "prince/script.h"
namespace Prince {
2014-05-11 11:57:52 +00:00
Hero::Hero(PrinceEngine *vm, GraphicsMan *graph) : _vm(vm), _graph(graph)
, _number(0), _visible(false), _state(MOVE), _middleX(0), _middleY(0)
, _boreNum(1), _currHeight(0), _moveDelay(0), _shadMinus(0), _moveSetType(0)
2014-07-18 13:35:43 +00:00
, _lastDirection(kHeroDirDown), _destDirection(kHeroDirDown), _talkTime(0), _boredomTime(0), _phase(0)
, _specAnim(nullptr), _drawX(0), _drawY(0), _drawZ(0), _zoomFactor(0), _scaleValue(0)
2014-05-14 03:04:12 +00:00
, _shadZoomFactor(0), _shadScaleValue(0), _shadLineLen(0), _shadDrawX(0), _shadDrawY(0)
, _frameXSize(0), _frameYSize(0), _scaledFrameXSize(0), _scaledFrameYSize(0), _color(0)
, _coords(nullptr), _dirTab(nullptr), _currCoords(nullptr), _currDirTab(nullptr), _step(0)
2014-07-18 13:35:43 +00:00
, _maxBoredom(200), _turnAnim(0), _leftRightMainDir(0), _upDownMainDir(0)
{
_zoomBitmap = (byte *)malloc(kZoomBitmapLen);
_shadowBitmap = (byte *)malloc(2 * kShadowBitmapSize);
_shadowLine = new byte[kShadowLineArraySize];
}
2013-12-05 00:02:31 +00:00
Hero::~Hero() {
free(_zoomBitmap);
free(_shadowBitmap);
delete[] _shadowLine;
freeHeroAnim();
}
2013-12-05 00:02:31 +00:00
bool Hero::loadAnimSet(uint32 animSetNr) {
if (animSetNr > sizeof(heroSetTable)) {
return false;
}
_shadMinus = heroSetBack[animSetNr];
for (uint32 i = 0; i < _moveSet.size(); i++) {
2013-12-05 00:02:31 +00:00
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 = NULL;
if (animSet[i] != NULL) {
anim = new Animation();
Resource::loadResource(anim, animSet[i], true);
2013-12-05 00:02:31 +00:00
}
_moveSet[i] = anim;
}
return true;
}
Graphics::Surface *Hero::getSurface() {
2014-04-01 23:35:07 +00:00
if (_moveSet[_moveSetType]) {
int16 phaseFrameIndex = _moveSet[_moveSetType]->getPhaseFrameIndex(_phase);
2014-05-30 15:48:00 +00:00
Graphics::Surface *heroFrame = _moveSet[_moveSetType]->getFrame(phaseFrameIndex);
return heroFrame;
2013-12-05 00:02:31 +00:00
}
return NULL;
}
//TEMP
void Hero::getState() {
switch (_state) {
case STAY:
debug("STAY");
break;
case TURN:
debug("TURN");
break;
case MOVE:
debug("MOVE");
break;
case BORE:
debug("BORE");
break;
case SPEC:
debug("SPEC");
break;
case TALK:
debug("TALK");
break;
case MVAN:
debug("MVAN");
break;
case TRAN:
debug("TRAN");
break;
case RUN:
debug("RUN");
break;
case DMOVE:
debug("DMOVE");
break;
}
}
uint16 Hero::getData(AttrId dataId) {
switch (dataId) {
case kHeroLastDir:
return _lastDirection;
case kHeroAnimSet:
return _moveSetType;
default:
assert(false);
return 0;
}
}
2014-04-28 10:15:54 +00:00
int Hero::getScaledValue(int size) {
int newSize = 0;
int16 initScaleValue = _scaleValue;
2014-04-29 14:57:14 +00:00
if (_scaleValue != 10000) {
2014-04-28 10:15:54 +00:00
for(int i = 0; i < size; i++) {
initScaleValue -= 100;
if(initScaleValue >= 0) {
newSize++;
} else {
initScaleValue += _scaleValue;
}
}
return newSize;
} else {
return size;
}
}
2014-04-29 14:57:14 +00:00
Graphics::Surface *Hero::zoomSprite(Graphics::Surface *heroFrame) {
Graphics::Surface *zoomedFrame = new Graphics::Surface();
2014-05-14 03:04:12 +00:00
zoomedFrame->create(_scaledFrameXSize, _scaledFrameYSize, Graphics::PixelFormat::createFormatCLUT8());
2014-04-29 14:57:14 +00:00
int sprZoomX;
int sprZoomY = _scaleValue;
uint xSource = 0;
uint ySource = 0;
uint xDest = 0;
uint yDest = 0;
2014-05-14 03:04:12 +00:00
for (int i = 0; i < _scaledFrameYSize; i++) {
// linear_loop:
while(1) {
sprZoomY -= 100;
if (sprZoomY >= 0 || _scaleValue == 10000) {
// all_r_y
sprZoomX = _scaleValue;
break; // to loop_lin
} else {
sprZoomY += _scaleValue;
xSource = 0;
ySource++;
2014-04-28 18:59:42 +00:00
}
}
// loop_lin:
2014-05-14 03:04:12 +00:00
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 += _scaleValue;
j--;
2014-04-28 18:59:42 +00:00
}
xSource++;
2014-04-28 18:59:42 +00:00
}
xDest = 0;
yDest++;
xSource = 0;
ySource++;
2014-04-29 14:57:14 +00:00
}
return zoomedFrame;
2014-04-29 14:57:14 +00:00
}
void Hero::countDrawPosition() {
int16 tempMiddleY;
int16 baseX = _moveSet[_moveSetType]->getBaseX();
int16 baseY = _moveSet[_moveSetType]->getBaseY();
// any chance?
if (baseX == 320) {
tempMiddleY = _middleY - (baseY - 240);
} else {
tempMiddleY = _middleY;
}
int phaseFrameIndex = _moveSet[_moveSetType]->getPhaseFrameIndex(_phase);
_frameXSize = _moveSet[_moveSetType]->getFrameWidth(phaseFrameIndex);
_frameYSize = _moveSet[_moveSetType]->getFrameHeight(phaseFrameIndex);
2014-05-14 03:04:12 +00:00
_scaledFrameXSize = getScaledValue(_frameXSize);
_scaledFrameYSize = getScaledValue(_frameYSize);
2014-06-01 02:25:01 +00:00
// any use of this?
/*
if (!_moveSet[_moveSetType]->testId()) {
int diffX = _moveSet[_moveSetType]->getIdXDiff();
int diffY = _moveSet[_moveSetType]->getIdYDiff();
}
*/
2014-04-29 14:57:14 +00:00
if (_zoomFactor != 0) {
//notfullSize
2014-05-14 03:04:12 +00:00
_drawX = _middleX - _scaledFrameXSize / 2;
_drawY = tempMiddleY + 1 - _scaledFrameYSize;
2014-06-01 12:28:48 +00:00
_vm->checkMasks(_drawX, _drawY - 1, _scaledFrameXSize, _scaledFrameYSize, _middleY);
2014-04-28 10:15:54 +00:00
} else {
//fullSize
2014-05-14 03:04:12 +00:00
_drawX = _middleX - _frameXSize / 2;
_drawY = tempMiddleY + 1 - _frameYSize;
2014-06-01 12:28:48 +00:00
_vm->checkMasks(_drawX, _drawY - 1, _frameXSize, _frameYSize, _middleY);
2014-04-28 10:15:54 +00:00
}
2014-06-02 20:59:13 +00:00
_drawZ = tempMiddleY;
2014-04-28 10:15:54 +00:00
}
2014-04-29 14:57:14 +00:00
void Hero::plotPoint(int x, int y) {
2014-05-14 03:04:12 +00:00
WRITE_UINT16(&_shadowLine[_shadLineLen * 4], x);
WRITE_UINT16(&_shadowLine[_shadLineLen * 4 + 2], y);
}
static void plot(int x, int y, int color, void *data) {
Hero *shadowLine = (Hero *)data;
shadowLine->plotPoint(x, y);
2014-05-14 03:04:12 +00:00
shadowLine->_shadLineLen++;
}
void Hero::showHeroShadow(Graphics::Surface *heroFrame) {
Graphics::Surface *makeShadow = new Graphics::Surface();
2014-05-14 03:04:12 +00:00
makeShadow->create(_frameXSize, _frameYSize, Graphics::PixelFormat::createFormatCLUT8());
2014-05-14 03:04:12 +00:00
for (int y = 0; y < _frameYSize; y++) {
byte *src = (byte *)heroFrame->getBasePtr(0, y);
2014-05-11 11:57:52 +00:00
byte *dst = (byte *)makeShadow->getBasePtr(0, y);
2014-05-14 03:04:12 +00:00
for (int x = 0; x < _frameXSize; x++, dst++, src++) {
2014-05-11 11:57:52 +00:00
if (*src != 0xFF) {
*dst = _graph->kShadowColor;
} else {
*dst = *src;
}
}
}
2014-05-14 03:04:12 +00:00
int destX = _middleX - _scaledFrameXSize / 2;
int destY = _middleY - _shadMinus - 1;
2014-05-04 16:02:53 +00:00
if (destY > 1 && destY < kMaxPicHeight) {
2014-05-11 11:57:52 +00:00
int shadDirection;
2014-05-04 16:02:53 +00:00
if (_lightY > destY) {
2014-05-11 11:57:52 +00:00
shadDirection = 1;
2014-05-04 16:02:53 +00:00
} else {
2014-05-11 11:57:52 +00:00
shadDirection = 0;
2014-05-04 16:02:53 +00:00
}
2014-05-14 03:04:12 +00:00
_shadLineLen = 0;
Graphics::drawLine(_lightX, _lightY, destX, destY, 0, &plot, this);
2014-05-04 16:02:53 +00:00
2014-05-11 11:57:52 +00:00
byte *sprShadow = (byte *)_graph->_shadowTable70;
2014-05-14 03:04:12 +00:00
_shadDrawX = destX - _vm->_picWindowX;
_shadDrawY = destY - _vm->_picWindowY;
2014-05-14 03:04:12 +00:00
int shadPosX = _shadDrawX;
int shadPosY = _shadDrawY;
int shadBitAddr = destY * kMaxPicWidth / 8 + destX / 8;
2014-05-09 12:01:08 +00:00
int shadBitMask = 128 >> (destX % 8);
int shadZoomY2 = _shadScaleValue;
int shadZoomY = _scaleValue;
int diffX = 0;
int diffY = 0;
2014-05-16 02:29:08 +00:00
int shadowHeroX = 0;
int shadowHeroY = _frameYSize - 1;
int shadLastY = 0;
2014-05-16 02:29:08 +00:00
byte *shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY); // first pixel from last row of shadow hero
2014-05-14 03:04:12 +00:00
byte *background = (byte *)_graph->_frontScreen->getBasePtr(_shadDrawX, _shadDrawY); // pixel of background where shadow sprite starts
// banked2
2014-05-11 11:57:52 +00:00
byte *shadowLineStart = _shadowLine + 8;
2014-05-16 02:29:08 +00:00
int shadWallDown = 0;
int shadWallBitAddr = 0;
int shadWallBitMask = 0;
byte *shadWallDestAddr = 0;
int shadWallPosY = 0;
int shadWallSkipX = 0;
int shadWallModulo = 0;
// linear_loop
2014-05-16 02:29:08 +00:00
for (int i = 0; i < _frameYSize; i++) {
int shadSkipX = 0;
int ct_loop = 0;
int sprModulo = 0;
2014-05-09 12:01:08 +00:00
2014-05-16 02:29:08 +00:00
int j;
//retry_line:
2014-05-16 02:29:08 +00:00
for (j = _frameYSize - i; j > 0; j--) {
shadZoomY -= 100;
2014-05-09 12:01:08 +00:00
if (shadZoomY < 0 && _scaleValue != 10000) {
shadZoomY += _scaleValue;
2014-05-16 02:29:08 +00:00
shadowHeroY--;
if (shadowHeroY < 0) {
break;
}
2014-05-16 02:29:08 +00:00
shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY);
} else {
2014-05-16 02:29:08 +00:00
break;
}
2014-05-09 12:01:08 +00:00
}
if (j == 0) {
break;
}
2014-05-16 02:29:08 +00:00
if (shadowHeroY < 0) {
break;
}
//line_y_ok
if (shadLastY != shadPosY && shadPosY >= 0 && shadPosY < 480 && shadPosX < 640) {
shadLastY = shadPosY;
2014-05-16 02:29:08 +00:00
if (shadPosX < 0) {
shadSkipX = -1 * shadPosX;
background += shadSkipX;
2014-05-14 03:04:12 +00:00
if (_frameXSize > shadSkipX) {
2014-05-16 02:29:08 +00:00
shadowHero += shadSkipX;
shadBitAddr += shadSkipX / 8;
2014-05-16 02:29:08 +00:00
if ((shadSkipX % 8) != 0) {
//loop_rotate:
2014-05-16 02:29:08 +00:00
for (int a = 0; a < (shadSkipX % 8); a++) {
if (shadBitMask == 1) {
shadBitMask = 128;
shadBitAddr++;
} else {
shadBitMask >>= 1;
2014-05-09 12:01:08 +00:00
}
}
2014-05-11 11:57:52 +00:00
}
} else {
//skip_line
2014-05-16 02:29:08 +00:00
//test it
2014-05-11 11:57:52 +00:00
}
} else {
//x1_ok
2014-05-14 03:04:12 +00:00
if (shadPosX + _frameXSize > 640) {
ct_loop = 640 - shadPosX; // test it
sprModulo = shadPosX + _frameXSize - 640;
} else {
//draw_line
2014-05-14 03:04:12 +00:00
ct_loop = _frameXSize;
2014-05-11 11:57:52 +00:00
}
}
//draw_line1
//retry_line2
2014-05-16 02:29:08 +00:00
int k;
for (k = j; k > 0; k--) {
shadZoomY2 -= 100;
if (shadZoomY2 < 0 && _shadScaleValue != 10000) {
shadZoomY2 += _shadScaleValue;
2014-05-16 02:29:08 +00:00
shadowHeroY--;
if (shadowHeroY < 0) {
break;
2014-05-11 11:57:52 +00:00
}
2014-05-16 02:29:08 +00:00
shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY);
} else {
2014-05-16 02:29:08 +00:00
break;
2014-05-11 11:57:52 +00:00
}
}
2014-05-16 02:29:08 +00:00
if (shadowHeroY < 0) {
break;
}
2014-05-16 02:29:08 +00:00
if (k == 0) {
break;
}
//line_y_ok_2:
//copy_trans
2014-05-16 02:29:08 +00:00
bool shadWDFlag = false;
int shadZoomX = _scaleValue;
int backgroundDiff = 0;
int shadBitMaskCopyTrans = shadBitMask;
int shadBitAddrCopyTrans = shadBitAddr;
//ct_loop:
2014-05-22 22:48:52 +00:00
for (int l = 0; l < ct_loop; l++) {
shadZoomX -= 100;
if (shadZoomX < 0 && _scaleValue != 10000) {
shadZoomX += _scaleValue;
} else {
if (*shadowHero == _graph->kShadowColor) {
if ((shadBitMaskCopyTrans & _shadowBitmap[shadBitAddrCopyTrans]) != 0) {
if (shadWallDown == 0) {
if ((shadBitMaskCopyTrans & _shadowBitmap[shadBitAddrCopyTrans + kShadowBitmapSize]) != 0) {
2014-05-16 02:29:08 +00:00
shadWDFlag = true;
//shadow
*background = *(sprShadow + *background);
2014-05-11 11:57:52 +00:00
}
2014-05-09 12:01:08 +00:00
}
} else {
//shadow
*background = *(sprShadow + *background);
2014-05-09 12:01:08 +00:00
}
2014-05-11 11:57:52 +00:00
}
//ct_next
if (shadBitMaskCopyTrans == 1) {
shadBitMaskCopyTrans = 128;
shadBitAddrCopyTrans++;
2014-05-11 11:57:52 +00:00
} else {
shadBitMaskCopyTrans >>= 1;
2014-05-11 11:57:52 +00:00
}
//okok
backgroundDiff++;
2014-05-14 03:04:12 +00:00
background = (byte *)_graph->_frontScreen->getBasePtr(_shadDrawX + diffX + backgroundDiff, _shadDrawY + diffY);
2014-05-11 11:57:52 +00:00
}
2014-05-16 02:29:08 +00:00
shadowHeroX++;
shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY);
}
//byebyebye
if (!shadWallDown && shadWDFlag) {
shadWallDown = shadPosX;
shadWallBitAddr = shadBitAddr;
shadWallDestAddr = (byte *)_graph->_frontScreen->getBasePtr(_shadDrawX + diffX, _shadDrawY + diffY);
shadWallBitMask = shadBitMask;
shadWallPosY = shadPosY;
shadWallSkipX = shadSkipX;
shadWallModulo = sprModulo;
}
//byebye
if (shadDirection != 0 && shadWallDown != 0) {
int shadBitMaskWallCopyTrans = shadWallBitMask;
int shadBitAddrWallCopyTrans = shadWallBitAddr;
background = shadWallDestAddr;
2014-05-16 02:29:08 +00:00
shadowHero = (byte *)makeShadow->getBasePtr(shadWallSkipX, shadowHeroY);
if (ct_loop > shadWallSkipX && ct_loop - shadWallSkipX > shadWallModulo) {
//WALL_copy_trans
2014-05-16 02:29:08 +00:00
shadWDFlag = false;
2014-05-27 19:30:57 +00:00
int shadZoomXWall = _scaleValue;
int backgroundDiffWall = 0;
2014-05-16 02:29:08 +00:00
int shadowHeroXWall = 0;
//ct_loop:
2014-05-22 22:48:52 +00:00
for (int m = 0; m < ct_loop; m++) {
2014-05-27 19:30:57 +00:00
shadZoomXWall -= 100;
if (shadZoomXWall < 0 && _scaleValue != 10000) {
shadZoomXWall += _scaleValue;
} else {
//point_ok:
if (*shadowHero == _graph->kShadowColor) {
if ((shadBitMaskWallCopyTrans & _shadowBitmap[shadBitAddrWallCopyTrans + kShadowBitmapSize]) != 0) {
*background = *(sprShadow + *background);
}
}
//ct_next
if (shadBitMaskWallCopyTrans == 1) {
shadBitMaskWallCopyTrans = 128;
shadBitAddrWallCopyTrans++;
} else {
shadBitMaskWallCopyTrans >>= 1;
}
//okok
backgroundDiffWall++;
background = shadWallDestAddr + backgroundDiffWall;
}
2014-05-16 02:29:08 +00:00
shadowHeroXWall++;
shadowHero = (byte *)makeShadow->getBasePtr(shadWallSkipX + shadowHeroXWall, shadowHeroY);
}
}
//krap2
2014-05-16 02:29:08 +00:00
shadWallDestAddr -= kScreenWidth;
shadWallBitAddr -= kMaxPicWidth / 8;
shadWallPosY--;
2014-05-09 12:01:08 +00:00
}
}
2014-05-09 12:01:08 +00:00
//skip_line
//next_line
if (*(shadowLineStart + 2) < *(shadowLineStart - 2)) {
//minus_y
shadBitAddr -= kMaxPicWidth / 8;
shadPosY--;
diffY--;
} else if (*(shadowLineStart + 2) > *(shadowLineStart - 2)) {
shadBitAddr += kMaxPicWidth / 8;
shadPosY++;
diffY++;
}
//no_change_y
if (*shadowLineStart < *(shadowLineStart - 4)) {
//minus_x
shadPosX--;
//rol
if (shadBitMask == 128) {
shadBitMask = 1;
shadBitAddr--;
} else {
shadBitMask <<= 1;
}
diffX--;
} else if (*shadowLineStart > *(shadowLineStart - 4)) {
shadPosX++;
//ror
if (shadBitMask == 1) {
shadBitMask = 128;
shadBitAddr++;
} else {
shadBitMask >>= 1;
}
diffX++;
}
//no_change_x
shadowLineStart += 4;
2014-05-16 02:29:08 +00:00
shadowHeroY--;
if (shadowHeroY < 0) {
break;
}
2014-05-16 02:29:08 +00:00
shadowHeroX = 0;
2014-05-14 03:04:12 +00:00
background = (byte *)_graph->_frontScreen->getBasePtr(_shadDrawX + diffX, _shadDrawY + diffY);
2014-05-16 02:29:08 +00:00
shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY);
2014-05-11 11:57:52 +00:00
}
//koniec_bajki - end_of_a_story
2014-05-04 16:02:53 +00:00
}
makeShadow->free();
delete makeShadow;
}
void Hero::showHeroAnimFrame() {
if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 1) {
if (_state == MVAN || _state == TRAN) {
_phase += 2;
} else {
_phase++;
}
} else {
if (_state == TALK) {
_phase = _moveSet[_moveSetType]->getLoopCount();
} else {
_phase = 0;
}
}
countDrawPosition();
}
void Hero::setScale(int8 zoomBitmapValue) {
if (zoomBitmapValue == 0) {
2014-04-28 18:59:42 +00:00
_zoomFactor = 0;
_scaleValue = 10000;
} else {
_zoomFactor = zoomBitmapValue;
2014-04-28 18:59:42 +00:00
_scaleValue = 10000 / _zoomFactor;
}
}
void Hero::selectZoom() {
int8 zoomBitmapValue = *(_zoomBitmap + _middleY / 4 * kZoomBitmapWidth + _middleX / 4);
setScale(zoomBitmapValue);
}
void Hero::setShadowScale(int32 shadowScale) {
shadowScale = 100 - shadowScale;
if (shadowScale == 0) {
_shadZoomFactor = 0;
_shadScaleValue = 10000;
} else {
_shadZoomFactor = shadowScale;
_shadScaleValue = 10000 / _shadZoomFactor;
}
}
void Hero::specialAnim() {
}
2014-07-18 13:35:43 +00:00
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;
2014-07-18 13:35:43 +00:00
case kHeroDirRight:
switch (newDirection) {
case kHeroDirLeft:
return kMove_MRL;
case kHeroDirUp:
return kMove_MRU;
case kHeroDirDown:
return kMove_MRD;
}
break;
2014-07-18 13:35:43 +00:00
case kHeroDirUp:
switch (newDirection) {
case kHeroDirLeft:
return kMove_MUL;
case kHeroDirRight:
return kMove_MUR;
case kHeroDirDown:
return kMove_MUD;
}
break;
2014-07-18 13:35:43 +00:00
case kHeroDirDown:
switch (newDirection) {
case kHeroDirLeft:
return kMove_MDL;
case kHeroDirRight:
return kMove_MDR;
case kHeroDirUp:
return kMove_MDU;
}
break;
}
2014-07-19 01:11:27 +00:00
error("rotateHero - wrong directions - old %d, new %d", oldDirection, newDirection);
}
void Hero::showHero() {
if (_visible) {
2014-07-18 13:35:43 +00:00
//cmp w FLAGI+NOHEROATALL,ax
//jnz @@no_hero_visible
if (_talkTime != 0) {
_talkTime--;
}
2014-07-18 13:35:43 +00:00
// Scale of hero
selectZoom();
2014-07-17 12:28:44 +00:00
if (_state != STAY) {
_boredomTime = 0;
}
switch (_state) {
case STAY:
2014-07-18 13:35:43 +00:00
if (!_vm->_optionsFlag && !_vm->_interpreter->getLastOPCode()) {
_boredomTime++;
if (_boredomTime == _maxBoredom) {
_boredomTime = 0;
_state = BORE;
}
} else {
_boredomTime = 0;
}
switch (_lastDirection) {
2014-07-18 13:35:43 +00:00
case kHeroDirLeft:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_SL;
break;
2014-07-18 13:35:43 +00:00
case kHeroDirRight:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_SR;
break;
2014-07-18 13:35:43 +00:00
case kHeroDirUp:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_SU;
break;
2014-07-18 13:35:43 +00:00
case kHeroDirDown:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_SD;
break;
}
break;
case TURN:
if (_destDirection) {
if (_lastDirection == _destDirection) {
_state = STAY;
} else {
_phase = 0;
int rotateDir = rotateHero(_lastDirection, _destDirection);
_lastDirection = _destDirection;
if (rotateDir) {
_turnAnim = rotateDir;
_state = TRAN;
} else {
_state = STAY;
}
}
} else {
_state = STAY;
}
break;
case MOVE:
2014-07-18 13:35:43 +00:00
int x, y, dir, oldMiddleX, oldMiddleY, dX, dY;
//go_for_it:
while (1) {
if (_currCoords != nullptr) {
if (READ_UINT32(_currCoords) != 0xFFFFFFFF) {
x = READ_UINT16(_currCoords);
y = READ_UINT16(_currCoords + 2);
_currCoords += 4;
dir = *_currDirTab;
_currDirTab++;
if (_lastDirection != dir) {
_phase = 0;
int rotateDir = rotateHero(_lastDirection, dir);
_lastDirection = dir;
if (!rotateDir) {
continue;
} else {
_turnAnim = rotateDir;
_state = MVAN;
break;
}
}
//no_need_direction_change
if (dir == kHeroDirLeft) {
if (_middleX - x >= _step) {
break;
}
} else if (dir == kHeroDirRight) {
if (x - _middleX >= _step) {
break;
}
} else if (dir == kHeroDirUp) {
if (_middleY - y >= _step) {
break;
}
} else if (dir == kHeroDirDown) {
if (y - _middleY >= _step) {
break;
}
}
} else {
//finito
_middleX = READ_UINT16(_currCoords - 4);
_middleY = READ_UINT16(_currCoords - 2);
selectZoom();
2014-07-18 13:35:43 +00:00
free(_coords);
_coords = nullptr;
_currCoords = nullptr;
free(_dirTab);
_dirTab = nullptr;
2014-07-18 13:35:43 +00:00
_currDirTab = nullptr;
_boredomTime = 0;
2014-07-18 13:35:43 +00:00
_phase = 0;
_state = TURN;
if (_destDirection) {
_destDirection = _lastDirection;
}
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;
}
break;
2014-07-18 13:35:43 +00:00
}
} else {
break;
2014-07-18 13:35:43 +00:00
}
}
if (_currCoords != nullptr) {
if (READ_UINT32(_currCoords) != 0xFFFFFFFF) {
oldMiddleX = _middleX;
oldMiddleY = _middleY;
_middleX = x;
_middleY = y;
selectZoom();
// TODO - useful or not?
dX = oldMiddleX - _middleX;
dY = oldMiddleY - _middleY;
if (dX) {
_leftRightMainDir = kHeroDirLeft;
if (dX >= 0) {
_leftRightMainDir = kHeroDirRight;
}
}
if (dY) {
_upDownMainDir = kHeroDirUp;
if (dY >= 0) {
_upDownMainDir = kHeroDirDown;
}
}
2014-07-18 13:35:43 +00:00
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;
}
//TODO - frames here?
if (_moveSet[_moveSetType] != nullptr) {
if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 1) {
if (_vm->_flags->getFlagValue(Flags::HEROFAST) || _state == RUN) {
//_phase += 2;
} else {
//_phase++;
}
} else {
//_phase = 0;
}
} else {
return;
}
_step = kStepLeftRight;
if (_moveSetType == kMove_MU || _moveSetType == kMove_MD) {
_step = kStepUpDown;
}
if (_vm->_flags->getFlagValue(Flags::HEROFAST)) {
_step *= 2.5;
} else if (_state == RUN) {
_step *= 2;
}
}
}
break;
case BORE:
//if (_direction == UP) {
switch (_boreNum) {
case 0:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_BORED1;
break;
case 1:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_BORED2;
break;
}
2014-07-18 13:35:43 +00:00
if (_phase == _moveSet[_moveSetType]->getPhaseCount() - 1) {
_boreNum = _vm->_randomSource.getRandomNumber(1); // rand one of two 'bored' animation
2014-07-18 13:35:43 +00:00
_lastDirection = kHeroDirDown;
_state = STAY;
}
break;
case SPEC:
//specialAnim();
break;
case TALK:
2014-07-18 13:35:43 +00:00
if (!_talkTime) {
_state = STAY;
}
switch (_lastDirection) {
2014-07-18 13:35:43 +00:00
case kHeroDirLeft:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_TL;
break;
2014-07-18 13:35:43 +00:00
case kHeroDirRight:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_TR;
break;
2014-07-18 13:35:43 +00:00
case kHeroDirUp:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_TU;
break;
2014-07-18 13:35:43 +00:00
case kHeroDirDown:
2014-06-18 22:05:54 +00:00
_moveSetType = kMove_TD;
break;
}
break;
2014-07-18 13:35:43 +00:00
case MVAN:
if (_moveSet[_turnAnim] != nullptr) {
if (_phase >= _moveSet[_turnAnim]->getPhaseCount() - 1) {
_state = MOVE;
2014-07-18 13:35:43 +00:00
}
} else {
_state = MOVE;
}
break;
case TRAN:
if (_moveSet[_turnAnim] != nullptr) {
if (_phase >= _moveSet[_turnAnim]->getPhaseCount() - 1) {
2014-07-18 13:35:43 +00:00
_state = STAY;
}
} else {
_state = STAY;
2014-07-18 13:35:43 +00:00
}
break;
//case RUN:
//break;
case DMOVE:
2014-07-18 13:35:43 +00:00
_moveDelay--;
if (!_moveDelay) {
_state = MOVE;
}
break;
}
showHeroAnimFrame();
} else {
// no hero visible
return;
}
}
2014-05-04 16:02:53 +00:00
void Hero::scrollHero() {
//FLAGI+SCROLLTYPE ??
//int scrollType = 0;
int position = _middleX;
/*
switch (scrollType) {
case 0:
position = _middleX;
break;
case 1:
break;
case 2:
break;
}
*/
int locationWidth = _vm->_sceneWidth;
int difference = locationWidth - _vm->kNormalWidth / 2;
2014-05-04 16:02:53 +00:00
int destValue = 0;
if (position > _vm->kNormalWidth / 2) {
destValue = difference - _vm->kNormalWidth / 2;
2014-05-04 16:02:53 +00:00
}
if (position < difference) {
destValue = position - _vm->kNormalWidth / 2;
2014-05-04 16:02:53 +00:00
}
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::STAY;
}
void Hero::freeHeroAnim() {
if (_specAnim != nullptr) {
delete _specAnim;
_specAnim = nullptr;
}
}
}
/* vim: set tabstop=4 noexpandtab: */