MYST3: Implement a few opcodes used in Tomahna

This commit is contained in:
Bastien Bouclet 2012-01-14 15:39:42 +01:00
parent 539d1ec502
commit 52d12cbf1a
7 changed files with 174 additions and 38 deletions

View File

@ -18,40 +18,40 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef CURSOR_H_
#define CURSOR_H_
#include "common/rect.h"
namespace Myst3 {
class Myst3Engine;
class Cursor {
public:
Cursor(Myst3Engine *vm);
virtual ~Cursor();
void changeCursor(uint32 index);
void lockPosition(bool lock);
Common::Point getPosition() { return _position; }
void updatePosition(Common::Point &mouse);
void draw();
private:
Myst3Engine *_vm;
uint32 _currentCursorID;
/** Position of the cursor */
Common::Point _position;
bool _lockedAtCenter;
void loadAvailableCursors();
};
} /* namespace Myst3 */
#endif /* CURSOR_H_ */
*/
#ifndef CURSOR_H_
#define CURSOR_H_
#include "common/rect.h"
namespace Myst3 {
class Myst3Engine;
class Cursor {
public:
Cursor(Myst3Engine *vm);
virtual ~Cursor();
void changeCursor(uint32 index);
void lockPosition(bool lock);
Common::Point getPosition() { return _position; }
void updatePosition(Common::Point &mouse);
void draw();
private:
Myst3Engine *_vm;
uint32 _currentCursorID;
/** Position of the cursor */
Common::Point _position;
bool _lockedAtCenter;
void loadAvailableCursors();
};
} /* namespace Myst3 */
#endif /* CURSOR_H_ */

View File

@ -28,6 +28,7 @@ namespace Myst3 {
Movie::Movie(Myst3Engine *vm, uint16 id) :
_vm(vm),
_id(id),
_posU(0),
_posV(0),
_startFrame(0),

View File

@ -42,11 +42,14 @@ public:
virtual void draw();
uint16 getId() { return _id; }
void setStartFrame(int32 v) { _startFrame = v; }
void setEndFrame(int32 v) { _endFrame = v; }
protected:
Myst3Engine *_vm;
uint16 _id;
Math::Vector3d _pTopLeft;
Math::Vector3d _pBottomLeft;
Math::Vector3d _pBottomRight;

View File

@ -595,6 +595,17 @@ void Myst3Engine::playSimpleMovie(uint16 id) {
_drawables.pop_back();
}
void Myst3Engine::setMovieLooping(uint16 id, bool loop) {
for (uint i = 0; i < _movies.size(); i++) {
if (_movies[i]->getId() == id) {
// Enable or disable looping
_movies[i]->setLoop(loop);
_movies[i]->setDisableWhenComplete(!loop);
break;
}
}
}
void Myst3Engine::addSpotItem(uint16 id, uint16 condition, bool fade) {
_node->loadSpotItem(id, condition, fade);
}

View File

@ -98,6 +98,7 @@ public:
void loadMovie(uint16 id, uint16 condition, bool resetCond, bool loop);
void playSimpleMovie(uint16 id);
void setMovieLooping(uint16 id, bool loop);
void addSpotItem(uint16 id, uint16 condition, bool fade);
void addMenuSpotItem(uint16 id, uint16 condition, const Common::Rect &rect);

View File

@ -53,7 +53,7 @@ Script::Script(Myst3Engine *vm):
OP_1( 13, spotItemAdd, kValue );
OP_2( 14, spotItemAddCond, kValue, kCondition );
OP_2( 15, spotItemAddCondFade, kValue, kCondition );
OP_5( 16, spotItemAddMenu, kValue, kCondition, kValue, kValue, kValue ); // Six args
OP_5( 16, spotItemAddMenu, kValue, kCondition, kValue, kValue, kValue ); // Six args
OP_1( 17, movieInitLooping, kEvalValue );
OP_2( 18, movieInitCondLooping, kEvalValue, kCondition );
OP_2( 19, movieInitCond, kEvalValue, kCondition );
@ -64,6 +64,8 @@ Script::Script(Myst3Engine *vm):
OP_2( 24, movieInitFrameVarPreload, kEvalValue, kVar );
OP_4( 25, movieInitOverrridePosition, kEvalValue, kCondition, kValue, kValue );
OP_3( 26, movieInitScriptedPosition, kEvalValue, kVar, kVar );
OP_1( 29, movieSetLooping, kValue );
OP_1( 30, movieSetNotLooping, kValue );
OP_2( 35, sunspotAdd, kValue, kValue );
OP_3( 36, sunspotAddIntensity, kValue, kValue, kValue );
OP_4( 37, sunspotAddVarIntensity, kValue, kValue, kValue, kVar );
@ -142,6 +144,9 @@ Script::Script(Myst3Engine *vm):
OP_2(120, ifVarHasAllBitsSet, kVar, kValue );
OP_2(121, ifVarHasNoBitsSet, kVar, kValue );
OP_3(122, ifVarHasSomeBitsSet, kVar, kValue, kValue );
OP_2(123, ifHeadingInRange, kValue, kValue );
OP_2(124, ifPitchInRange, kValue, kValue );
OP_4(125, ifHeadingPitchInRect, kValue, kValue, kValue, kValue );
OP_4(126, ifMouseIsInRect, kValue, kValue, kValue, kValue );
OP_3(135, chooseNextNode, kCondition, kValue, kValue );
OP_2(136, goToNodeTransition, kValue, kValue );
@ -155,6 +160,8 @@ Script::Script(Myst3Engine *vm):
OP_1(164, changeNode, kValue );
OP_2(165, changeNodeRoom, kValue, kValue );
OP_3(166, changeNodeRoomAge, kValue, kValue, kValue );
OP_1(169, drawXFrames, kValue );
OP_1(171, drawWhileCond, kCondition );
OP_2(174, runScriptWhileCond, kCondition, kValue );
OP_3(175, runScriptWhileCondEachXFrames,kCondition, kValue, kValue );
OP_4(176, runScriptForVar, kVar, kValue, kValue, kValue );
@ -174,6 +181,7 @@ Script::Script(Myst3Engine *vm):
OP_2(195, runPuzzle2, kValue, kValue );
OP_3(196, runPuzzle3, kValue, kValue, kValue );
OP_4(197, runPuzzle4, kValue, kValue, kValue, kValue );
OP_0(239, drawOneFrame );
OP_0(249, newGame );
#undef OP_0
@ -496,6 +504,20 @@ void Script::movieInitScriptedPosition(Context &c, const Opcode &cmd) {
_vm->loadMovie(movieid, 1, false, true);
}
void Script::movieSetLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set movie % to loop",
cmd.op, cmd.args[0]);
_vm->setMovieLooping(cmd.args[0], true);
}
void Script::movieSetNotLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set movie % not to loop",
cmd.op, cmd.args[0]);
_vm->setMovieLooping(cmd.args[0], false);
}
void Script::sunspotAdd(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
@ -1284,6 +1306,68 @@ void Script::ifVarHasSomeBitsSet(Context &c, const Opcode &cmd) {
goToElse(c);
}
void Script::ifHeadingInRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If heading in range %d -> %d",
cmd.op, cmd.args[0], cmd.args[1]);
float heading = _vm->_state->getLookAtHeading();
if (cmd.args[1] > cmd.args[0]) {
// If heading in range
if (heading > cmd.args[0] && heading < cmd.args[1]) {
debug("in range true %d %d", cmd.args[0], cmd.args[1]);
return;
}
} else {
// If heading *not* in range
if (heading > cmd.args[0] || heading < cmd.args[1]) {
debug("not in range true %d %d", cmd.args[1], cmd.args[0]);
return;
}
}
goToElse(c);
}
void Script::ifPitchInRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If pitch in range %d -> %d",
cmd.op, cmd.args[0], cmd.args[1]);
float pitch = _vm->_state->getLookAtPitch();
// If pitch in range
if (pitch > cmd.args[0] && pitch < cmd.args[1])
return;
goToElse(c);
}
void Script::ifHeadingPitchInRect(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If heading in range %d -> %d",
cmd.op, cmd.args[0], cmd.args[1]);
float heading = _vm->_state->getLookAtHeading();
float pitch = _vm->_state->getLookAtPitch();
// If pitch in range
if (pitch <= cmd.args[0] || pitch >= cmd.args[1]) {
goToElse(c);
return;
}
if (cmd.args[1] > cmd.args[0]) {
// If heading in range
if (heading > cmd.args[0] && heading < cmd.args[1])
return;
} else {
// If heading *not* in range
if (heading > cmd.args[0] || heading < cmd.args[1])
return;
}
goToElse(c);
}
void Script::ifMouseIsInRect(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If mouse in rect l%d t%d w%d h%d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
@ -1379,6 +1463,27 @@ void Script::changeNodeRoomAge(Context &c, const Opcode &cmd) {
_vm->loadNode(cmd.args[2], cmd.args[1], cmd.args[0]);
}
void Script::drawXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Draw %d frames", cmd.op, cmd.args[0]);
uint32 endFrame = _vm->_state->getFrameCount() + cmd.args[0];
while (_vm->_state->getFrameCount() < endFrame) {
_vm->processInput(true);
_vm->drawFrame();
}
}
void Script::drawWhileCond(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: While condition %d, draw", cmd.op, cmd.args[0]);
// TODO: Skippable with Escape
while (_vm->_state->evaluate(cmd.args[0])) {
_vm->processInput(true);
_vm->drawFrame();
}
}
void Script::runScriptWhileCond(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: While condition %d, run script %d", cmd.op, cmd.args[0], cmd.args[1]);
@ -1600,6 +1705,13 @@ void Script::runPuzzle4(Context &c, const Opcode &cmd) {
_puzzles->run(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
}
void Script::drawOneFrame(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Draw one frame", cmd.op);
_vm->processInput(true);
_vm->drawFrame();
}
void Script::newGame(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: New game", cmd.op);

View File

@ -117,6 +117,8 @@ private:
DECLARE_OPCODE(movieInitFrameVarPreload);
DECLARE_OPCODE(movieInitOverrridePosition);
DECLARE_OPCODE(movieInitScriptedPosition);
DECLARE_OPCODE(movieSetLooping);
DECLARE_OPCODE(movieSetNotLooping);
DECLARE_OPCODE(sunspotAdd);
DECLARE_OPCODE(sunspotAddIntensity);
DECLARE_OPCODE(sunspotAddVarIntensity);
@ -195,6 +197,9 @@ private:
DECLARE_OPCODE(ifVarHasAllBitsSet);
DECLARE_OPCODE(ifVarHasNoBitsSet);
DECLARE_OPCODE(ifVarHasSomeBitsSet);
DECLARE_OPCODE(ifHeadingInRange);
DECLARE_OPCODE(ifPitchInRange);
DECLARE_OPCODE(ifHeadingPitchInRect);
DECLARE_OPCODE(ifMouseIsInRect);
DECLARE_OPCODE(chooseNextNode);
DECLARE_OPCODE(goToNodeTransition);
@ -208,6 +213,8 @@ private:
DECLARE_OPCODE(changeNode);
DECLARE_OPCODE(changeNodeRoom);
DECLARE_OPCODE(changeNodeRoomAge);
DECLARE_OPCODE(drawXFrames);
DECLARE_OPCODE(drawWhileCond);
DECLARE_OPCODE(runScriptWhileCond);
DECLARE_OPCODE(runScriptWhileCondEachXFrames);
DECLARE_OPCODE(runScriptForVar);
@ -227,6 +234,7 @@ private:
DECLARE_OPCODE(runPuzzle2);
DECLARE_OPCODE(runPuzzle3);
DECLARE_OPCODE(runPuzzle4);
DECLARE_OPCODE(drawOneFrame);
DECLARE_OPCODE(newGame);
};