From 86f6aaf206fadd6970b300c953a525804d7d84df Mon Sep 17 00:00:00 2001 From: Andrew Kurushin Date: Sat, 9 Jun 2007 22:45:03 +0000 Subject: fix IHNM protagonist state loading routine. now Ellen's animations are showing well svn-id: r27263 --- engines/saga/actor.cpp | 230 ++++++++++++++++++++++++++++++++++++++----------- engines/saga/actor.h | 14 ++- 2 files changed, 190 insertions(+), 54 deletions(-) diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp index 32311da03d..1ba881f565 100644 --- a/engines/saga/actor.cpp +++ b/engines/saga/actor.cpp @@ -243,7 +243,7 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { _debugPointsAlloced = _debugPointsCount = 0; #endif - _protagStates = 0; + _protagStates = NULL; _protagStatesCount = 0; _pathNodeList = _newPathNodeList = NULL; @@ -356,52 +356,65 @@ Actor::~Actor() { free(_pathCell); _actorsStrings.freeMem(); //release resources + freeProtagStates(); freeActorList(); freeObjList(); } -bool Actor::loadActorResources(ActorData *actor) { +void Actor::freeProtagStates() { + int i; + for (i = 0; i < _protagStatesCount; i++) { + free(_protagStates[i]._frames); + } + free(_protagStates); + _protagStates = NULL; + _protagStatesCount = 0; +} + +void Actor::loadFrameList(int frameListResourceId, ActorFrameSequence *&framesPointer, int &framesCount) { byte *resourcePointer; size_t resourceLength; - int framesCount; - ActorFrameSequence *framesPointer; - bool gotSomething = false; - if (actor->_frameListResourceId) { - debug(9, "Loading frame resource id %d", actor->_frameListResourceId); - _vm->_resource->loadResource(_actorContext, actor->_frameListResourceId, resourcePointer, resourceLength); + debug(9, "Loading frame resource id %d", frameListResourceId); + _vm->_resource->loadResource(_actorContext, frameListResourceId, resourcePointer, resourceLength); - framesCount = resourceLength / 16; - debug(9, "Frame resource contains %d frames (res length is %d)", framesCount, (int)resourceLength); + framesCount = resourceLength / 16; + debug(9, "Frame resource contains %d frames (res length is %d)", framesCount, (int)resourceLength); - framesPointer = (ActorFrameSequence *)malloc(sizeof(ActorFrameSequence) * framesCount); - if (framesPointer == NULL && framesCount != 0) { - memoryError("Actor::loadActorResources"); - } + framesPointer = (ActorFrameSequence *)malloc(sizeof(ActorFrameSequence) * framesCount); + if (framesPointer == NULL && framesCount != 0) { + memoryError("Actor::loadFrameList"); + } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian); + MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian); - for (int i = 0; i < framesCount; i++) { - debug(9, "frameType %d", i); - for (int orient = 0; orient < ACTOR_DIRECTIONS_COUNT; orient++) { - // Load all four orientations - framesPointer[i].directions[orient].frameIndex = readS.readUint16(); - if (_vm->getGameType() == GType_ITE) { - framesPointer[i].directions[orient].frameCount = readS.readSint16(); - } else { - framesPointer[i].directions[orient].frameCount = readS.readByte(); - readS.readByte(); - } - if (framesPointer[i].directions[orient].frameCount < 0) - warning("frameCount < 0 (%d)", framesPointer[i].directions[orient].frameCount); - debug(9, "frameIndex %d frameCount %d", framesPointer[i].directions[orient].frameIndex, framesPointer[i].directions[orient].frameCount); + for (int i = 0; i < framesCount; i++) { + debug(9, "frameType %d", i); + for (int orient = 0; orient < ACTOR_DIRECTIONS_COUNT; orient++) { + // Load all four orientations + framesPointer[i].directions[orient].frameIndex = readS.readUint16(); + if (_vm->getGameType() == GType_ITE) { + framesPointer[i].directions[orient].frameCount = readS.readSint16(); + } else { + framesPointer[i].directions[orient].frameCount = readS.readByte(); + readS.readByte(); } + if (framesPointer[i].directions[orient].frameCount < 0) + warning("frameCount < 0 (%d)", framesPointer[i].directions[orient].frameCount); + debug(9, "frameIndex %d frameCount %d", framesPointer[i].directions[orient].frameIndex, framesPointer[i].directions[orient].frameCount); } + } + + free(resourcePointer); +} + +bool Actor::loadActorResources(ActorData *actor) { + bool gotSomething = false; - free(resourcePointer); + if (actor->_frameListResourceId) { + loadFrameList(actor->_frameListResourceId, actor->_frames, actor->_framesCount); - actor->_frames = framesPointer; - actor->_framesCount = framesCount; + actor->_shareFrames = false; gotSomething = true; } else { @@ -470,6 +483,7 @@ void Actor::loadActorList(int protagonistIdx, int actorCount, int actorsResource int movementSpeed; int walkStepIndex; int walkStepCount; + int stateResourceId; freeActorList(); @@ -567,28 +581,34 @@ void Actor::loadActorList(int protagonistIdx, int actorCount, int actorsResource _protagState = 0; if (protagStatesResourceID) { - free(_protagStates); + if (!_protagonist->_shareFrames) + free(_protagonist->_frames); + freeProtagStates(); - _protagStates = (ActorFrameSequence *)malloc(sizeof(ActorFrameSequence) * protagStatesCount); + _protagStates = (ProtagStateData *)malloc(sizeof(ProtagStateData) * protagStatesCount); - byte *resourcePointer; - size_t resourceLength; + byte *idsResourcePointer; + size_t idsResourceLength; _vm->_resource->loadResource(_actorContext, protagStatesResourceID, - resourcePointer, resourceLength); + idsResourcePointer, idsResourceLength); + if (idsResourceLength < (size_t)protagStatesCount * 4) { + error("Wrong protagonist states resource"); + } - MemoryReadStream statesS(resourcePointer, resourceLength); + MemoryReadStream statesIds(idsResourcePointer, idsResourceLength); for (i = 0; i < protagStatesCount; i++) { - for (j = 0; j < ACTOR_DIRECTIONS_COUNT; j++) { - _protagStates[i].directions[j].frameIndex = statesS.readUint16LE(); - _protagStates[i].directions[j].frameCount = statesS.readUint16LE(); - } + stateResourceId = statesIds.readUint32LE(); + + loadFrameList(stateResourceId, _protagStates[i]._frames, _protagStates[i]._framesCount); } - free(resourcePointer); + free(idsResourcePointer); - _protagonist->_frames = &_protagStates[_protagState]; + _protagonist->_frames = _protagStates[_protagState]._frames; + _protagonist->_framesCount = _protagStates[_protagState]._framesCount; + _protagonist->_shareFrames = true; } _protagStatesCount = protagStatesCount; @@ -823,8 +843,14 @@ bool Actor::validFollowerLocation(const Location &location) { void Actor::setProtagState(int state) { _protagState = state; - if (_vm->getGameType() == GType_IHNM) - _protagonist->_frames = &_protagStates[state]; + if (_vm->getGameType() == GType_IHNM) { + if (!_protagonist->_shareFrames) + free(_protagonist->_frames); + + _protagonist->_frames = _protagStates[state]._frames; + _protagonist->_framesCount = _protagStates[state]._framesCount; + _protagonist->_shareFrames = true; + } } void Actor::updateActorsScene(int actorsEntrance) { @@ -1024,19 +1050,117 @@ ActorFrameRange *Actor::getActorFrameRange(uint16 actorId, int frameType) { if ((actor->_facingDirection < kDirUp) || (actor->_facingDirection > kDirUpLeft)) error("Actor::getActorFrameRange Wrong direction 0x%X actorId 0x%X", actor->_facingDirection, actorId); - if (frameType >= actor->_framesCount) { + if (_vm->getGameType() == GType_ITE) { + if (frameType >= actor->_framesCount) { + warning("Actor::getActorFrameRange Wrong frameType 0x%X (%d) actorId 0x%X", frameType, actor->_framesCount, actorId); + return &def; + } + + + fourDirection = actorDirectectionsLUT[actor->_facingDirection]; + return &actor->_frames[frameType].directions[fourDirection]; + } + + if (_vm->getGameType() == GType_IHNM) { // It is normal for some actors to have no frames for a given frameType // These are mainly actors with no frames at all (e.g. narrators or immovable actors) // Examples are AM and the boy when he is talking to Benny via the computer screen. // Both of them are invisible and immovable // There is no point to keep throwing warnings about this, the original checks for // a valid framecount too - //warning("Actor::getActorFrameRange Wrong frameType 0x%X (%d) actorId 0x%X", frameType, actor->_framesCount, actorId); - return &def; + if (0 == actor->_framesCount) { + return &def; + } + if (frameType >= actor->_framesCount) { + frameType = actor->_framesCount - 1; + } + if (frameType < 0) { + frameType = 0; + } + + fourDirection = actorDirectectionsLUT[actor->_facingDirection]; + return &actor->_frames[frameType].directions[fourDirection]; } + return NULL; + /* + } else { + if (0 == actor->_framesCount) { + return &def; + } + + //TEST + if (actor->_id == 0x2000) { + if (actor->_framesCount <= _currentFrameIndex) { + _currentFrameIndex = 0; + } + fr = actor->_frames[_currentFrameIndex].directions; + return fr; + } + //TEST + if (frameType >= actor->_framesCount) { + frameType = actor->_framesCount - 1; + } + if (frameType < 0) { + frameType = 0; + } - fourDirection = actorDirectectionsLUT[actor->_facingDirection]; - return &actor->_frames[frameType].directions[fourDirection]; + if (frameType == kFrameIHNMWalk ) { + switch (actor->_facingDirection) { + case kDirUpRight: + if (frameType > 0) + fr = &actor->_frames[frameType - 1].directions[ACTOR_DIRECTION_RIGHT]; + else + fr = &def; + if (!fr->frameCount) + fr = &actor->_frames[frameType].directions[ACTOR_DIRECTION_RIGHT]; + break; + case kDirDownRight: + if (frameType > 0) + fr = &actor->_frames[frameType - 1].directions[ACTOR_DIRECTION_FORWARD]; + else + fr = &def; + if (!fr->frameCount) + fr = &actor->_frames[frameType].directions[ACTOR_DIRECTION_RIGHT]; + break; + case kDirUpLeft: + if (frameType > 0) + fr = &actor->_frames[frameType - 1].directions[ACTOR_DIRECTION_LEFT]; + else + fr = &def; + if (!fr->frameCount) + fr = &actor->_frames[frameType].directions[ACTOR_DIRECTION_LEFT]; + break; + case kDirDownLeft: + if (frameType > 0) + fr = &actor->_frames[frameType - 1].directions[ACTOR_DIRECTION_BACK]; + else + fr = &def; + if (!fr->frameCount) + fr = &actor->_frames[frameType].directions[ACTOR_DIRECTION_LEFT]; + break; + case kDirRight: + fr = &actor->_frames[frameType].directions[ACTOR_DIRECTION_RIGHT]; + break; + case kDirLeft: + fr = &actor->_frames[frameType].directions[ACTOR_DIRECTION_LEFT]; + break; + case kDirUp: + fr = &actor->_frames[frameType].directions[ACTOR_DIRECTION_BACK]; + break; + case kDirDown: + fr = &actor->_frames[frameType].directions[ACTOR_DIRECTION_FORWARD]; + break; + } + return fr; + } + else { + if (frameType >= actor->_framesCount) { + error("Actor::getActorFrameRange Wrong frameType 0x%X (%d) actorId 0x%X", frameType, actor->_framesCount, actorId); + } + fourDirection = actorDirectectionsLUT[actor->_facingDirection]; + return &actor->_frames[frameType].directions[fourDirection]; + } + }*/ } void Actor::handleSpeech(int msec) { @@ -1709,6 +1833,10 @@ bool Actor::getSpriteParams(CommonObjectData *commonObjectData, int &frameNumber frameNumber = commonObjectData->_spriteListResourceId; } + if (spriteList->spriteCount == 0) { + return false; + } + if ((frameNumber < 0) || (spriteList->spriteCount <= frameNumber)) { debug(1, "Actor::getSpriteParams frameNumber invalid for %s id 0x%X (%d)", validObjId(commonObjectData->_id) ? "object" : "actor", diff --git a/engines/saga/actor.h b/engines/saga/actor.h index d4d7a0957d..3296246cba 100644 --- a/engines/saga/actor.h +++ b/engines/saga/actor.h @@ -303,6 +303,7 @@ public: //constant SpriteList _spriteList; // sprite list data + bool _shareFrames; ActorFrameSequence *_frames; // Actor's frames int _framesCount; // Actor's frames count int _frameListResourceId; // Actor's frame list resource id @@ -474,13 +475,18 @@ public: memset(this, 0, sizeof(*this)); } ~ActorData() { - free(_frames); + if (!_shareFrames) + free(_frames); free(_tileDirections); free(_walkStepsPoints); freeSpriteList(); } }; +struct ProtagStateData { + ActorFrameSequence *_frames; // Actor's frames + int _framesCount; // Actor's frames count +}; struct SpeechData { @@ -592,6 +598,8 @@ public: void setProtagState(int state); int getProtagState() { return _protagState; } + void freeProtagStates(); + void freeActorList(); void loadActorList(int protagonistIdx, int actorCount, int actorsResourceID, int protagStatesCount, int protagStatesResourceID); @@ -606,7 +614,7 @@ public: protected: friend class Script; bool loadActorResources(ActorData *actor); - + void loadFrameList(int frameListResourceId, ActorFrameSequence *&framesPointer, int &framesCount); private: void stepZoneAction(ActorData *actor, const HitZone *hitZone, bool exit, bool stopped); void loadActorSpriteList(ActorData *actor); @@ -682,7 +690,7 @@ protected: bool _dragonHunt; private: - ActorFrameSequence *_protagStates; + ProtagStateData *_protagStates; int _protagStatesCount; //path stuff -- cgit v1.2.3