diff options
-rw-r--r-- | engines/mutationofjb/commands/changecommand.cpp | 28 | ||||
-rw-r--r-- | engines/mutationofjb/debug.cpp | 30 | ||||
-rw-r--r-- | engines/mutationofjb/gamedata.cpp | 32 | ||||
-rw-r--r-- | engines/mutationofjb/gamedata.h | 219 | ||||
-rw-r--r-- | engines/mutationofjb/room.cpp | 14 | ||||
-rw-r--r-- | engines/mutationofjb/tasks/objectanimationtask.cpp | 34 | ||||
-rw-r--r-- | engines/mutationofjb/tasks/saytask.cpp | 10 |
7 files changed, 247 insertions, 120 deletions
diff --git a/engines/mutationofjb/commands/changecommand.cpp b/engines/mutationofjb/commands/changecommand.cpp index a2d45260f5..d7a8f9ca4b 100644 --- a/engines/mutationofjb/commands/changecommand.cpp +++ b/engines/mutationofjb/commands/changecommand.cpp @@ -381,22 +381,22 @@ Command::ExecuteResult ChangeObjectCommand::execute(ScriptExecutionContext &scri switch (_register) { case AC: - object->_AC = _value._byteVal; + object->_active = _value._byteVal; break; case FA: - object->_FA = _value._byteVal; + object->_firstFrame = _value._byteVal; break; case FR: - object->_FR = _value._byteVal; + object->_randomFrame = _value._byteVal; break; case NA: - object->_NA = _value._byteVal; + object->_numFrames = _value._byteVal; break; case FS: - object->_FS = _value._byteVal; + object->_roomFrameLSB = _value._byteVal; break; case CA: - object->_CA = _value._byteVal; + object->_currentFrame = _value._byteVal; break; case XX: object->_x = _value._wordVal; @@ -405,16 +405,16 @@ Command::ExecuteResult ChangeObjectCommand::execute(ScriptExecutionContext &scri object->_y = _value._byteVal; break; case XL: - object->_XL = _value._wordVal; + object->_width = _value._wordVal; break; case YL: - object->_YL = _value._byteVal; + object->_height = _value._byteVal; break; case WX: object->_WX = _value._wordVal; break; case WY: - object->_WY = _value._byteVal; + object->_roomFrameMSB = _value._byteVal; break; case SP: object->_SP = _value._byteVal; @@ -468,7 +468,7 @@ Command::ExecuteResult ChangeStaticCommand::execute(ScriptExecutionContext &scri stat->_walkToY = _value._byteVal; break; case SP: - stat->_SP = _value._byteVal; + stat->_walkToFrame = _value._byteVal; break; default: warning("Object does not support changing this register."); @@ -493,7 +493,7 @@ Command::ExecuteResult ChangeSceneCommand::execute(ScriptExecutionContext &scrip scene->_startup = _value._byteVal; break; case DL: - scene->_DL = _value._byteVal; + scene->_delay = _value._byteVal; break; case ND: scene->_noDoors = _value._byteVal; @@ -505,13 +505,13 @@ Command::ExecuteResult ChangeSceneCommand::execute(ScriptExecutionContext &scrip scene->_noStatics = _value._byteVal; break; case PF: - scene->_palRotStart = _value._byteVal; + scene->_palRotFirst = _value._byteVal; break; case PL: - scene->_palRotEnd = _value._byteVal; + scene->_palRotLast = _value._byteVal; break; case PD: - scene->_palRotPeriod = _value._byteVal; + scene->_palRotDelay = _value._byteVal; break; default: warning("Scene does not support changing this register."); diff --git a/engines/mutationofjb/debug.cpp b/engines/mutationofjb/debug.cpp index b1c96efd3a..b4f00c9da3 100644 --- a/engines/mutationofjb/debug.cpp +++ b/engines/mutationofjb/debug.cpp @@ -318,14 +318,14 @@ bool Console::cmd_dumpsceneinfo(int argc, const char **argv) { Scene *scene = _vm->getGame().getGameData().getScene(sceneId); if (scene) { debugPrintf("Startup: %u\n", (unsigned int) scene->_startup); - debugPrintf("Delay: %u\n", (unsigned int) scene->_DL); + debugPrintf("Delay: %u\n", (unsigned int) scene->_delay); debugPrintf("Doors: %u\n", (unsigned int) scene->_noDoors); debugPrintf("Objects: %u\n", (unsigned int) scene->_noObjects); debugPrintf("Statics: %u\n", (unsigned int) scene->_noStatics); debugPrintf("ObstacleY1: %u\n", (unsigned int) scene->_obstacleY1); - debugPrintf("PalRotStart: %u\n", (unsigned int) scene->_palRotStart); - debugPrintf("PalRotEnd: %u\n", (unsigned int) scene->_palRotEnd); - debugPrintf("PalRotPeriod: %u\n", (unsigned int) scene->_palRotPeriod); + debugPrintf("PalRotFirst: %u\n", (unsigned int) scene->_palRotFirst); + debugPrintf("PalRotLast: %u\n", (unsigned int) scene->_palRotLast); + debugPrintf("PalRotDelay: %u\n", (unsigned int) scene->_palRotDelay); } else { debugPrintf(_("Scene %u not found.\n"), (unsigned int) sceneId); } @@ -377,19 +377,19 @@ bool Console::cmd_dumpobjectinfo(int argc, const char **argv) { if (scene) { Object *const object = scene->getObject(objectId); if (object) { - debugPrintf("AC: %u\n", (unsigned int) object->_AC); - debugPrintf("FA: %u\n", (unsigned int) object->_FA); - debugPrintf("FR: %u\n", (unsigned int) object->_FR); - debugPrintf("NA: %u\n", (unsigned int) object->_NA); - debugPrintf("FS: %u\n", (unsigned int) object->_FS); - debugPrintf("Unknown: %u\n", (unsigned int) object->_unknown); - debugPrintf("CA: %u\n", (unsigned int) object->_CA); + debugPrintf("AC: %u\n", (unsigned int) object->_active); + debugPrintf("FA: %u\n", (unsigned int) object->_firstFrame); + debugPrintf("FR: %u\n", (unsigned int) object->_randomFrame); + debugPrintf("NA: %u\n", (unsigned int) object->_numFrames); + debugPrintf("FS: %u\n", (unsigned int) object->_roomFrameLSB); + debugPrintf("Jump chance: %u\n", (unsigned int) object->_jumpChance); + debugPrintf("CA: %u\n", (unsigned int) object->_currentFrame); debugPrintf("X: %u\n", (unsigned int) object->_x); debugPrintf("Y: %u\n", (unsigned int) object->_y); - debugPrintf("XL: %u\n", (unsigned int) object->_XL); - debugPrintf("YL: %u\n", (unsigned int) object->_YL); + debugPrintf("XL: %u\n", (unsigned int) object->_width); + debugPrintf("YL: %u\n", (unsigned int) object->_height); debugPrintf("WX: %u\n", (unsigned int) object->_WX); - debugPrintf("WY: %u\n", (unsigned int) object->_WY); + debugPrintf("WY: %u\n", (unsigned int) object->_roomFrameMSB); debugPrintf("SP: %u\n", (unsigned int) object->_SP); } else { debugPrintf(_("Object %u not found.\n"), (unsigned int) objectId); @@ -421,7 +421,7 @@ bool Console::cmd_dumpstaticinfo(int argc, const char **argv) { debugPrintf("Height: %u\n", (unsigned int) stat->_height); debugPrintf("WalkToX: %u\n", (unsigned int) stat->_walkToY); debugPrintf("WalkToY: %u\n", (unsigned int) stat->_walkToX); - debugPrintf("WalkToFrame: %u\n", (unsigned int) stat->_SP); + debugPrintf("WalkToFrame: %u\n", (unsigned int) stat->_walkToFrame); } else { debugPrintf(_("Static %u not found.\n"), (unsigned int) staticId); } diff --git a/engines/mutationofjb/gamedata.cpp b/engines/mutationofjb/gamedata.cpp index 6a9c166106..b6295a7b04 100644 --- a/engines/mutationofjb/gamedata.cpp +++ b/engines/mutationofjb/gamedata.cpp @@ -58,19 +58,19 @@ bool Door::loadFromStream(Common::ReadStream &stream) { } bool Object::loadFromStream(Common::ReadStream &stream) { - _AC = stream.readByte(); - _FA = stream.readByte(); - _FR = stream.readByte(); - _NA = stream.readByte(); - _FS = stream.readByte(); - _unknown = stream.readByte(); - _CA = stream.readByte(); + _active = stream.readByte(); + _firstFrame = stream.readByte(); + _randomFrame = stream.readByte(); + _numFrames = stream.readByte(); + _roomFrameLSB = stream.readByte(); + _jumpChance = stream.readByte(); + _currentFrame = stream.readByte(); _x = stream.readUint16LE(); _y = stream.readByte(); - _XL = stream.readUint16LE(); - _YL = stream.readByte(); + _width = stream.readUint16LE(); + _height = stream.readByte(); _WX = stream.readUint16LE(); - _WY = stream.readByte(); + _roomFrameMSB = stream.readByte(); _SP = stream.readByte(); return true; @@ -85,13 +85,13 @@ bool Static::loadFromStream(Common::ReadStream &stream) { _height = stream.readByte(); _walkToX = stream.readUint16LE(); _walkToY = stream.readByte(); - _SP = stream.readByte(); + _walkToFrame = stream.readByte(); return true; } bool Bitmap::loadFromStream(Common::ReadStream &stream) { - _frame = stream.readByte(); + _roomFrame = stream.readByte(); _isVisible = stream.readByte(); _x1 = stream.readUint16LE(); _y1 = stream.readByte(); @@ -108,7 +108,7 @@ bool Scene::loadFromStream(Common::ReadStream &stream) { _unknown001 = stream.readByte(); _unknown002 = stream.readByte(); _unknown003 = stream.readByte(); - _DL = stream.readByte(); + _delay = stream.readByte(); _noDoors = stream.readByte(); _noDoors = MIN(_noDoors, (uint8) ARRAYSIZE(_doors)); @@ -133,9 +133,9 @@ bool Scene::loadFromStream(Common::ReadStream &stream) { } _obstacleY1 = stream.readUint16LE(); - _palRotStart = stream.readByte(); - _palRotEnd = stream.readByte(); - _palRotPeriod = stream.readByte(); + _palRotFirst = stream.readByte(); + _palRotLast = stream.readByte(); + _palRotDelay = stream.readByte(); _exhaustedChoiceNext = stream.readByte(); for (i = 0; i < 79; ++i) { diff --git a/engines/mutationofjb/gamedata.h b/engines/mutationofjb/gamedata.h index 62c66a1363..99174ee25d 100644 --- a/engines/mutationofjb/gamedata.h +++ b/engines/mutationofjb/gamedata.h @@ -36,40 +36,49 @@ enum { MAX_ENTITY_NAME_LENGTH = 0x14 }; -/* - There are 4 types of entities present in the game data: - - Door - - Object - - Static - - Bitmap -*/ +/** @file gamedata.h + * There are 4 types of entities present in the game data: + * - Door + * - Object + * - Static + * - Bitmap + */ +/** + * An interactable scene changer with no visual representation. + */ struct Door { - /* - Door name. - Can be empty - deactivates door completely. - */ + /** + * Door name (NM register). + * + * Can be empty - deactivates door completely (you can't mouse over or interact with it at all). + * + * If it ends with '+', using the "go" verb on the door will not implicitly change the scene, + * but the player will still walk towards the door. + * + * TODO: Implement the '+' restriction. + */ char _name[MAX_ENTITY_NAME_LENGTH + 1]; - /* - Scene ID where the door leads. - Can be 0 - you can hover your mouse over it, but clicking it doesn't do anything (unless scripted). - */ + /** + * Scene ID where the door leads (LT register). + * Can be 0 - you can hover your mouse over it, but clicking it doesn't do anything (unless scripted). + */ uint8 _destSceneId; - /* X coordinate for player's position after going through the door. */ + /** X coordinate for player's position after going through the door (SX register). */ uint16 _destX; - /* Y coordinate for player's position after going through the door. */ + /** Y coordinate for player's position after going through the door (SY register). */ uint16 _destY; - /* X coordinate of the door rectangle. */ + /** X coordinate of the door rectangle (XX register). */ uint16 _x; - /* Y coordinate of the door rectangle. */ + /** Y coordinate of the door rectangle (YY register). */ uint8 _y; - /* Width of the door rectangle. */ + /** Width of the door rectangle (XL register). */ uint16 _width; - /* Height of the door rectangle. */ + /** Height of the door rectangle (YL register). */ uint8 _height; - /* X coordinate for position towards player will walk after clicking the door. */ + /** X coordinate for position player will walk towards after clicking the door (WX register). */ uint16 _walkToX; - /* Y coordinate for position towards player will walk after clicking the door. */ + /** Y coordinate for position player will walk towards after clicking the door (WY register). */ uint8 _walkToY; /* Unknown for now - likely not even used. */ uint8 _SP; @@ -77,56 +86,148 @@ struct Door { bool loadFromStream(Common::ReadStream &stream); }; +/** + * An animated image in the scene. + * + * Object frames consist of surfaces carved out of room frames (starting from _roomFrame + * up until _roomFrame + _numFrames - 1) based on the object's rectangle. They are stored + * in the shared object frame space that each object occupies a continous part of from + * the beginning. + * + * By using the term "frame" alone we will be referring to an object frame, not a room + * frame. + * + * For details regarding animation playback, see objectanimationtask.cpp. + */ struct Object { - uint8 _AC; - uint8 _FA; - uint8 _FR; - uint8 _NA; - uint8 _FS; - uint8 _unknown; - uint8 _CA; + /** Controls whether the animation is playing. */ + uint8 _active; + /** + * Number of the first frame this object has in the shared object frame space (FA register). + * + * For the first object, it is equal to 1. + * For any subsequent object, it is equal to (_firstFrame + _numFrames) of the previous object. + * + * @note The numbering starts from 1. + * @note Technically this field is useless because it can be calculated. + */ + uint8 _firstFrame; + /** + * The frame that is jumped to randomly based on _jumpChance (FR register). + * + * @note Numbered from 1 and relative to _firstFrame. + * @note A value of 0 disables randomness completely. + * @see objectanimationtask.cpp + * @see _jumpChance + */ + uint8 _randomFrame; + /** Number of animation frames (NA register). */ + uint8 _numFrames; + /** + * Low 8 bits of the 16-bit starting room frame (FS register). + * + * @see _roomFrameMSB + */ + uint8 _roomFrameLSB; + /** + * Chance (1 in x) of the animation jumping to _randomFrame. + * + * @see objectanimationtask.cpp + */ + uint8 _jumpChance; + /** + * Current animation frame (CA register). + * + * @note Absolute index to the frame space. Numbered from 1. + */ + uint8 _currentFrame; + /** X coordinate of the object rectangle (XX register). */ uint16 _x; + /** Y coordinate of the object rectangle (YY register). */ uint8 _y; - uint16 _XL; - uint8 _YL; + /** Width of the object rectangle (XL register). */ + uint16 _width; + /** Height of the object rectangle (YL register). */ + uint8 _height; + /** A general-purpose register for use in scripts. Nothing to do with animation. */ uint16 _WX; - uint8 _WY; + /** + * High 8 bits of the 16-bit starting room frame (WY register). + * + * @see _roomFrameLSB + */ + uint8 _roomFrameMSB; + /* Unknown. TODO: Figure out what this does. */ uint8 _SP; bool loadFromStream(Common::ReadStream &stream); }; +/** + * An interactable area without a visual representation. + */ struct Static { + /** Whether you can mouse over and interact with the static (AC register). */ uint8 _active; + /** + * Static name (NM register). + * + * If it starts with '~', the static has an implicit "pickup" action that adds + * an item with the same name (except '`' replaces '~') to your inventory and + * disables the static. If there is a matching scripted "pickup" action, it + * overrides the implicit action. + * + * TODO: Support '~' statics. + */ char _name[MAX_ENTITY_NAME_LENGTH + 1]; + /** X coordinate of the static rectangle (XX register). */ uint16 _x; + /** Y coordinate of the static rectangle (YY register). */ uint8 _y; + /** Width of the static rectangle (XL register). */ uint16 _width; + /** Height of the static rectangle (YL register). */ uint8 _height; + /** X coordinate of the position the player will walk towards after clicking the static (WX register). */ uint16 _walkToX; + /** Y coordinate of the position the player will walk towards after clicking the static (WY register). */ uint8 _walkToY; - uint8 _SP; + /** Player frame (rotation) set after the player finishes walking towards the walk to position (SP register). */ + uint8 _walkToFrame; bool loadFromStream(Common::ReadStream &stream); }; +/** + * A static image that is carved out of a room frame based on its rectangle. + * The bitmap rectangle also specifies where to blit it on the screen. + */ struct Bitmap { - uint8 _frame; + /** Room frame that this bitmap carves out of. */ + uint8 _roomFrame; + /** Whether to draw the bitmap. */ uint8 _isVisible; + /** X coordinate of the top left corner of the bitmap rectangle. */ uint16 _x1; + /** Y coordinate of the top left corner of the bitmap rectangle. */ uint8 _y1; + /** X coordinate of the bottom right corner of the bitmap rectangle. */ uint16 _x2; + /** Y coordinate of the bottom right corner of the bitmap rectangle. */ uint8 _y2; bool loadFromStream(Common::ReadStream &stream); }; +/** + * Encoded exhausted choice. + */ struct ExhaustedChoice { - /* - 1 bit - context - 3 bits - choice index - 4 bits - choice list index - */ + /** + * 1 bit - context + * 3 bits - choice index + * 4 bits - choice list index + */ uint8 _encodedData; uint8 getContext() const { return (_encodedData >> 7) & 0x1; } @@ -154,29 +255,41 @@ struct Scene { void addExhaustedChoice(uint8 context, uint8 choiceIndex, uint8 choiceIndexList); bool isChoiceExhausted(uint8 context, uint8 choiceIndex, uint8 choiceIndexList) const; + /** Refers to the script block that will be executed when you enter this scene (DS register). */ uint8 _startup; + /** + * These three variables control downscaling of the player character depending on his Y. + * TODO: Find out more. + */ uint8 _unknown001; uint8 _unknown002; uint8 _unknown003; - uint8 _DL; + uint8 _delay; /**< Delay between object animation advancements (DL register). */ + + uint8 _noDoors; /**< Number of doors in the scene (ND register). */ + Door _doors[5]; /**< Door definitions. */ - uint8 _noDoors; - Door _doors[5]; + uint8 _noObjects; /**< Number of animated objects in the scene (NO register). */ + Object _objects[9]; /**< Object definitions. */ - uint8 _noObjects; - Object _objects[9]; + uint8 _noStatics; /**< Number of statics in the scene (NS register). */ + Static _statics[15]; /**< Static definitions. */ - uint8 _noStatics; - Static _statics[15]; + Bitmap _bitmaps[10]; /**< Bitmap definitions. There is no corresponding _noBitmaps field. */ - Bitmap _bitmaps[10]; + uint16 _obstacleY1; /**< Fixed Y coordinate for all static obstacles in the scene. Always 0 in data files. */ - uint16 _obstacleY1; - uint8 _palRotStart; - uint8 _palRotEnd; - uint8 _palRotPeriod; + /** First index (inclusive and 0-indexed) of the rotating portion of the palette (PF register). */ + uint8 _palRotFirst; + /** Last index (inclusive and 0-indexed) of the rotating portion of the palette (PL register). */ + uint8 _palRotLast; + /** Delay between each right rotation of the palette portion (PD register). */ + uint8 _palRotDelay; - /* Points to the first free item in exhausted choices list. */ + /** + * Points to the first free item in exhausted choices list. + * @note Indexed from 1. + */ uint8 _exhaustedChoiceNext; ExhaustedChoice _exhaustedChoices[79]; diff --git a/engines/mutationofjb/room.cpp b/engines/mutationofjb/room.cpp index 009c4bedbf..414a3675ec 100644 --- a/engines/mutationofjb/room.cpp +++ b/engines/mutationofjb/room.cpp @@ -71,12 +71,12 @@ void RoomAnimationDecoderCallback::onFrame(int frameNo, Graphics::Surface &surfa const uint8 noObjects = scene->getNoObjects(); for (int i = 0; i < noObjects; ++i) { Object &object = scene->_objects[i]; - const uint16 startFrame = (object._WY << 8) + object._FS; - if (frameNo1 >= startFrame && frameNo1 < startFrame + object._NA) { + const uint16 startFrame = (object._roomFrameMSB << 8) + object._roomFrameLSB; + if (frameNo1 >= startFrame && frameNo1 < startFrame + object._numFrames) { const int x = object._x; const int y = object._y; - const int w = (object._XL + 3) / 4 * 4; // Original code uses this to round up width to a multiple of 4. - const int h = object._YL; + const int w = (object._width + 3) / 4 * 4; // Original code uses this to round up width to a multiple of 4. + const int h = object._height; Common::Rect rect(x, y, x + w, y + h); const Graphics::Surface sharedSurface = surface.getSubArea(rect); @@ -100,11 +100,11 @@ bool Room::load(uint8 roomNumber, bool roomB) { for (int i = 0; i < noObjects; ++i) { uint8 firstIndex = 0; if (i != 0) { - firstIndex = _objectsStart[i - 1] + scene->_objects[i - 1]._NA; + firstIndex = _objectsStart[i - 1] + scene->_objects[i - 1]._numFrames; } _objectsStart.push_back(firstIndex); - uint8 numAnims = scene->_objects[i]._NA; + uint8 numAnims = scene->_objects[i]._numFrames; while (numAnims--) { _surfaces.push_back(Graphics::Surface()); } @@ -142,7 +142,7 @@ void Room::redraw() { Scene *const currentScene = _game->getGameData().getCurrentScene(); for (int i = 0; i < currentScene->getNoObjects(); ++i) { Object *const obj = currentScene->getObject(i + 1); - if (obj->_AC) { + if (obj->_active) { drawObjectAnimation(i + 1, 0); } } diff --git a/engines/mutationofjb/tasks/objectanimationtask.cpp b/engines/mutationofjb/tasks/objectanimationtask.cpp index 75c15bf624..90438f8bc2 100644 --- a/engines/mutationofjb/tasks/objectanimationtask.cpp +++ b/engines/mutationofjb/tasks/objectanimationtask.cpp @@ -31,6 +31,7 @@ namespace MutationOfJB { static const int TICK_MILLIS = 100; +// TODO: Respect currentScene._delay. ObjectAnimationTask::ObjectAnimationTask() : _timer(TICK_MILLIS) { } @@ -47,6 +48,17 @@ void ObjectAnimationTask::update() { } } +/** + * Advances every object animation in the current scene to the next frame. + * + * Normally the animation restarts after the last object frame. However, some animations have random + * elements to them. If _randomFrame is set, the animation restarts when _randomFrame is reached. + * Additionally, there is a chance with each frame until _randomFrame that the animation may jump + * straight to _randomFrame and continue until the last frame, then wrap around to the first frame. + * + * Randomness is used to introduce variety - e.g. in the starting scene a perched bird occassionally + * spreads its wings. + */ void ObjectAnimationTask::updateObjects() { Scene *const scene = getTaskManager()->getGame().getGameData().getCurrentScene(); if (!scene) { @@ -56,34 +68,34 @@ void ObjectAnimationTask::updateObjects() { for (uint8 i = 1; i <= scene->getNoObjects(); ++i) { Object *const object = scene->getObject(i); // Skip if object animation not active. - if (!object->_AC) + if (!object->_active) continue; - // Number of framers must be higher than 1. - if (object->_NA <= 1) + // Number of frames must be higher than 1. + if (object->_numFrames <= 1) continue; - const uint8 currentAnimOffset = object->_CA - object->_FA; + const uint8 currentAnimOffset = object->_currentFrame - object->_firstFrame; - const bool randomized = object->_FR != 0; - const bool belowRandomFrame = currentAnimOffset < (object->_FR - 1); + const bool randomized = object->_randomFrame != 0; + const bool belowRandomFrame = currentAnimOffset < (object->_randomFrame - 1); - uint8 maxAnimOffset = object->_NA - 1; + uint8 maxAnimOffset = object->_numFrames - 1; if (randomized && belowRandomFrame) { - maxAnimOffset = object->_FR - 2; + maxAnimOffset = object->_randomFrame - 2; } uint8 nextAnimationOffset = currentAnimOffset + 1; if (currentAnimOffset == maxAnimOffset) { - if (randomized && object->_unknown != 0 && getTaskManager()->getGame().getRandomSource().getRandomNumber(object->_unknown) == 0) - nextAnimationOffset = object->_FR - 1; + if (randomized && object->_jumpChance != 0 && getTaskManager()->getGame().getRandomSource().getRandomNumber(object->_jumpChance) == 0) + nextAnimationOffset = object->_randomFrame - 1; else nextAnimationOffset = 0; } // TODO: Hardcoded animations. - object->_CA = nextAnimationOffset + object->_FA; + object->_currentFrame = nextAnimationOffset + object->_firstFrame; getTaskManager()->getGame().getRoom().drawObjectAnimation(i, nextAnimationOffset); } } diff --git a/engines/mutationofjb/tasks/saytask.cpp b/engines/mutationofjb/tasks/saytask.cpp index c9c2a95ad8..bd89805c68 100644 --- a/engines/mutationofjb/tasks/saytask.cpp +++ b/engines/mutationofjb/tasks/saytask.cpp @@ -60,10 +60,12 @@ void SayTask::drawSubtitle(const Common::String &text, int16 talkX, int16 talkY, Common::Array<Common::String> lines; font.wordWrap(text, MAX_LINE_WIDTH, lines); + // Get the x, y coordinates of the top center point of the text's bounding box + // from the (rather strange) talk coordinates coming from scripts. int16 x = talkX; - int16 y = talkY - (lines.size() - 1) * font.getLineHeight() - 15; // Get the top y + int16 y = talkY - (lines.size() - 1) * font.getLineHeight() - 15; - // Clamp to screen edges + // Clamp to screen edges. y = MAX<int16>(y, 3); int16 maxWidth = 0; for (uint i = 0; i < lines.size(); i++) { @@ -75,12 +77,12 @@ void SayTask::drawSubtitle(const Common::String &text, int16 talkX, int16 talkY, x = MIN<int16>(x, 317 - lineWidth / 2); } - // Draw lines + // Draw lines. for (uint i = 0; i < lines.size(); i++) { font.drawString(lines[i], color, x - font.getWidth(lines[i]) / 2, y + i * font.getLineHeight(), getTaskManager()->getGame().getScreen()); } - // Remember the area occupied by the text + // Remember the area occupied by the text. _boundingBox.top = x - maxWidth / 2; _boundingBox.left = y; _boundingBox.setWidth(maxWidth); |