some work in progress on verb stuff:

- many structers and fields renamed to proper names
- added missing functions

svn-id: r16562
This commit is contained in:
Andrew Kurushin 2005-01-15 20:12:49 +00:00
parent 139f57a29d
commit 2f20dd57c2
23 changed files with 534 additions and 249 deletions

View File

@ -135,7 +135,8 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
size_t stringsLength;
ActorData *actor;
debug(9, "Actor::Actor()");
_actors = NULL;
if (_vm->getGameType() == GType_IHNM) {
warning("Actors aren't implemented for IHNM yet");
return;
@ -180,32 +181,37 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
_vm->loadStrings(_actorsStrings, stringsPointer, stringsLength);
RSC_FreeResource(stringsPointer);
for (i = 0; i < ACTORCOUNT; i++) {
actor = &_actors[i];
actor->actorId = actorIndexToId(i);
actor->index = i;
debug(9, "init actorId=%d index=%d", actor->actorId, actor->index);
actor->nameIndex = ActorTable[i].nameIndex;
actor->spriteListResourceId = ActorTable[i].spriteListResourceId;
actor->frameListResourceId = ActorTable[i].frameListResourceId;
actor->speechColor = ActorTable[i].speechColor;
actor->sceneNumber = ActorTable[i].sceneIndex;
actor->flags = ActorTable[i].flags;
actor->currentAction = ActorTable[i].currentAction;
actor->facingDirection = ActorTable[i].facingDirection;
actor->actionDirection = ActorTable[i].actionDirection;
actor->frameNumber = 0;
actor->targetObject = ID_NOTHING;
actor->actorFlags = 0;
if (_vm->getGameType() == GType_ITE) {
_actorsCount = ITE_ACTORCOUNT;
_actors = (ActorData **)malloc(_actorsCount * sizeof(ActorData *));
for (i = 0; i < _actorsCount; i++) {
actor = _actors[i] = new ActorData();
actor->actorId = actorIndexToId(i);
actor->index = i;
debug(9, "init actorId=%d index=%d", actor->actorId, actor->index);
actor->nameIndex = ITE_ActorTable[i].nameIndex;
actor->scriptEntrypointNumber = ITE_ActorTable[i].scriptEntrypointNumber;
actor->spriteListResourceId = ITE_ActorTable[i].spriteListResourceId;
actor->frameListResourceId = ITE_ActorTable[i].frameListResourceId;
actor->speechColor = ITE_ActorTable[i].speechColor;
actor->sceneNumber = ITE_ActorTable[i].sceneIndex;
actor->flags = ITE_ActorTable[i].flags;
actor->currentAction = ITE_ActorTable[i].currentAction;
actor->facingDirection = ITE_ActorTable[i].facingDirection;
actor->actionDirection = ITE_ActorTable[i].actionDirection;
actor->frameNumber = 0;
actor->targetObject = ID_NOTHING;
actor->actorFlags = 0;
actor->location.x = ActorTable[i].x;
actor->location.y = ActorTable[i].y;
actor->location.z = ActorTable[i].z;
actor->location.x = ITE_ActorTable[i].x;
actor->location.y = ITE_ActorTable[i].y;
actor->location.z = ITE_ActorTable[i].z;
actor->disabled = !loadActorResources(actor);
if (actor->disabled) {
warning("Disabling actorId=%d index=%d", actor->actorId, actor->index);
}
actor->disabled = !loadActorResources(actor);
if (actor->disabled) {
warning("Disabling actorId=%d index=%d", actor->actorId, actor->index);
}
}
}
}
@ -225,11 +231,11 @@ Actor::~Actor() {
free(_pathCell);
_actorsStrings.freeMem();
//release resources
for (i = 0; i < ACTORCOUNT; i++) {
actor = &_actors[i];
free(actor->frames);
actor->spriteList.freeMem();
for (i = 0; i < _actorsCount; i++) {
actor = _actors[i];
delete actor;
}
free(_actors);
}
bool Actor::loadActorResources(ActorData *actor) {
@ -304,7 +310,7 @@ bool Actor::loadActorResources(ActorData *actor) {
return true;
}
void Actor::realLocation(ActorLocation &location, uint16 objectId, uint16 walkFlags) {
void Actor::realLocation(Location &location, uint16 objectId, uint16 walkFlags) {
int angle;
int distance;
ActorData *actor;
@ -332,9 +338,9 @@ void Actor::realLocation(ActorLocation &location, uint16 objectId, uint16 walkFl
}
}
void Actor::actorFaceTowardsPoint(uint16 actorId, const ActorLocation &toLocation) {
void Actor::actorFaceTowardsPoint(uint16 actorId, const Location &toLocation) {
ActorData *actor;
ActorLocation delta;
Location delta;
actor = getActor(actorId);
@ -382,7 +388,7 @@ ActorData *Actor::getActor(uint16 actorId) {
return _protagonist;
}
actor = &_actors[actorIdToIndex(actorId)];
actor = _actors[actorIdToIndex(actorId)];
if (actor->disabled)
warning("Actor::getActor disabled actorId 0x%X", actorId);
@ -390,7 +396,7 @@ ActorData *Actor::getActor(uint16 actorId) {
return actor;
}
bool Actor::validFollowerLocation(const ActorLocation &location) {
bool Actor::validFollowerLocation(const Location &location) {
Point point;
location.toScreenPointXY(point);
@ -406,8 +412,8 @@ void Actor::updateActorsScene() {
int i, j;
int followerDirection;
ActorData *actor;
ActorLocation tempLocation;
ActorLocation possibleLocation;
Location tempLocation;
Location possibleLocation;
Point delta;
if (_vm->getGameType() == GType_IHNM) {
@ -418,8 +424,8 @@ void Actor::updateActorsScene() {
_activeSpeech.stringsCount = 0;
_protagonist = NULL;
for (i = 0; i < ACTORCOUNT; i++) {
actor = &_actors[i];
for (i = 0; i < _actorsCount; i++) {
actor = _actors[i];
if (actor->flags & (kProtagonist | kFollower)) {
actor->sceneNumber = _vm->_scene->currentSceneNumber();
if (actor->flags & kProtagonist) {
@ -452,8 +458,8 @@ void Actor::updateActorsScene() {
followerDirection = _protagonist->facingDirection + 3;
calcActorScreenPosition(_protagonist);
for (i = 0; i < ACTORCOUNT; i++) {
actor = &_actors[i];
for (i = 0; i < _actorsCount; i++) {
actor = _actors[i];
if (actor->flags & (kFollower)) {
actor->facingDirection = actor->actionDirection = _protagonist->facingDirection;
actor->currentAction = kActionWait;
@ -630,11 +636,11 @@ void Actor::handleActions(int msec, bool setup) {
ActorFrameRange *frameRange;
int state;
int speed;
ActorLocation delta;
ActorLocation addDelta;
Location delta;
Location addDelta;
for (i = 0; i < ACTORCOUNT; i++) {
actor = &_actors[i];
for (i = 0; i < _actorsCount; i++) {
actor = _actors[i];
if (actor->disabled) continue;
if (actor->sceneNumber != _vm->_scene->currentSceneNumber()) continue;
@ -876,7 +882,7 @@ int Actor::direct(int msec) {
// FIXME: HACK. This should be turned into cycle event.
_lastTickMsec += msec;
if (_lastTickMsec > ticksToMSec(5)) { // fixme
if (_lastTickMsec > ticksToMSec(2)) { // fixme
_lastTickMsec = 0;
//process actions
handleActions(msec, false);
@ -922,8 +928,8 @@ void Actor::createDrawOrderList() {
ActorData *actor;
_drawOrderList.clear();
for (i = 0; i < ACTORCOUNT; i++) {
actor = &_actors[i];
for (i = 0; i < _actorsCount; i++) {
actor = _actors[i];
if (actor->disabled) continue;
if (actor->sceneNumber != _vm->_scene->currentSceneNumber()) continue;
@ -1009,9 +1015,9 @@ int Actor::drawActors() {
}
bool Actor::followProtagonist(ActorData *actor) {
ActorLocation protagonistLocation;
ActorLocation newLocation;
ActorLocation delta;
Location protagonistLocation;
Location newLocation;
Location delta;
int protagonistBGMaskType;
Point prefer1;
Point prefer2;
@ -1132,7 +1138,7 @@ bool Actor::actorEndWalk(uint16 actorId, bool recurse) {
return walkMore;
}
bool Actor::actorWalkTo(uint16 actorId, const ActorLocation &toLocation) {
bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) {
ActorData *actor;
ActorData *anotherActor;
int i;
@ -1207,8 +1213,8 @@ bool Actor::actorWalkTo(uint16 actorId, const ActorLocation &toLocation) {
_barrierCount = 0;
for (i = 0; (i < ACTORCOUNT) && (_barrierCount < ACTOR_BARRIERS_MAX); i++) {
anotherActor = &_actors[i];
for (i = 0; (i < _actorsCount) && (_barrierCount < ACTOR_BARRIERS_MAX); i++) {
anotherActor = _actors[i];
if (anotherActor->disabled) continue;
if (anotherActor->sceneNumber != _vm->_scene->currentSceneNumber()) continue;
if (anotherActor == actor ) continue;
@ -1298,8 +1304,8 @@ bool Actor::actorWalkTo(uint16 actorId, const ActorLocation &toLocation) {
return false;
} else {
if (actor->flags & kProtagonist) {
_actors[1].actorFlags &= ~kActorNoFollow;
_actors[2].actorFlags &= ~kActorNoFollow;
_actors[1]->actorFlags &= ~kActorNoFollow; // TODO: mark all actors with kFollower flag, not only 1 and 2
_actors[2]->actorFlags &= ~kActorNoFollow;
}
actor->currentAction = (actor->walkStepsCount >= ACTOR_MAX_STEPS_COUNT) ? kActionWalkToLink : kActionWalkToPoint;
actor->walkFrameSequence = kFrameWalk;
@ -1903,7 +1909,7 @@ void Actor::drawPathTest() {
void Actor::cmdActorWalkTo(int argc, const char **argv) {
uint16 actorId = (uint16) atoi(argv[1]);
ActorLocation location;
Location location;
Point movePoint;
movePoint.x = atoi(argv[2]);

View File

@ -134,22 +134,22 @@ struct ActorFrameSequence {
ActorFrameRange directions[ACTOR_DIRECTIONS_COUNT];
};
struct ActorLocation {
int x; // Actor's logical coordinates
struct Location {
int x; // logical coordinates
int y; //
int z; //
ActorLocation() {
Location() {
x = y = z = 0;
}
int distance(const ActorLocation &location) const {
int distance(const Location &location) const {
return MAX(ABS(x - location.x), ABS(y - location.y));
}
void delta(const ActorLocation &location, ActorLocation &result) const {
void delta(const Location &location, Location &result) const {
result.x = x - location.x;
result.y = y - location.y;
result.z = z - location.z;
}
void add(const ActorLocation &location) {
void add(const Location &location) {
x += location.x;
y += location.y;
z += location.z;
@ -176,10 +176,10 @@ struct ActorData {
int nameIndex; // Actor's index in actor name string list
byte speechColor; // Actor dialogue color
uint16 flags; // Actor initial flags
int scriptEntrypointNumber; // Actor script entrypoint number
int sceneNumber; // scene of actor
ActorLocation location; // Actor's logical coordinates
Location location; // Actor's logical coordinates
Point screenPosition; // Actor's screen coordinates
int screenDepth; //
@ -211,8 +211,8 @@ struct ActorData {
int walkStepIndex;
Point *walkStepsPoints;
ActorLocation finalTarget;
ActorLocation partialTarget;
Location finalTarget;
Location partialTarget;
int walkFrameSequence;
void cycleWrap(int cycleLimit) {
@ -235,7 +235,9 @@ struct ActorData {
memset(&spriteList, 0, sizeof(spriteList));
}
~ActorData() {
free(frames);
free(walkStepsPoints);
spriteList.freeMem();
}
};
@ -271,7 +273,7 @@ public:
void cmdActorWalkTo(int argc, const char **argv);
bool validActorId(uint16 id) { return (id == 1) || ((id >= 0x2000) && (id < (0x2000 | ACTORCOUNT))); }
bool validActorId(uint16 id) { return (id == 1) || ((id >= 0x2000) && (id < (0x2000 | _actorsCount))); }
int actorIdToIndex(uint16 id) { return (id == 1 ) ? 0 : (id & ~0x2000); }
uint16 actorIndexToId(int index) { return (index == 0 ) ? 1 : (index | 0x2000); }
@ -281,13 +283,14 @@ public:
void drawPathTest();
uint16 testHit(const Point& mousePointer){ return ID_NOTHING;}; //TODO: do it
const char * getActorName(uint16 actorId);
bool actorEndWalk(uint16 actorId, bool recurse);
bool actorWalkTo(uint16 actorId, const ActorLocation &toLocation);
bool actorWalkTo(uint16 actorId, const Location &toLocation);
ActorData *getActor(uint16 actorId);
ActorFrameRange *getActorFrameRange(uint16 actorId, int frameType);
void realLocation(ActorLocation &location, uint16 objectId, uint16 walkFlags);
void actorFaceTowardsPoint(uint16 actorId, const ActorLocation &toLocation);
void realLocation(Location &location, uint16 objectId, uint16 walkFlags);
void actorFaceTowardsPoint(uint16 actorId, const Location &toLocation);
void actorFaceTowardsObject(uint16 actorId, uint16 objectId);
// speech
@ -337,13 +340,14 @@ private:
void removeNodes();
void nodeToPath();
void removePathPoints();
bool validFollowerLocation(const ActorLocation &location);
bool validFollowerLocation(const Location &location);
int _lastTickMsec;
SagaEngine *_vm;
RSCFILE_CONTEXT *_actorContext;
ActorOrderList _drawOrderList;
ActorData _actors[ACTORCOUNT];
int _actorsCount;
ActorData **_actors;
SpeechData _activeSpeech;
StringsTable _actorsStrings;

View File

@ -27,7 +27,7 @@
namespace Saga {
ActorTableData ActorTable[ACTORCOUNT] = {
ActorTableData ITE_ActorTable[ITE_ACTORCOUNT] = {
// Original used so called permanent actors for first three and that was designed by
// EXTENDED object flag. They contained frames in more than one resource. We use
// different technique here see "Apppending to sprite list" in loadActorResources()

View File

@ -49,16 +49,16 @@ struct ActorTableData {
int16 z;
int32 spriteListResourceId;
int32 frameListResourceId;
byte scriptResourceId;
byte scriptEntrypointNumber;
byte speechColor;
byte currentAction;
byte facingDirection;
byte actionDirection;
};
#define ACTORCOUNT 181
#define ITE_ACTORCOUNT 181
extern ActorTableData ActorTable[ACTORCOUNT];
extern ActorTableData ITE_ActorTable[ITE_ACTORCOUNT];
} // End of namespace Saga

View File

@ -258,7 +258,7 @@ int Events::handleImmediate(EVENT *event) {
int Events::handleOneShot(EVENT *event) {
SURFACE *back_buf;
SCRIPT_THREAD *sthread;
ScriptThread *sthread;
Rect rect;
static SCENE_BGINFO bginfo;
@ -397,7 +397,7 @@ int Events::handleOneShot(EVENT *event) {
case EVENT_EXEC_NONBLOCKING:
debug(0, "Starting start script #%d", event->param);
sthread = _vm->_script->SThreadCreate();
sthread = _vm->_script->createThread();
if (sthread == NULL) {
_vm->_console->DebugPrintf("Thread creation failed.\n");
break;
@ -408,10 +408,10 @@ int Events::handleOneShot(EVENT *event) {
sthread->threadVars[kVarWithObject] = TO_LE_16(event->param4);
sthread->threadVars[kVarActor] = TO_LE_16(event->param5);
_vm->_script->SThreadExecute(sthread, event->param);
_vm->_script->executeThread(sthread, event->param);
if (event->op == EVENT_EXEC_BLOCKING)
_vm->_script->SThreadCompleteThread();
_vm->_script->completeThread();
break;
case EVENT_THREAD_WAKE:

View File

@ -41,7 +41,7 @@ SCENE_RESLIST IHNM_IntroMovie1RL[] = {
{31, SAGA_ANIM_1, 0, 0}
};
SCENE_DESC IHNM_IntroMovie1Desc = {
SceneDescription IHNM_IntroMovie1Desc = {
0, 0, 0, 0, 0, 0, 0, 0,
IHNM_IntroMovie1RL,
ARRAYSIZE(IHNM_IntroMovie1RL)
@ -52,7 +52,7 @@ SCENE_RESLIST IHNM_IntroMovie2RL[] = {
{33, SAGA_ANIM_1, 0, 0}
};
SCENE_DESC IHNM_IntroMovie2Desc = {
SceneDescription IHNM_IntroMovie2Desc = {
0, 0, 0, 0, 0, 0, 0, 0,
IHNM_IntroMovie2RL,
ARRAYSIZE(IHNM_IntroMovie2RL)
@ -63,7 +63,7 @@ SCENE_RESLIST IHNM_IntroMovie3RL[] = {
{35, SAGA_ANIM_1, 0, 0}
};
SCENE_DESC IHNM_IntroMovie3Desc = {
SceneDescription IHNM_IntroMovie3Desc = {
0, 0, 0, 0, 0, 0, 0, 0,
IHNM_IntroMovie3RL,
ARRAYSIZE(IHNM_IntroMovie3RL)
@ -74,7 +74,7 @@ SCENE_RESLIST IHNM_IntroMovie4RL[] = {
{1226, SAGA_ANIM_1, 0, 0}
};
SCENE_DESC IHNM_IntroMovie4Desc = {
SceneDescription IHNM_IntroMovie4Desc = {
0, 0, 0, 0, 0, 0, 0, 0,
IHNM_IntroMovie4RL,
ARRAYSIZE(IHNM_IntroMovie4RL)

View File

@ -67,7 +67,7 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) {
return;
}
_iThread = _vm->_script->SThreadCreate();
_iThread = _vm->_script->createThread();
if (_iThread == NULL) {
error("Interface::Interface(): Error creating script thread for game interface module");
}
@ -347,7 +347,7 @@ int Interface::draw() {
return SUCCESS;
}
int Interface::update(const Point& imousePointer, int updateFlag) {
int Interface::update(const Point& mousePoint, int updateFlag) {
SURFACE *backBuffer;
@ -358,31 +358,33 @@ int Interface::update(const Point& imousePointer, int updateFlag) {
backBuffer = _vm->_gfx->getBackBuffer();
if (_panelMode == kPanelMain) { // FIXME: HACK
// Update playfield space ( only if cursor is inside )
if (imousePointer.y < _vm->getSceneHeight()) {
// Mouse is in playfield space
if (updateFlag == UPDATE_MOUSEMOVE) {
handlePlayfieldUpdate(backBuffer, imousePointer);
if (_panelMode == kPanelMain) {
if (updateFlag == UPDATE_MOUSEMOVE) {
if (mousePoint.y < _vm->getSceneHeight()) {
//handlePlayfieldUpdate(backBuffer, imousePointer);
_vm->_script->whichObject(mousePoint);
} else {
if (updateFlag == UPDATE_MOUSECLICK) {
handlePlayfieldClick(backBuffer, imousePointer);
if (_lastMousePoint.y < _vm->getSceneHeight()) {
_vm->_script->setNonPlayfieldVerb();
}
handleCommandUpdate(backBuffer, mousePoint);
}
} else {
// Update command space
if (updateFlag == UPDATE_MOUSEMOVE) {
handleCommandUpdate(backBuffer, imousePointer);
} else {
if (updateFlag == UPDATE_MOUSECLICK) {
handleCommandClick(backBuffer, imousePointer);
if (updateFlag == UPDATE_MOUSECLICK) {
if (mousePoint.y < _vm->getSceneHeight()) {
handlePlayfieldClick(backBuffer, mousePoint);
} else {
handleCommandClick(backBuffer, mousePoint);
}
}
}
}
drawStatusBar(backBuffer);
_lastMousePoint = mousePoint;
return SUCCESS;
}
@ -415,21 +417,21 @@ int Interface::drawStatusBar(SURFACE *ds) {
return SUCCESS;
}
void Interface::handleCommandClick(SURFACE *ds, const Point& imousePointer) {
void Interface::handleCommandClick(SURFACE *ds, const Point& mousePoint) {
PanelButton *panelButton;
panelButton = verbHitTest(imousePointer);
panelButton = verbHitTest(mousePoint);
if (panelButton) {
_vm->_script->setVerb(panelButton->id);
return;
}
}
void Interface::handleCommandUpdate(SURFACE *ds, const Point& imousePointer) {
void Interface::handleCommandUpdate(SURFACE *ds, const Point& mousePoint) {
PanelButton *panelButton;
panelButton = verbHitTest(imousePointer);
panelButton = verbHitTest(mousePoint);
if (_mainPanel.currentButton != panelButton) {
if (_mainPanel.currentButton) {
drawVerb(_mainPanel.currentButton->id, 0);
@ -458,7 +460,7 @@ int Interface::handlePlayfieldClick(SURFACE *ds, const Point& imousePt) {
uint16 object_flags = 0;
// int script_num;
ActorLocation location;
Location location;
objectNum = _vm->_scene->_objectMap->hitTest(imousePt);
@ -529,7 +531,7 @@ int Interface::handlePlayfieldUpdate(SURFACE *ds, const Point& imousePt) {
*/
}
PanelButton *Interface::verbHitTest(const Point& imousePointer) {
PanelButton *Interface::verbHitTest(const Point& mousePoint) {
PanelButton *panelButton;
Rect rect;
int i;
@ -540,7 +542,7 @@ PanelButton *Interface::verbHitTest(const Point& imousePointer) {
rect.right = rect.left + panelButton->width;
rect.top = _mainPanel.y + panelButton->yOffset;
rect.bottom = rect.top + panelButton->height;
if (rect.contains(imousePointer))
if (rect.contains(mousePoint))
return panelButton;
}
}
@ -643,6 +645,7 @@ int Interface::inventoryTest(const Point& imousePt, int *ibutton) {
return FAILURE;
}
void Interface::drawVerb(int verb, int state) {
SURFACE *backBuffer;
PanelButton * panelButton;

View File

@ -96,19 +96,18 @@ public:
int activate();
int deactivate();
bool isActive() { return _active; }
int setMode(int mode, bool force = false);
int getMode(void) const { return _panelMode; }
void rememberMode();
void restoreMode();
void lockMode() { _lockedMode = _panelMode; }
void unlockMode() { _panelMode = _lockedMode; }
bool isInMainMode() { return _inMainMode; }
int setStatusText(const char *new_txt);
int loadScenePortraits(int resourceId);
int setLeftPortrait(int portrait);
int setRightPortrait(int portrait);
int draw();
int update(const Point& imousePointer, int updateFlag);
int update(const Point& mousePoint, int updateFlag);
int drawStatusBar(SURFACE *ds);
void drawVerb(int verb, int state);
@ -120,12 +119,15 @@ public:
private:
int inventoryTest(const Point& imousePt, int *ibutton);
PanelButton *verbHitTest(const Point& imousePointer);
void handleCommandUpdate(SURFACE *ds, const Point& imousePointer);
void handleCommandClick(SURFACE *ds, const Point& imousePointer);
PanelButton *verbHitTest(const Point& mousePoint);
void handleCommandUpdate(SURFACE *ds, const Point& mousePoint);
void handleCommandClick(SURFACE *ds, const Point& mousePoint);
int handlePlayfieldUpdate(SURFACE *ds, const Point& imousePt);
int handlePlayfieldClick(SURFACE *ds, const Point& imousePt);
void lockMode() { _lockedMode = _panelMode; }
void unlockMode() { _panelMode = _lockedMode; }
void drawPanelButtonText(SURFACE *ds, InterfacePanel *panel, PanelButton *panelButton, int textColor, int textShadowColor);
public:
void converseClear(void);
@ -152,7 +154,7 @@ private:
InterfacePanel _conversePanel;
SpriteList _defPortraits;
SpriteList _scenePortraits;
SCRIPT_THREAD *_iThread;
ScriptThread *_iThread;
PanelButton *_verbTypeToPanelButton[kVerbTypesMax];
bool _active;
@ -164,6 +166,8 @@ private:
int _leftPortrait;
int _rightPortrait;
Point _lastMousePoint;
uint16 *_inventory;
int _inventorySize;
byte _inventoryCount;

View File

@ -27,10 +27,6 @@
namespace Saga {
enum {
kObjUseWith = 0x01,
kObjNotFlat = 0x02
};
OBJECTTABLE ObjectTable[OBJECTCOUNT] = {
{ 8, 49, 1256, 760, 0, 9, 5, kObjNotFlat }, // Magic Hat

View File

@ -28,12 +28,17 @@
namespace Saga {
enum {
kObjUseWith = 0x01,
kObjNotFlat = 0x02
};
struct OBJECTTABLE {
byte nameIndex;
int32 sceneIndex;
int16 x, y, z;
int32 spritelistRn;
byte scriptRn;
byte scriptEntrypointNumber;
uint16 interactBits;
};

View File

@ -43,7 +43,7 @@ HitZone::HitZone(MemoryReadStreamEndian *readStream) {
_flags = readStream->readByte();
_clickAreasCount = readStream->readByte();
_defaultVerb = readStream->readByte();
_rightButtonVerb = readStream->readByte();
readStream->readByte(); // pad
_nameNumber = readStream->readUint16();
_scriptNumber = readStream->readUint16();

View File

@ -49,13 +49,16 @@ public:
int getEntranceNumber() const {
return _scriptNumber;
}
int getRightButtonVerb() const {
return _rightButtonVerb;
}
void draw(SURFACE *ds, int color);
bool hitTest(const Point &testPoint);
private:
int _flags; // HitZoneFlags
int _clickAreasCount;
int _defaultVerb;
int _rightButtonVerb;
int _nameNumber;
int _scriptNumber;

View File

@ -115,6 +115,11 @@ namespace Saga {
//TODO: fill it
#define RID_SCENE1_VOICE_138 186
#define RID_BOAR_VOICE_000 239
#define RID_BOAR_VOICE_002 241
#define RID_BOAR_VOICE_005 244
#define RID_BOAR_VOICE_006 245
#define RID_BOAR_VOICE_007 246
// MUSIC
#define MUSIC_1 9

View File

@ -357,6 +357,27 @@ const char *SagaEngine::getObjectName(uint16 objectId) {
return NULL;
}
int SagaEngine::getObjectScriptEntrypointNumber(uint16 objectId) {
ActorData *actor;
switch (objectIdType(objectId)) {
case kGameObjectActor:
actor = _vm->_actor->getActor(objectId);
return actor->scriptEntrypointNumber;
break;
}
//todo: object name & etc
return 0;
}
int SagaEngine::getObjectFlags(uint16 objectId) {
ActorData *actor;
if (objectIdType(objectId) == kGameObjectActor) {
actor = _vm->_actor->getActor(objectId);
return actor->flags;
}
return 0;
}
const char *SagaEngine::getTextString(int textStringId) {
const char *string;
int lang = _vm->getFeatures() & GF_LANG_DE ? 1 : 0;
@ -368,4 +389,30 @@ const char *SagaEngine::getTextString(int textStringId) {
return string;
}
void SagaEngine::getExcuseInfo(int verb, const char *&textString, int &soundResourceId) {
textString = NULL; // TODO: i18n it !
switch (verb) {
case kVerbPickUp:
textString = "I can't pick that up.";
soundResourceId = RID_BOAR_VOICE_007;
break;
case kVerbLookAt:
textString = "I see nothing special about it.";
soundResourceId = RID_BOAR_VOICE_006;
break;
case kVerbOpen:
textString = "There's no place to open it.";
soundResourceId = RID_BOAR_VOICE_000;
break;
case kVerbClose:
textString = "There's no opening to close.";
soundResourceId = RID_BOAR_VOICE_002;
break;
case kVerbUse:
textString = "I don't know how to do that.";
soundResourceId = RID_BOAR_VOICE_005;
break;
}
}
} // End of namespace Saga

View File

@ -433,8 +433,10 @@ public:
byte **output_buf, size_t *output_buf_len, int *w, int *h);
const byte *getImagePal(const byte *image_data, size_t image_size);
void loadStrings(StringsTable &stringsTable, const byte *stringsPointer, size_t stringsLength);
const char *getObjectName(uint16 objectId);
const char *getObjectName(uint16 objectId);
int getObjectScriptEntrypointNumber(uint16 objectId);
int getObjectFlags(uint16 objectId);
public:
TEXTLIST *textCreateList();
void textDestroyList(TEXTLIST *textlist);
@ -491,6 +493,7 @@ public:
const GameDisplayInfo & getDisplayInfo() { return _gameDisplayInfo; }
const char *getTextString(int textStringId);
void getExcuseInfo(int verb, const char *&textString, int &soundResourceId);
private:
int loadGame(int gameNumber);
};

View File

@ -191,7 +191,7 @@ int Scene::startScene() {
scene_qdat = queueIterator.operator->();
assert(scene_qdat != NULL);
loadScene(scene_qdat->scene_n, scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->scene_desc, scene_qdat->fadeType);
loadScene(scene_qdat->scene_n, scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->sceneDescription, scene_qdat->fadeType);
return SUCCESS;
}
@ -230,7 +230,7 @@ int Scene::nextScene() {
scene_qdat = queueIterator.operator->();
assert(scene_qdat != NULL);
loadScene(scene_qdat->scene_n, scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->scene_desc, scene_qdat->fadeType);
loadScene(scene_qdat->scene_n, scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->sceneDescription, scene_qdat->fadeType);
return SUCCESS;
}
@ -277,7 +277,7 @@ int Scene::skipScene() {
_sceneQueue.erase(_sceneQueue.begin(), queueIterator);
endScene();
loadScene(skip_qdat->scene_n, skip_qdat->load_flag, skip_qdat->scene_proc, skip_qdat->scene_desc, skip_qdat->fadeType);
loadScene(skip_qdat->scene_n, skip_qdat->load_flag, skip_qdat->scene_proc, skip_qdat->sceneDescription, skip_qdat->fadeType);
}
// Search for a scene to skip to
@ -504,7 +504,7 @@ int Scene::getSceneLUT(int scene_num) {
return _sceneLUT[scene_num];
}
int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SCENE_DESC *scene_desc_param, int fadeType) {
int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SceneDescription *scene_desc_param, int fadeType) {
SCENE_INFO scene_info;
uint32 res_number = 0;
int result;
@ -580,8 +580,8 @@ int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SCENE_
}
// Load scene script data
if (_desc.scriptNum > 0) {
if (_vm->_script->loadScript(_desc.scriptNum) != SUCCESS) {
if (_desc.scriptModuleNumber > 0) {
if (_vm->_script->loadScript(_desc.scriptModuleNumber) != SUCCESS) {
warning("Scene::loadScene(): Error loading scene script");
return FAILURE;
}
@ -635,12 +635,12 @@ int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SCENE_
q_event = _vm->_events->chain(q_event, &event);
// Start the scene pre script, but stay with black palette
if (_desc.startScriptNum > 0) {
if (_desc.startScriptEntrypointNumber > 0) {
event.type = ONESHOT_EVENT;
event.code = SCRIPT_EVENT;
event.op = EVENT_EXEC_BLOCKING;
event.time = 0;
event.param = _desc.startScriptNum;
event.param = _desc.startScriptEntrypointNumber;
event.param2 = 0; // Action
event.param3 = _sceneNumber; // Object
event.param4 = 0; // With Object - TODO: should be 'entrance'
@ -695,9 +695,9 @@ int Scene::loadSceneDescriptor(uint32 res_number) {
_desc.resListRN = readS.readSint16();
_desc.endSlope = readS.readSint16();
_desc.beginSlope = readS.readSint16();
_desc.scriptNum = readS.readUint16();
_desc.sceneScriptNum = readS.readUint16();
_desc.startScriptNum = readS.readUint16();
_desc.scriptModuleNumber = readS.readUint16();
_desc.sceneScriptEntrypointNumber = readS.readUint16();
_desc.startScriptEntrypointNumber = readS.readUint16();
_desc.musicRN = readS.readSint16();
RSC_FreeResource(scene_desc_data);
@ -930,7 +930,7 @@ int Scene::endScene() {
_sceneProc(SCENE_END, &scene_info, this);
if (_desc.scriptNum > 0) {
if (_desc.scriptModuleNumber > 0) {
_vm->_script->freeScript();
}
@ -1002,9 +1002,9 @@ void Scene::cmdSceneInfo() {
_vm->_console->DebugPrintf(fmt, "Resource list R#:", _desc.resListRN);
_vm->_console->DebugPrintf(fmt, "End slope:", _desc.endSlope);
_vm->_console->DebugPrintf(fmt, "Begin slope:", _desc.beginSlope);
_vm->_console->DebugPrintf(fmt, "Script resource:", _desc.scriptNum);
_vm->_console->DebugPrintf(fmt, "Scene script:", _desc.sceneScriptNum);
_vm->_console->DebugPrintf(fmt, "Start script:", _desc.startScriptNum);
_vm->_console->DebugPrintf(fmt, "scriptModuleNumber:", _desc.scriptModuleNumber);
_vm->_console->DebugPrintf(fmt, "sceneScriptEntrypointNumber:", _desc.sceneScriptEntrypointNumber);
_vm->_console->DebugPrintf(fmt, "startScriptEntrypointNumber:", _desc.startScriptEntrypointNumber);
_vm->_console->DebugPrintf(fmt, "Music R#", _desc.musicRN);
}
@ -1084,12 +1084,12 @@ int Scene::defaultScene(int param, SCENE_INFO *scene_info) {
_vm->_events->chain(q_event, &event);
// Start the scene main script
if (_desc.sceneScriptNum > 0) {
if (_desc.sceneScriptEntrypointNumber > 0) {
event.type = ONESHOT_EVENT;
event.code = SCRIPT_EVENT;
event.op = EVENT_EXEC_NONBLOCKING;
event.time = 0;
event.param = _desc.sceneScriptNum;
event.param = _desc.sceneScriptEntrypointNumber;
event.param2 = 0; // Action
event.param3 = _sceneNumber; // Object
event.param4 = 0; // With Object - TODO: should be 'entrance'

View File

@ -99,14 +99,14 @@ struct SCENE_RESLIST {
#define SAGA_SCENE_DESC_LEN 16
struct SCENE_DESC {
struct SceneDescription {
int16 flags;
int16 resListRN;
int16 endSlope;
int16 beginSlope;
uint16 scriptNum;
uint16 sceneScriptNum;
uint16 startScriptNum;
uint16 scriptModuleNumber;
uint16 sceneScriptEntrypointNumber;
uint16 startScriptEntrypointNumber;
int16 musicRN;
SCENE_RESLIST *resList;
size_t resListCnt;
@ -139,7 +139,7 @@ enum SCENE_FADE_TYPES {
struct SCENE_QUEUE {
uint32 scene_n;
SCENE_DESC *scene_desc;
SceneDescription* sceneDescription;
int load_flag;
SCENE_PROC *scene_proc;
int scene_skiptarget;
@ -203,7 +203,8 @@ class Scene {
int endScene();
int queueScene(SCENE_QUEUE *scene_queue);
int draw(SURFACE *);
int getFlags() { return _desc.flags; }
int getFlags() const { return _desc.flags; }
int getScriptModuleNumber() const { return _desc.scriptModuleNumber; }
bool isInDemo() { return !_inGame; }
void getBGMaskInfo(int &width, int &height, byte *&buffer, size_t &bufferLength);
@ -232,8 +233,7 @@ class Scene {
int currentSceneNumber() { return _sceneNumber; }
private:
int loadScene(int scene, int load_flag, SCENE_PROC scene_proc, SCENE_DESC *,
int fadeIn);
int loadScene(int scene, int load_flag, SCENE_PROC scene_proc, SceneDescription *, int fadeIn);
int loadSceneDescriptor(uint32 res_number);
int loadSceneResourceList(uint32 res_number);
int processSceneResources();
@ -253,7 +253,7 @@ class Scene {
int _sceneResNum;
bool _inGame;
bool _loadDesc;
SCENE_DESC _desc;
SceneDescription _desc;
int _resListEntries;
SCENE_RESLIST *_resList;
int _animEntries;

View File

@ -31,6 +31,12 @@
#include "saga/script.h"
#include "saga/stream.h"
#include "saga/interface.h"
#include "saga/actordata.h"
#include "saga/scene.h"
#include "saga/events.h"
#include "saga/actor.h"
#include "saga/objectdata.h"
#include "saga/objectmap.h"
namespace Saga {
@ -61,6 +67,7 @@ Script::Script() {
_stickyVerb = kVerbWalkTo;
_leftButtonVerb = kVerbNone;
_rightButtonVerb = kVerbNone;
_pointerObject = 0;
_dataBuf[0].data = _dataBuf[1].data = (ScriptDataWord *)calloc(SCRIPT_DATABUF_LEN, sizeof(ScriptDataWord));;
_dataBuf[0].length = _dataBuf[1].length = SCRIPT_DATABUF_LEN;
@ -256,7 +263,7 @@ int Script::getBit(int bufNumber, ScriptDataWord bitNumber, int *bitState) {
}
// Loads a script; including script bytecode and dialogue list
int Script::loadScript(int script_num) {
int Script::loadScript(int scriptModuleNumber) {
ScriptData *script_data;
byte *bytecode_p;
size_t bytecode_len;
@ -270,8 +277,8 @@ int Script::loadScript(int script_num) {
int result;
// Validate script number
if ((script_num < 0) || (script_num > _scriptLUTMax)) {
warning("Script::loadScript(): Invalid script number");
if ((scriptModuleNumber < 0) || (scriptModuleNumber > _scriptLUTMax)) {
warning("Script::loadScript(): Invalid script module number");
return FAILURE;
}
@ -279,7 +286,7 @@ int Script::loadScript(int script_num) {
freeScript();
// Initialize script data structure
debug(0, "Loading script data for script #%d", script_num);
debug(0, "Loading script data for script module #%d", scriptModuleNumber);
script_data = (ScriptData *)malloc(sizeof(*script_data));
if (script_data == NULL) {
@ -293,7 +300,7 @@ int Script::loadScript(int script_num) {
script_data->voice = NULL;
// Load script bytecode
scriptl_rn = _scriptLUT[script_num].script_rn;
scriptl_rn = _scriptLUT[scriptModuleNumber].script_rn;
result = RSC_LoadResource(_scriptContext, scriptl_rn, &bytecode_p, &bytecode_len);
if (result != SUCCESS) {
@ -309,7 +316,7 @@ int Script::loadScript(int script_num) {
}
// Load script strings list
stringsResourceId = _scriptLUT[script_num].diag_list_rn;
stringsResourceId = _scriptLUT[scriptModuleNumber].diag_list_rn;
// Load strings list resource
result = RSC_LoadResource(_scriptContext, stringsResourceId, &stringsPointer, &stringsLength);
@ -323,7 +330,7 @@ int Script::loadScript(int script_num) {
// Load voice resource lookup table
if (_voiceLUTPresent) {
voicelut_rn = _scriptLUT[script_num].voice_lut_rn;
voicelut_rn = _scriptLUT[scriptModuleNumber].voice_lut_rn;
// Load voice LUT resource
result = RSC_LoadResource(_scriptContext, voicelut_rn, &voicelut_p, &voicelut_len);
@ -492,7 +499,7 @@ VOICE_LUT *Script::loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, Scr
return voice_lut;
}
void Script::scriptError(SCRIPT_THREAD *thread, const char *format, ...) {
void Script::scriptError(ScriptThread *thread, const char *format, ...) {
char buf[STRINGBUFLEN];
va_list argptr;
@ -501,8 +508,8 @@ void Script::scriptError(SCRIPT_THREAD *thread, const char *format, ...) {
va_end (argptr);
thread->flags |= kTFlagAborted;
debug(0, "Script::scriptError %X: %s", thread->i_offset, buf);
_vm->_console->DebugPrintf("Script::scriptError %X: %s", thread->i_offset, buf);
debug(0, "Script::scriptError %X: %s", thread->instructionOffset, buf);
_vm->_console->DebugPrintf("Script::scriptError %X: %s", thread->instructionOffset, buf);
}
void Script::scriptInfo() {
@ -536,7 +543,7 @@ void Script::scriptExec(int argc, const char **argv) {
if (_dbg_thread == NULL) {
_vm->_console->DebugPrintf("Creating debug thread...\n");
_dbg_thread = SThreadCreate();
_dbg_thread = createThread();
if (_dbg_thread == NULL) {
_vm->_console->DebugPrintf("Thread creation failed.\n");
return;
@ -548,7 +555,7 @@ void Script::scriptExec(int argc, const char **argv) {
return;
}
SThreadExecute(_dbg_thread, ep_num);
executeThread(_dbg_thread, ep_num);
}
// verb
@ -641,6 +648,198 @@ void Script::setRightButtonVerb(int verb) {
}
void Script::doVerb() {
int scriptEntrypointNumber = 0;
int scriptModuleNumber = 0;
int objectType;
EVENT event;
const char *excuseText;
int excuseSampleResourceId;
objectType = objectIdType(_pendingObject[0]);
if (_pendingVerb == kVerbGive) {
scriptEntrypointNumber = _vm->getObjectScriptEntrypointNumber(_pendingObject[1]);
if (_vm->getObjectFlags(_pendingObject[1]) & (kFollower|kProtagonist|kExtended)) {
scriptModuleNumber = 0;
} else {
scriptModuleNumber = _vm->_scene->getScriptModuleNumber();
}
} else {
if (_pendingVerb == kVerbUse) {
if ((objectIdType(_pendingObject[1]) > kGameObjectNone) && (objectType < objectIdType(_pendingObject[1]))) {
SWAP(_pendingObject[0], _pendingObject[1]);
objectType = objectIdType(_pendingObject[0]);
}
}
if (objectType == kGameObjectHitZone) {
scriptModuleNumber = _vm->_scene->getScriptModuleNumber();
//TODO: check HitZone Exit
} else {
if (objectType & (kGameObjectActor | kGameObjectObject)) {
scriptEntrypointNumber = _vm->getObjectScriptEntrypointNumber(_pendingObject[0]);
if ((objectType == kGameObjectActor) && !(_vm->getObjectFlags(_pendingObject[0]) & (kFollower|kProtagonist|kExtended))) {
scriptModuleNumber = _vm->_scene->getScriptModuleNumber();
} else {
scriptModuleNumber = 0;
}
}
}
}
if (scriptEntrypointNumber > 0) {
if (scriptModuleNumber != _vm->_scene->getScriptModuleNumber()) {
warning("scriptModuleNumber != _vm->_scene->getScriptModuleNumber()");
}
event.type = ONESHOT_EVENT;
event.code = SCRIPT_EVENT;
event.op = EVENT_EXEC_NONBLOCKING;
event.time = 0;
event.param = scriptEntrypointNumber;
event.param2 = _pendingVerb; // Action
event.param3 = _pendingObject[0]; // Object
event.param4 = _pendingObject[1]; // With Object
event.param5 = (objectType == kGameObjectActor) ? _pendingObject[0] : ID_PROTAG; // Actor
_vm->_events->queue(&event);
} else {
_vm->getExcuseInfo(_pendingVerb, excuseText, excuseSampleResourceId);
if (excuseText)
_vm->_actor->actorSpeech(ID_PROTAG, &excuseText, 1, excuseSampleResourceId, 0);
}
if ((_currentVerb == kVerbWalkTo) || (_currentVerb == kVerbLookAt)) {
_stickyVerb = _currentVerb;
}
_pendingVerb = kVerbNone;
_currentObject[0] = _currentObject[1] = ID_NOTHING;
setLeftButtonVerb(_stickyVerb);
setPointerVerb();
}
void Script::setPointerVerb() {
Point mousePoint;
mousePoint = _vm->getMousePos();
if (_vm->_interface->isActive()) {
_pointerObject = ID_PROTAG;
whichObject(mousePoint);
}
}
void Script::whichObject(const Point& mousePointer) {
uint16 objectId;
int16 objectFlags;
int newRightButtonVerb;
uint16 newObjectId;
ActorData *actor;
Location pickLocation;
int hitZoneId;
HitZone * hitZone;
objectId = ID_NOTHING;
objectFlags = 0;
_leftButtonVerb = _currentVerb;
newRightButtonVerb = kVerbNone;
if (_vm->_actor->_protagonist->currentAction == kActionWalkDir) {
} else {
newObjectId = _vm->_actor->testHit(mousePointer);
if (newObjectId != ID_NOTHING) {
if (objectIdType(newObjectId) == kGameObjectObject) {
objectId = newObjectId;
objectFlags = 0;
newRightButtonVerb = kVerbLookAt;
if ((_currentVerb == kVerbTalkTo) || ((_currentVerb == kVerbGive) && _firstObjectSet)) {
objectId = ID_NOTHING;
newObjectId = ID_NOTHING;
}
} else {
actor = _vm->_actor->getActor(newObjectId);
objectId = newObjectId;
objectFlags = kObjUseWith;
newRightButtonVerb = kVerbTalkTo;
if ((_currentVerb == kVerbPickUp) ||
(_currentVerb == kVerbOpen) ||
(_currentVerb == kVerbClose) ||
((_currentVerb == kVerbGive) && !_firstObjectSet) ||
((_currentVerb == kVerbUse) && !(actor->flags & kFollower))) {
objectId = ID_NOTHING;
newObjectId = ID_NOTHING;
}
}
}
if (newObjectId == ID_NOTHING) {
/* struct HitZone far *newZone = NULL;
UWORD zone;*/
if (_vm->_scene->getFlags() & kSceneFlagISO) {
//todo: it
} else {
pickLocation.x = mousePointer.x;
pickLocation.y = mousePointer.y;
pickLocation.z = 0;
}
hitZoneId = _vm->_scene->_objectMap->hitTest(mousePointer);
if ((hitZoneId != -1) && 0) { //TODO: do it
//hitZone = _vm->_scene->_objectMap->getZone(hitZoneId);
//objectId = hitZone->objectId;
objectFlags = 0;
newRightButtonVerb = hitZone->getRightButtonVerb() & 0x7f;
if (newRightButtonVerb == kVerbWalkOnly) {
if (_firstObjectSet) {
objectId = ID_NOTHING;
} else {
newRightButtonVerb = _leftButtonVerb = kVerbWalkTo;
}
} else {
if (_firstObjectSet) {
objectId = ID_NOTHING;
} else {
newRightButtonVerb = _leftButtonVerb = kVerbLookAt;
}
}
if (newRightButtonVerb >= kVerbOptions) {
newRightButtonVerb = kVerbNone;
}
if ((_currentVerb == kVerbTalkTo) || ((_currentVerb == kVerbGive) && !_firstObjectSet)) {
objectId = ID_NOTHING;
newObjectId = ID_NOTHING;
}
if ((_leftButtonVerb == kVerbUse) && (hitZone->getRightButtonVerb() & 0x80)) {
objectFlags = kObjUseWith;
}
}
}
}
if (objectId != _pointerObject) {
_pointerObject = objectId;
_currentObject[_firstObjectSet ? 1 : 0] = objectId;
_currentObjectFlags[_firstObjectSet ? 1 : 0] = objectFlags;
if (_pendingVerb == kVerbNone) {
showVerb();
}
}
if (newRightButtonVerb != _rightButtonVerb) {
setRightButtonVerb(newRightButtonVerb);
}
}
// console wrappers

View File

@ -127,15 +127,15 @@ enum WalkFlags {
kWalkFace = (1<<5)
};
struct SCRIPT_THREAD {
struct ScriptThread {
int flags; // ThreadFlags
int waitType; // ThreadWaitTypes
void *threadObj; // which object we're handling
uint sleepTime;
int ep_num; // Entrypoint number
unsigned long ep_offset; // Entrypoint offset
unsigned long i_offset; // Instruction offset
int entrypointNumber; // Entrypoint number
unsigned long entrypointOffset; // Entrypoint offset
unsigned long instructionOffset; // Instruction offset
// The scripts are allowed to access the stack like any other memory
// area. It's therefore probably quite important that our stacks work
@ -183,10 +183,12 @@ struct SCRIPT_THREAD {
sleepTime = aSleepTime;
}
SCRIPT_THREAD() { memset(this, 0, sizeof(*this)); }
ScriptThread() {
memset(this, 0, sizeof(*this));
}
};
typedef SortedList<SCRIPT_THREAD> ScriptThreadList;
typedef SortedList<ScriptThread> ScriptThreadList;
struct PROC_TBLENTRY {
size_t name_offset;
@ -224,7 +226,7 @@ struct ScriptDataBuf {
int length;
};
#define SCRIPTFUNC_PARAMS SCRIPT_THREAD *thread, int nArgs
#define SCRIPTFUNC_PARAMS ScriptThread *thread, int nArgs
class Script {
public:
@ -251,11 +253,19 @@ public:
void doVerb();
void showVerb();
void setVerb(int verb);
void setLeftButtonVerb(int verb);
void setRightButtonVerb(int verb);
int getCurrentVerb() const { return _currentVerb; }
void setPointerVerb();
void whichObject(const Point& mousePointer);
void setLeftButtonVerb(int verb);
int getLeftButtonVerb() const { return _leftButtonVerb; }
void setRightButtonVerb(int verb);
int getRightButtonVerb() const { return _rightButtonVerb; }
void setNonPlayfieldVerb() {
setRightButtonVerb(kVerbNone);
_pointerObject = ID_NOTHING;
_currentObject[_firstObjectSet ? 1 : 0] = ID_NOTHING;
}
void scriptInfo();
void scriptExec(int argc, const char **argv);
@ -276,13 +286,15 @@ protected:
bool _firstObjectSet;
bool _secondObjectNeeded;
uint16 _currentObject[2];
int16 _currentObjectFlags[2];
uint16 _pendingObject[2];
int _currentVerb;
int _stickyVerb;
int _leftButtonVerb;
int _rightButtonVerb;
int _pendingVerb;
uint16 _pointerObject;
public:
bool _skipSpeeches;
@ -290,27 +302,27 @@ public:
int _dbg_singlestep;
int _dbg_dostep;
SCRIPT_THREAD *_dbg_thread;
ScriptThread *_dbg_thread;
TEXTLIST_ENTRY *_dbg_txtentry;
public:
SCRIPT_THREAD *SThreadCreate();
int SThreadExecute(SCRIPT_THREAD *thread, int ep_num);
ScriptThread *createThread();
int executeThread(ScriptThread *thread, int entrypointNumber);
int executeThreads(uint msec);
int SThreadDebugStep();
void SThreadCompleteThread(void);
void completeThread(void);
void wakeUpActorThread(int waitType, void *threadObj);
void wakeUpThreads(int waitType);
void wakeUpThreadsDelayed(int waitType, int sleepTime);
private:
void setFramePtr(SCRIPT_THREAD *thread, int newPtr);
unsigned char *SThreadGetReadPtr(SCRIPT_THREAD *thread);
void setFramePtr(ScriptThread *thread, int newPtr);
unsigned char *SThreadGetReadPtr(ScriptThread *thread);
unsigned long SThreadGetReadOffset(const byte *read_p);
size_t SThreadGetReadLen(SCRIPT_THREAD *thread);
void runThread(SCRIPT_THREAD *thread, int instr_limit);
int SThreadSetEntrypoint(SCRIPT_THREAD *thread, int ep_num);
size_t SThreadGetReadLen(ScriptThread *thread);
void runThread(ScriptThread *thread, int instr_limit);
void setThreadEntrypoint(ScriptThread *thread, int entrypointNumber);
private:
typedef int (Script::*ScriptFunctionType)(SCRIPTFUNC_PARAMS);
@ -322,8 +334,8 @@ private:
const ScriptFunctionDescription *_scriptFunctionsList;
void setupScriptFuncList(void);
void scriptError(SCRIPT_THREAD *thread, const char *format, ...);
int SDebugPrintInstr(SCRIPT_THREAD *thread);
void scriptError(ScriptThread *thread, const char *format, ...);
int SDebugPrintInstr(ScriptThread *thread);
int SF_putString(SCRIPTFUNC_PARAMS);
int sfWait(SCRIPTFUNC_PARAMS);

View File

@ -37,7 +37,7 @@ namespace Saga {
#define SD_DISPLAY_LEN 128
#define SD_ADDTXT(x) strncat(disp_buf, x, SD_DISPLAY_LEN);
int Script::SDebugPrintInstr(SCRIPT_THREAD *thread) {
int Script::SDebugPrintInstr(ScriptThread *thread) {
TEXTLIST_ENTRY tl_e;
char tmp_buf[80] = { 0 };
static char disp_buf[SD_DISPLAY_LEN] = { 0 };
@ -66,11 +66,11 @@ int Script::SDebugPrintInstr(SCRIPT_THREAD *thread) {
tl_e.display = 1;
MemoryReadStream readS(currentScript()->bytecode->bytecode_p
+ thread->i_offset,
+ thread->instructionOffset,
currentScript()->bytecode->bytecode_len
- thread->i_offset);
- thread->instructionOffset);
in_char = readS.readByte();
sprintf(tmp_buf, "%04lX | %02X | ", thread->i_offset, in_char);
sprintf(tmp_buf, "%04lX | %02X | ", thread->instructionOffset, in_char);
strncat(disp_buf, tmp_buf, SD_DISPLAY_LEN);
switch (in_char) {

View File

@ -209,7 +209,7 @@ int Script::SF_mainMode(SCRIPTFUNC_PARAMS) {
// Param3: actor y
int Script::sfScriptWalkTo(SCRIPTFUNC_PARAMS) {
uint16 actorId;
ActorLocation actorLocation;
Location actorLocation;
ActorData *actor;
actorId = getSWord(thread->pop());
@ -566,7 +566,7 @@ int Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
// Param3: actor y
int Script::sfScriptWalkToAsync(SCRIPTFUNC_PARAMS) {
uint16 actorId;
ActorLocation actorLocation;
Location actorLocation;
ActorData *actor;
actorId = getSWord(thread->pop());
@ -619,7 +619,7 @@ int Script::sfSetActorState(SCRIPTFUNC_PARAMS) {
// Param3: actor pos y
int Script::scriptMoveTo(SCRIPTFUNC_PARAMS) {
uint16 actorId;
ActorLocation actorLocation;
Location actorLocation;
ActorData *actor;
actorId = getSWord(thread->pop());
@ -688,7 +688,7 @@ int Script::sfSwapActors(SCRIPTFUNC_PARAMS) {
uint16 actorId2;
ActorData *actor1;
ActorData *actor2;
ActorLocation location;
Location location;
actorId1 = getSWord(thread->pop());
actorId2 = getSWord(thread->pop());
@ -751,7 +751,7 @@ int Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) {
// Param4: actor walk flag
int Script::sfScriptWalk(SCRIPTFUNC_PARAMS) {
uint16 actorId;
ActorLocation actorLocation;
Location actorLocation;
ActorData *actor;
uint16 walkFlags;
@ -917,7 +917,7 @@ int Script::SF_scriptSpecialWalk(SCRIPTFUNC_PARAMS) {
// Param6: actor frame number
int Script::sfPlaceActor(SCRIPTFUNC_PARAMS) {
uint16 actorId;
ActorLocation actorLocation;
Location actorLocation;
int actorDirection;
int frameType;
int frameOffset;

View File

@ -37,34 +37,34 @@
namespace Saga {
void Script::setFramePtr(SCRIPT_THREAD *thread, int newPtr) {
void Script::setFramePtr(ScriptThread *thread, int newPtr) {
thread->framePtr = newPtr;
dataBuffer(3)->length = ARRAYSIZE(thread->stackBuf) - thread->framePtr;
dataBuffer(3)->data = (ScriptDataWord *) &(thread->stackBuf[newPtr]);
}
SCRIPT_THREAD *Script::SThreadCreate() {
SCRIPT_THREAD *new_thread;
ScriptThread *Script::createThread() {
ScriptThread *newThread;
if (!isInitialized()) {
return NULL;
}
new_thread = _threadList.pushFront().operator->();
newThread = _threadList.pushFront().operator->();
new_thread->stackPtr = ARRAYSIZE(new_thread->stackBuf) - 1;
setFramePtr(new_thread, new_thread->stackPtr);
newThread->stackPtr = ARRAYSIZE(newThread->stackBuf) - 1;
setFramePtr(newThread, newThread->stackPtr);
new_thread->flags = kTFlagWaiting;
new_thread->waitType = kWaitTypePause;
newThread->flags = kTFlagWaiting;
newThread->waitType = kWaitTypePause;
dataBuffer(4)->length = ARRAYSIZE(new_thread->threadVars);
dataBuffer(4)->data = new_thread->threadVars;
return new_thread;
dataBuffer(4)->length = ARRAYSIZE(newThread->threadVars);
dataBuffer(4)->data = newThread->threadVars;
return newThread;
}
void Script::wakeUpActorThread(int waitType, void *threadObj) {
SCRIPT_THREAD *thread;
ScriptThread *thread;
ScriptThreadList::iterator threadIterator;
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
@ -76,7 +76,7 @@ void Script::wakeUpActorThread(int waitType, void *threadObj) {
}
void Script::wakeUpThreads(int waitType) {
SCRIPT_THREAD *thread;
ScriptThread *thread;
ScriptThreadList::iterator threadIterator;
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
@ -88,7 +88,7 @@ void Script::wakeUpThreads(int waitType) {
}
void Script::wakeUpThreadsDelayed(int waitType, int sleepTime) {
SCRIPT_THREAD *thread;
ScriptThread *thread;
ScriptThreadList::iterator threadIterator;
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
@ -101,7 +101,7 @@ void Script::wakeUpThreadsDelayed(int waitType, int sleepTime) {
}
int Script::executeThreads(uint msec) {
SCRIPT_THREAD *thread;
ScriptThread *thread;
ScriptThreadList::iterator threadIterator;
if (!isInitialized()) {
@ -114,8 +114,8 @@ int Script::executeThreads(uint msec) {
thread = threadIterator.operator->();
if (thread->flags & (kTFlagFinished | kTFlagAborted)) {
//if (thread->flags & kTFlagFinished) // FIXME. Missing function
if (thread->flags & kTFlagFinished)
setPointerVerb();
threadIterator = _threadList.erase(threadIterator);
continue;
@ -152,12 +152,12 @@ int Script::executeThreads(uint msec) {
return SUCCESS;
}
void Script::SThreadCompleteThread(void) {
void Script::completeThread(void) {
for (int i = 0; i < 40 && !_threadList.isEmpty() ; i++)
executeThreads(0);
}
int Script::SThreadSetEntrypoint(SCRIPT_THREAD *thread, int ep_num) {
void Script::setThreadEntrypoint(ScriptThread *thread, int entrypointNumber) {
SCRIPT_BYTECODE *bytecode;
int max_entrypoint;
@ -166,26 +166,24 @@ int Script::SThreadSetEntrypoint(SCRIPT_THREAD *thread, int ep_num) {
bytecode = currentScript()->bytecode;
max_entrypoint = bytecode->n_entrypoints;
if ((ep_num < 0) || (ep_num >= max_entrypoint)) {
return FAILURE;
if ((entrypointNumber < 0) || (entrypointNumber >= max_entrypoint)) {
error("Script::setThreadEntrypoint wrong entrypointNumber");
}
thread->ep_num = ep_num;
thread->ep_offset = bytecode->entrypoints[ep_num].offset;
return SUCCESS;
thread->entrypointNumber = entrypointNumber;
thread->entrypointOffset = bytecode->entrypoints[entrypointNumber].offset;
}
int Script::SThreadExecute(SCRIPT_THREAD *thread, int ep_num) {
int Script::executeThread(ScriptThread *thread, int entrypointNumber) {
assert(isInitialized());
if ((currentScript() == NULL) || (!currentScript()->loaded)) {
return FAILURE;
}
SThreadSetEntrypoint(thread, ep_num);
setThreadEntrypoint(thread, entrypointNumber);
thread->i_offset = thread->ep_offset;
thread->instructionOffset = thread->entrypointOffset;
thread->flags = kTFlagNone;
return SUCCESS;
@ -193,16 +191,16 @@ int Script::SThreadExecute(SCRIPT_THREAD *thread, int ep_num) {
unsigned char *Script::SThreadGetReadPtr(SCRIPT_THREAD *thread) {
return currentScript()->bytecode->bytecode_p + thread->i_offset;
unsigned char *Script::SThreadGetReadPtr(ScriptThread *thread) {
return currentScript()->bytecode->bytecode_p + thread->instructionOffset;
}
unsigned long Script::SThreadGetReadOffset(const byte *read_p) {
return (unsigned long)(read_p - (unsigned char *)currentScript()->bytecode->bytecode_p);
}
size_t Script::SThreadGetReadLen(SCRIPT_THREAD *thread) {
return currentScript()->bytecode->bytecode_len - thread->i_offset;
size_t Script::SThreadGetReadLen(ScriptThread *thread) {
return currentScript()->bytecode->bytecode_len - thread->instructionOffset;
}
@ -216,7 +214,7 @@ int Script::SThreadDebugStep() {
return SUCCESS;
}
void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
void Script::runThread(ScriptThread *thread, int instr_limit) {
int instr_count;
uint32 saved_offset;
ScriptDataWord param1;
@ -251,23 +249,23 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
dataBuffer(2)->length = currentScript()->bytecode->bytecode_len / sizeof(ScriptDataWord);
dataBuffer(2)->data = (ScriptDataWord *) currentScript()->bytecode->bytecode_p;
scriptS.seek(thread->i_offset);
scriptS.seek(thread->instructionOffset);
for (instr_count = 0; instr_count < instr_limit; instr_count++) {
if (thread->flags & (kTFlagAsleep))
break;
saved_offset = thread->i_offset;
saved_offset = thread->instructionOffset;
operandChar = scriptS.readByte();
// debug print (opCode name etc) should be placed here
// SDebugPrintInstr(thread)
// debug(2, "Executing thread offset: %lu (%x) stack: %d", thread->i_offset, operandChar, thread->stackSize());
// debug(2, "Executing thread offset: %lu (%x) stack: %d", thread->instructionOffset, operandChar, thread->stackSize());
switch (operandChar) {
case 0x01: // nextblock
// Some sort of "jump to the start of the next memory
// page" instruction, I think.
thread->i_offset = 1024 * ((thread->i_offset / 1024) + 1);
thread->instructionOffset = 1024 * ((thread->instructionOffset / 1024) + 1);
break;
// STACK INSTRUCTIONS
@ -356,7 +354,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
// counter as a pointer here. But I don't think
// we will have to do that.
thread->push(data);
thread->i_offset = (unsigned long)param1;
thread->instructionOffset = (unsigned long)param1;
}
break;
case opCcall: // Call function
@ -377,7 +375,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
scriptFunction = _scriptFunctionsList[functionNumber].scriptFunction;
scriptFunctionReturnValue = (this->*scriptFunction)(thread, argumentsCount);
if (scriptFunctionReturnValue != SUCCESS) {
_vm->_console->DebugPrintf(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->i_offset, scriptFunctionReturnValue);
_vm->_console->DebugPrintf(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->instructionOffset, scriptFunctionReturnValue);
}
if (functionNumber == 16) { // SF_gotoScene
@ -408,7 +406,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
thread->flags |= kTFlagFinished;
return;
} else {
thread->i_offset = thread->pop();
thread->instructionOffset = thread->pop();
/* int n_args = */ thread->pop();
if (operandChar == opReturn)
thread->push(scriptRetVal);
@ -420,14 +418,14 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
// (JMP): Unconditional jump
case 0x1D:
param1 = scriptS.readUint16LE();
thread->i_offset = (unsigned long)param1;
thread->instructionOffset = (unsigned long)param1;
break;
// (JNZP): Jump if nonzero + POP
case 0x1E:
param1 = scriptS.readUint16LE();
data = thread->pop();
if (data) {
thread->i_offset = (unsigned long)param1;
thread->instructionOffset = (unsigned long)param1;
}
break;
// (JZP): Jump if zero + POP
@ -435,7 +433,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
param1 = scriptS.readUint16LE();
data = thread->pop();
if (!data) {
thread->i_offset = (unsigned long)param1;
thread->instructionOffset = (unsigned long)param1;
}
break;
// (JNZ): Jump if nonzero
@ -443,7 +441,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
param1 = scriptS.readUint16LE();
data = thread->stackTop();
if (data) {
thread->i_offset = (unsigned long)param1;
thread->instructionOffset = (unsigned long)param1;
}
break;
// (JZ): Jump if zero
@ -451,7 +449,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
param1 = scriptS.readUint16LE();
data = thread->stackTop();
if (!data) {
thread->i_offset = (unsigned long)param1;
thread->instructionOffset = (unsigned long)param1;
}
break;
// (SWCH): Switch
@ -470,7 +468,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
switch_jmp = scriptS.readUint16LE();
// Found the specified case
if (data == (ScriptDataWord) switch_num) {
thread->i_offset = switch_jmp;
thread->instructionOffset = switch_jmp;
case_found = 1;
break;
}
@ -479,7 +477,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
// Jump to default case
if (!case_found) {
default_jmp = scriptS.readUint16LE();
thread->i_offset = default_jmp;
thread->instructionOffset = default_jmp;
}
}
break;
@ -497,7 +495,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
uint16 offset = scriptS.readUint16LE();
if (branch_probability > probability) {
thread->i_offset = offset;
thread->instructionOffset = offset;
break;
}
@ -770,7 +768,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
if (!(speechFlags & kSpeakAsync)) {
thread->wait(kWaitTypeSpeech);
thread->i_offset = scriptS.pos();
thread->instructionOffset = scriptS.pos();
return;
}
}
@ -803,7 +801,7 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
scriptS.readUint16LE();
scriptS.readUint16LE();
iparam1 = (long)scriptS.readByte();
thread->i_offset += iparam1;
thread->instructionOffset += iparam1;
break;
// End instruction list
@ -814,14 +812,14 @@ void Script::runThread(SCRIPT_THREAD *thread, int instr_limit) {
}
// Set instruction offset only if a previous instruction didn't branch
if (saved_offset == thread->i_offset) {
thread->i_offset = scriptS.pos();
if (saved_offset == thread->instructionOffset) {
thread->instructionOffset = scriptS.pos();
} else {
if (thread->i_offset >= scriptS.size()) {
if (thread->instructionOffset >= scriptS.size()) {
scriptError(thread, "Out of range script execution");
return;
} else {
scriptS.seek(thread->i_offset);
scriptS.seek(thread->instructionOffset);
}
}

View File

@ -60,9 +60,9 @@ Scene.c
resInfo->loadList _desc.resListRN
resInfo->horizon _desc.endSlope
resInfo->nearFigureLimit _desc.beginSlope
resInfo->scriptModule _desc.scriptNum
resInfo->entryScript _desc.sceneScriptNum
resInfo->preScript _desc.startScriptNum
resInfo->scriptModule _desc.scriptModuleNumber
resInfo->entryScript _desc.sceneScriptEntrypointNumber
resInfo->preScript _desc.startScriptEntrypointNumber
resInfo->backgroundMusic _desc.musicRN
thisScene->ID currentSceneNumber()