mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 01:08:25 +00:00
SCUMM: Maniac V0: Implement original walkbox queue, Cleanup actor walk code
This commit is contained in:
parent
1a880c748c
commit
44000ba826
@ -259,6 +259,8 @@ void Actor_v0::initActor(int mode) {
|
||||
_limb_flipped[i] = false;
|
||||
}
|
||||
|
||||
walkBoxQueueReset();
|
||||
|
||||
if (_vm->_game.features & GF_DEMO) {
|
||||
_sound[0] = v0ActorDemoTalk[_number];
|
||||
} else {
|
||||
@ -266,6 +268,116 @@ void Actor_v0::initActor(int mode) {
|
||||
}
|
||||
}
|
||||
|
||||
void Actor_v0::walkBoxQueueReset() {
|
||||
_walkboxHistory.clear();
|
||||
_walkboxQueueIndex = 0;
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE( _walkboxQueue ); ++i) {
|
||||
_walkboxQueue[i] = kInvalidBox;
|
||||
}
|
||||
}
|
||||
|
||||
bool Actor_v0::walkBoxQueueAdd(int box) {
|
||||
|
||||
if (_walkboxQueueIndex == ARRAYSIZE( _walkboxQueue ))
|
||||
return false;
|
||||
|
||||
_walkboxQueue[_walkboxQueueIndex++] = box ;
|
||||
_walkboxHistory.push_back( box );
|
||||
return true;
|
||||
}
|
||||
|
||||
void Actor_v0::walkboxQueueReverse() {
|
||||
int j = ARRAYSIZE( _walkboxQueue ) - 1;
|
||||
|
||||
while (_walkboxQueue[j] == kInvalidBox && j >= 1)
|
||||
--j;
|
||||
|
||||
if (j <= 1)
|
||||
return;
|
||||
|
||||
for (int i = 1; i < j && j >= 1 ; ++i, --j) {
|
||||
|
||||
byte tmp = _walkboxQueue[i];
|
||||
|
||||
_walkboxQueue[i] = _walkboxQueue[j];
|
||||
_walkboxQueue[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
bool Actor_v0::walkBoxQueueFind(int box) {
|
||||
|
||||
for (uint i = 0; i < _walkboxHistory.size(); ++i) {
|
||||
if (box == _walkboxHistory[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Actor_v0::walkBoxQueuePrepare() {
|
||||
walkBoxQueueReset();
|
||||
int BoxFound = _walkbox;
|
||||
|
||||
if (BoxFound == _walkdata.destbox) {
|
||||
|
||||
_newWalkBoxEntered = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Build a series of walkboxes from our current position, to the target
|
||||
do {
|
||||
// Add the current box to the queue
|
||||
if (!walkBoxQueueAdd( BoxFound ))
|
||||
return false;
|
||||
|
||||
// Loop until we find a walkbox which hasn't been tested
|
||||
while (_walkboxQueueIndex > 0) {
|
||||
|
||||
// Check if the dest box is a direct neighbour
|
||||
if ((BoxFound = _vm->getNextBox( BoxFound, _walkdata.destbox )) == kInvalidBox) {
|
||||
|
||||
// Its not, start hunting through this boxes immediate connections
|
||||
byte* boxm = _vm->getBoxConnectionBase( _walkboxQueue[_walkboxQueueIndex - 1] );
|
||||
|
||||
// Attempt to find one, which we havn't already used
|
||||
for (; *boxm != kInvalidBox; ++boxm) {
|
||||
if (walkBoxQueueFind( *boxm ) != true)
|
||||
break;
|
||||
}
|
||||
|
||||
BoxFound = *boxm;
|
||||
}
|
||||
|
||||
// Found one?
|
||||
if (BoxFound != kInvalidBox) {
|
||||
|
||||
// Did we find a connection to the final walkbox
|
||||
if (BoxFound == _walkdata.destbox) {
|
||||
|
||||
_newWalkBoxEntered = true;
|
||||
|
||||
walkBoxQueueAdd( BoxFound );
|
||||
|
||||
walkboxQueueReverse();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nope, check the next box
|
||||
break;
|
||||
}
|
||||
|
||||
// Drop this box, its useless to us
|
||||
_walkboxQueue[--_walkboxQueueIndex] = kInvalidBox;
|
||||
|
||||
BoxFound = _walkboxQueue[_walkboxQueueIndex - 1];
|
||||
}
|
||||
|
||||
} while (_walkboxQueueIndex > 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Actor::setBox(int box) {
|
||||
_walkbox = box;
|
||||
setupActorScale();
|
||||
@ -634,17 +746,18 @@ void Actor::startWalkActor(int destX, int destY, int dir) {
|
||||
_walkdata.dest.y = abr.y;
|
||||
_walkdata.destbox = abr.box;
|
||||
_walkdata.destdir = dir;
|
||||
|
||||
_walkdata.point3.x = 32000;
|
||||
_walkdata.curbox = _walkbox;
|
||||
|
||||
if (_vm->_game.version == 0) {
|
||||
((Actor_v0*)this)->_newWalkBoxEntered = true;
|
||||
((Actor_v0*)this)->walkBoxQueuePrepare();
|
||||
|
||||
} else if (_vm->_game.version <= 2) {
|
||||
_moving = (_moving & ~(MF_LAST_LEG | MF_IN_LEG)) | MF_NEW_LEG;
|
||||
} else {
|
||||
_moving = (_moving & MF_IN_LEG) | MF_NEW_LEG;
|
||||
}
|
||||
|
||||
_walkdata.point3.x = 32000;
|
||||
_walkdata.curbox = _walkbox;
|
||||
}
|
||||
|
||||
void Actor::startWalkAnim(int cmd, int angle) {
|
||||
@ -861,13 +974,7 @@ L2C36:;
|
||||
stopActorMoving();
|
||||
return;
|
||||
}
|
||||
// 2C98: Yes, an exact copy of what just occurred.. the original does this, so im doing it...
|
||||
// Just to keep me sane when going over it :)
|
||||
if (A == 0xFF) {
|
||||
setActorFromTmp();
|
||||
stopActorMoving();
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1398,13 +1505,13 @@ void Actor::putActor(int dstX, int dstY, int newRoom) {
|
||||
showActor();
|
||||
}
|
||||
|
||||
// V0 always sets the actor to face the camera upon entering a room
|
||||
if (_vm->_game.version == 0) {
|
||||
_walkdata.dest = _pos;
|
||||
|
||||
((Actor_v0*)this)->_newWalkBoxEntered = true;
|
||||
((Actor_v0*)this)->_newWalkBoxEntered = false;
|
||||
((Actor_v0*)this)->_CurrentWalkTo = _pos;
|
||||
((Actor_v0*)this)->_NewWalkTo = _pos;
|
||||
|
||||
// V0 always sets the actor to face the camera upon entering a room
|
||||
setDirection(oldDirToNewDir(2));
|
||||
}
|
||||
}
|
||||
@ -1549,7 +1656,7 @@ AdjustBoxResult Actor_v0::adjustPosInBorderWalkbox(AdjustBoxResult box) {
|
||||
if (A < box.x)
|
||||
return box;
|
||||
|
||||
if (A < 0xA0 || A == 0xA0)
|
||||
if (A <= 0xA0)
|
||||
A = 0;
|
||||
|
||||
Result.x = A;
|
||||
@ -1980,9 +2087,10 @@ void ScummEngine::processActors() {
|
||||
if (_game.version == 0) {
|
||||
// 0x057B
|
||||
Actor_v0 *a0 = (Actor_v0*) a;
|
||||
if (a0->_speaking & 1)
|
||||
if (a0->_speaking & 1) {
|
||||
a0->_speaking ^= 0xFE;
|
||||
|
||||
++_V0Delay._actorRedrawCount;
|
||||
}
|
||||
// 0x22B5
|
||||
if (a0->_miscflags & kActorMiscFlagHide)
|
||||
continue;
|
||||
@ -2404,8 +2512,13 @@ void Actor_v0::limbFrameCheck(int limb) {
|
||||
void Actor_v0::animateCostume() {
|
||||
speakCheck();
|
||||
|
||||
if (_vm->_costumeLoader->increaseAnims(this))
|
||||
byte count = _vm->_costumeLoader->increaseAnims( this );
|
||||
|
||||
if (count) {
|
||||
_vm->_V0Delay._actorLimbRedrawDrawCount += count;
|
||||
|
||||
_needRedraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Actor_v0::speakCheck() {
|
||||
@ -3254,7 +3367,7 @@ void Actor_v0::animateActor(int anim) {
|
||||
|
||||
} else {
|
||||
|
||||
if (anim > 4 && anim <= 7)
|
||||
if (anim >= 4 && anim <= 7)
|
||||
_facing = normalizeAngle(oldDirToNewDir(dir));
|
||||
}
|
||||
}
|
||||
@ -3311,7 +3424,7 @@ void Actor_v0::setActorFromTmp() {
|
||||
}
|
||||
|
||||
void Actor_v0::actorSetWalkTo() {
|
||||
|
||||
|
||||
if (_newWalkBoxEntered == false)
|
||||
return;
|
||||
|
||||
@ -3350,10 +3463,33 @@ void Actor_v0::saveLoadWithSerializer(Serializer *ser) {
|
||||
MKLINE(Actor_v0, _walkYCount, sleByte, VER(97)),
|
||||
MKLINE(Actor_v0, _walkYCountInc, sleByte, VER(97)),
|
||||
MKLINE(Actor_v0, _walkMaxXYCountInc, sleByte, VER(97)),
|
||||
|
||||
MKARRAY(Actor_v0, _walkboxQueue[0], sleByte, 16, VER(98)),
|
||||
MKLINE(Actor_v0, _walkboxQueueIndex, sleByte, VER(98)),
|
||||
MKEND()
|
||||
};
|
||||
|
||||
ser->saveLoadEntries(this, actorEntries);
|
||||
|
||||
if (ser->isLoading()) {
|
||||
if (_costCommand != 0xFF ) {
|
||||
|
||||
if (_walkboxQueueIndex < 1) {
|
||||
|
||||
_costCommand = 0xFF;
|
||||
setDirection( _facing );
|
||||
speakCheck();
|
||||
}
|
||||
else {
|
||||
//_costCommandNew = _costCommand;
|
||||
//_costCommand = 0xFF;
|
||||
//animateActor( _costCommandNew );
|
||||
_facing = 0;
|
||||
directionUpdate();
|
||||
animateActor( newDirToOldDir( _facing ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Actor::saveLoadWithSerializer(Serializer *ser) {
|
||||
@ -3496,6 +3632,8 @@ void Actor::saveLoadWithSerializer(Serializer *ser) {
|
||||
_walkdata.point3.x >>= V12_X_SHIFT;
|
||||
_walkdata.point3.y >>= V12_Y_SHIFT;
|
||||
}
|
||||
|
||||
setDirection( _facing );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,6 +350,11 @@ class Actor_v0 : public Actor_v2 {
|
||||
public:
|
||||
Common::Point _CurrentWalkTo, _NewWalkTo;
|
||||
|
||||
Common::Array<byte> _walkboxHistory;
|
||||
|
||||
byte _walkboxQueue[0x10];
|
||||
byte _walkboxQueueIndex;
|
||||
|
||||
byte _costCommandNew;
|
||||
byte _costCommand;
|
||||
byte _miscflags;
|
||||
@ -380,6 +385,12 @@ public:
|
||||
|
||||
bool _limb_flipped[8];
|
||||
|
||||
private:
|
||||
|
||||
bool walkBoxQueueAdd( int box );
|
||||
bool walkBoxQueueFind( int box );
|
||||
void walkboxQueueReverse();
|
||||
|
||||
public:
|
||||
Actor_v0(ScummEngine *scumm, int id) : Actor_v2(scumm, id) {}
|
||||
|
||||
@ -401,6 +412,9 @@ public:
|
||||
byte actorWalkY();
|
||||
byte updateWalkbox();
|
||||
|
||||
void walkBoxQueueReset();
|
||||
bool walkBoxQueuePrepare();
|
||||
|
||||
AdjustBoxResult adjustXYToBeInBox(int dstX, int dstY);
|
||||
AdjustBoxResult adjustPosInBorderWalkbox(AdjustBoxResult box);
|
||||
|
||||
|
@ -692,6 +692,22 @@ byte *ScummEngine::getBoxMatrixBaseAddr() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
byte *ScummEngine::getBoxConnectionBase( int box ) {
|
||||
byte *boxm = getBoxMatrixBaseAddr();
|
||||
|
||||
int boxIndex = 0;
|
||||
|
||||
for (; boxIndex != box; ++boxIndex) {
|
||||
|
||||
while ( *boxm != 0xFF) {
|
||||
++boxm;
|
||||
}
|
||||
|
||||
++boxm;
|
||||
}
|
||||
|
||||
return boxm;
|
||||
}
|
||||
/**
|
||||
* Compute if there is a way that connects box 'from' with box 'to'.
|
||||
* Returns the number of a box adjacent to 'from' that is the next on the
|
||||
@ -719,21 +735,18 @@ int ScummEngine::getNextBox(byte from, byte to) {
|
||||
boxm = getBoxMatrixBaseAddr();
|
||||
|
||||
if (_game.version == 0) {
|
||||
// calculate shortest paths
|
||||
byte *itineraryMatrix = (byte *)malloc(numOfBoxes * numOfBoxes);
|
||||
calcItineraryMatrix(itineraryMatrix, numOfBoxes);
|
||||
|
||||
dest = to;
|
||||
do {
|
||||
dest = itineraryMatrix[numOfBoxes * from + dest];
|
||||
} while (dest != Actor::kInvalidBox && !areBoxesNeighbors(from, dest));
|
||||
boxm = getBoxConnectionBase( from );
|
||||
|
||||
if (dest == Actor::kInvalidBox)
|
||||
dest = -1;
|
||||
for (; *boxm != 0xFF; ++boxm) {
|
||||
if (*boxm == to)
|
||||
break;
|
||||
}
|
||||
|
||||
free(itineraryMatrix);
|
||||
return dest;
|
||||
} else if (_game.version <= 2) {
|
||||
return *boxm;
|
||||
|
||||
}
|
||||
else if (_game.version <= 2) {
|
||||
// The v2 box matrix is a real matrix with numOfBoxes rows and columns.
|
||||
// The first numOfBoxes bytes contain indices to the start of the corresponding
|
||||
// row (although that seems unnecessary to me - the value is easily computable.
|
||||
@ -967,6 +980,7 @@ void ScummEngine::calcItineraryMatrix(byte *itineraryMatrix, int num) {
|
||||
// 255 (= infinity) to all other boxes.
|
||||
for (i = 0; i < num; i++) {
|
||||
for (j = 0; j < num; j++) {
|
||||
|
||||
if (i == j) {
|
||||
adjacentMatrix[i * boxSize + j] = 0;
|
||||
itineraryMatrix[i * boxSize + j] = j;
|
||||
@ -1160,20 +1174,31 @@ bool ScummEngine::areBoxesNeighbors(int box1nr, int box2nr) {
|
||||
|
||||
byte ScummEngine_v0::walkboxFindTarget(Actor *a, int destbox, Common::Point walkdest) {
|
||||
Actor_v0 *Actor = (Actor_v0*)a;
|
||||
byte nextBox = kOldInvalidBox;
|
||||
|
||||
byte nextBox = getNextBox(a->_walkbox, destbox);
|
||||
// Do we have a walkbox queue to process
|
||||
if (Actor->_walkboxQueueIndex > 1) {
|
||||
nextBox = Actor->_walkboxQueue[--Actor->_walkboxQueueIndex];
|
||||
|
||||
if (nextBox != 0xFF && nextBox == destbox && areBoxesNeighbors(a->_walkbox, nextBox)) {
|
||||
if (Actor->_walkboxQueueIndex <= 1) {
|
||||
Actor->walkBoxQueueReset();
|
||||
}
|
||||
}
|
||||
|
||||
// Target box reached?
|
||||
if (nextBox != Actor::kInvalidBox && nextBox == destbox && areBoxesNeighbors(a->_walkbox, nextBox)) {
|
||||
|
||||
Actor->_NewWalkTo = walkdest;
|
||||
return nextBox;
|
||||
}
|
||||
|
||||
if (nextBox != 0xFF && nextBox != a->_walkbox) {
|
||||
// Next box reached
|
||||
if (nextBox != Actor::kInvalidBox && nextBox != a->_walkbox) {
|
||||
|
||||
getClosestPtOnBox(getBoxCoordinates(nextBox), a->getPos().x, a->getPos().y, Actor->_NewWalkTo.x, Actor->_NewWalkTo.y);
|
||||
|
||||
} else {
|
||||
|
||||
if (walkdest.x == -1)
|
||||
Actor->_NewWalkTo = Actor->_CurrentWalkTo;
|
||||
else
|
||||
|
@ -47,7 +47,7 @@ namespace Scumm {
|
||||
* only saves/loads those which are valid for the version of the savegame
|
||||
* which is being loaded/saved currently.
|
||||
*/
|
||||
#define CURRENT_VER 97
|
||||
#define CURRENT_VER 98
|
||||
|
||||
/**
|
||||
* An auxillary macro, used to specify savegame versions. We use this instead
|
||||
|
@ -1131,6 +1131,8 @@ public:
|
||||
|
||||
byte getNumBoxes();
|
||||
byte *getBoxMatrixBaseAddr();
|
||||
byte *getBoxConnectionBase( int box );
|
||||
|
||||
int getNextBox(byte from, byte to);
|
||||
|
||||
void setBoxFlags(int box, int val);
|
||||
|
Loading…
Reference in New Issue
Block a user