[Scummvm-cvs-logs] scummvm master -> 5407bb8fcdbfdf0d3576e156a84f5fd2709ae6e3
fuzzie
fuzzie at fuzzie.org
Sun Jan 29 08:59:15 CET 2012
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
5407bb8fcd SCUMM: Revert accidentally-committed 0ceeee8148..f0172ba15.
Commit: 5407bb8fcdbfdf0d3576e156a84f5fd2709ae6e3
https://github.com/scummvm/scummvm/commit/5407bb8fcdbfdf0d3576e156a84f5fd2709ae6e3
Author: Alyssa Milburn (fuzzie at fuzzie.org)
Date: 2012-01-28T23:57:42-08:00
Commit Message:
SCUMM: Revert accidentally-committed 0ceeee8148..f0172ba15.
Changed paths:
engines/scumm/actor.cpp
engines/scumm/actor.h
engines/scumm/object.cpp
engines/scumm/object.h
engines/scumm/saveload.cpp
engines/scumm/script.cpp
engines/scumm/script_v0.cpp
engines/scumm/script_v2.cpp
engines/scumm/script_v5.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm.h
engines/scumm/scumm_v0.h
engines/scumm/scumm_v2.h
engines/scumm/scumm_v5.h
engines/scumm/vars.cpp
engines/scumm/verbs.cpp
engines/scumm/verbs.h
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 70e051e..eb23c30 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -1323,23 +1323,23 @@ static const byte v0ActorSounds[24] = {
0x06, // Bernard
0x06, // Wendy
0x00, // Jeff
- 0x46, // Radiation Suit
+ 0x46, // ???
0x06, // Dr Fred
0x06, // Nurse Edna
0x06, // Weird Ed
0x06, // Dead Cousin Ted
0xFF, // Purple Tentacle
0xFF, // Green Tentacle
- 0x06, // Meteor police
- 0xC0, // Meteor
- 0x06, // Mark Eteer
- 0x06, // Talkshow Host
- 0x00, // Plant
- 0xC0, // Meteor Radiation
- 0xC0, // Edsel (small, outro)
- 0x00, // Meteor (small, intro)
- 0x06, // Sandy (Lab)
- 0x06, // Sandy (Cut-Scene)
+ 0x06, // Meteor
+ 0xC0, // Plant
+ 0x06, // ???
+ 0x06, // ???
+ 0x00, // ???
+ 0xC0, // ???
+ 0xC0, // ???
+ 0x00, // ???
+ 0x06, // Sandy
+ 0x06, // ???
};
/* Used in Scumm v5 only. Play sounds associated with actors */
@@ -1355,10 +1355,7 @@ void ScummEngine::playActorSounds() {
} else {
sound = _actors[i]->_sound[0];
}
- // fast mode will flood the queue with walk sounds
- if (!_fastMode) {
- _sound->addSoundToQueue(sound);
- }
+ _sound->addSoundToQueue(sound);
for (j = 1; j < _numActors; j++) {
_actors[j]->_cost.soundCounter = 0;
}
@@ -2298,23 +2295,22 @@ static const char *const v0ActorNames_English[25] = {
"Bernard",
"Wendy",
"Jeff",
- "", // Radiation Suit
+ "",
"Dr Fred",
"Nurse Edna",
"Weird Ed",
"Dead Cousin Ted",
"Purple Tentacle",
"Green Tentacle",
- "", // Meteor Police
"Meteor",
- "", // Mark Eteer
- "", // Talkshow Host
+ "",
+ "",
+ "",
"Plant",
- "", // Meteor Radiation
- "", // Edsel (small, outro)
- "", // Meteor (small, intro)
- "Sandy", // (Lab)
- "", // Sandy (Cut-Scene)
+ "",
+ "",
+ "",
+ "Sandy"
};
static const char *const v0ActorNames_German[25] = {
@@ -2332,16 +2328,15 @@ static const char *const v0ActorNames_German[25] = {
"Ted",
"Lila Tentakel",
"Gr<nes Tentakel",
- "",
"Meteor",
"",
"",
- "Pflanze",
"",
+ "Pflanze",
"",
"",
- "Sandy",
"",
+ "Sandy"
};
const byte *Actor::getActorName() {
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index d8e3692..1584d0a 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -335,21 +335,10 @@ protected:
virtual void prepareDrawActorCostume(BaseCostumeRenderer *bcr);
};
-enum ActorC64MiscFlags {
- kActorMiscFlagStrong = 0x01, // Kid is strong (Hunk-O-Matic used)
- kActorMiscFlag_02 = 0x02, // ???
- kActorMiscFlag_04 = 0x04, // ???
- kActorMiscFlagEdsEnemy = 0x08, // Kid is not Weird Ed's friend
- kActorMiscFlag_10 = 0x10, // ???
- kActorMiscFlag_20 = 0x20, // ???
- kActorMiscFlagFreeze = 0x40, // Stop moving
- kActorMiscFlagHide = 0x80, // Hide actor (e.g. dead or wearing radiation suit)
-};
-
class ActorC64 : public Actor_v2 {
public:
byte _costCommand, _costFrame;
- byte _miscflags;
+ byte _miscflags; // 0x1: strong, 0x8: Ed's enemy, 0x40: stop moving, 0x80: hide(dead/radiation suit)
byte _speaking, _speakingPrev;
public:
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index 86d9065..da238dc 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -178,7 +178,10 @@ void ScummEngine::clearOwnerOf(int obj) {
// Alternatively, scan the inventory to see if the object is in there...
for (i = 0; i < _numInventory; i++) {
if (_inventory[i] == obj) {
- assert(WIO_INVENTORY == whereIsObject(obj));
+ if (_game.version == 0)
+ assert(WIO_INVENTORY == whereIsObjectInventory(obj));
+ else
+ assert(WIO_INVENTORY == whereIsObject(obj));
// Found the object! Nuke it from the inventory.
_res->nukeResource(rtInventory, i);
@@ -307,50 +310,52 @@ int ScummEngine::getObjectRoom(int obj) const {
int ScummEngine::getObjectIndex(int object) const {
int i;
- int nr = (_game.version != 0) ? object : OBJECT_V0_NR(object);
- if (nr < 1)
+ if (object < 1)
return -1;
for (i = (_numLocalObjects-1); i > 0; i--) {
- if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(object))
- continue;
+ if (_game.version == 0 )
+ if( _objs[i].flags != _v0ObjectFlag )
+ continue;
- if (_objs[i].obj_nr == nr)
+ if (_objs[i].obj_nr == object)
return i;
}
return -1;
}
+int ScummEngine::whereIsObjectInventory(int object) {
+ int res = 0;
+ _v0ObjectInInventory = true;
+ res = whereIsObject(object);
+ _v0ObjectInInventory = false;
+
+ return res;
+}
+
int ScummEngine::whereIsObject(int object) const {
int i;
- // Note: in MMC64 bg objects are greater _numGlobalObjects
- if (_game.version != 0 && object >= _numGlobalObjects)
+ if (object >= _numGlobalObjects)
return WIO_NOT_FOUND;
if (object < 1)
return WIO_NOT_FOUND;
- if ((_game.version != 0 || OBJECT_V0_TYPE(object) == 0) &&
- _objectOwnerTable[object] != OF_OWNER_ROOM)
- {
+ if ((_objectOwnerTable[object] != OF_OWNER_ROOM && _game.version != 0) || _v0ObjectInInventory) {
for (i = 0; i < _numInventory; i++)
if (_inventory[i] == object)
return WIO_INVENTORY;
return WIO_NOT_FOUND;
}
- for (i = (_numLocalObjects-1); i > 0; i--) {
- int nr = (_game.version != 0) ? object : OBJECT_V0_NR(object);
- if (_objs[i].obj_nr == nr) {
- if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(object))
- continue;
+ for (i = (_numLocalObjects-1); i > 0; i--)
+ if ((_objs[i].obj_nr == object && !_v0ObjectIndex) || (_v0ObjectIndex && i == object)) {
if (_objs[i].fl_object_index)
return WIO_FLOBJECT;
return WIO_ROOM;
}
- }
return WIO_NOT_FOUND;
}
@@ -391,7 +396,7 @@ int ScummEngine::getObjectOrActorXY(int object, int &x, int &y) {
* Returns X, Y and direction in angles
*/
void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) {
- int idx = getObjectIndex(object);
+ int idx = (_v0ObjectIndex) ? object : getObjectIndex(object);
assert(idx >= 0);
ObjectData &od = _objs[idx];
int state;
@@ -434,15 +439,8 @@ void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) {
y = od.y_pos + (int16)READ_LE_UINT16(&imhd->old.hotspot[state].y);
}
} else if (_game.version <= 2) {
- if (od.actordir) {
- x = od.walk_x;
- y = od.walk_y;
- } else {
- x = od.x_pos + od.width/2;
- y = od.y_pos + od.height/2;
- }
- x = x >> V12_X_SHIFT;
- y = y >> V12_Y_SHIFT;
+ x = od.walk_x >> V12_X_SHIFT;
+ y = od.walk_y >> V12_Y_SHIFT;
} else {
x = od.walk_x;
y = od.walk_y;
@@ -494,6 +492,14 @@ int ScummEngine::getObjActToObjActDist(int a, int b) {
return getDist(x, y, x2, y2);
}
+int ScummEngine_v0::findObjectIndex(int x, int y) {
+ int objIdx;
+ _v0ObjectIndex = true;
+ objIdx = findObject(x, y);
+ _v0ObjectIndex = false;
+ return objIdx;
+}
+
int ScummEngine::findObject(int x, int y) {
int i, b;
byte a;
@@ -504,7 +510,7 @@ int ScummEngine::findObject(int x, int y) {
continue;
if (_game.version == 0) {
- if (_objs[i].obj_type == 0 && _objs[i].state & kObjectStateUntouchable)
+ if (_objs[i].flags == 0 && _objs[i].state & kObjectStateUntouchable)
continue;
} else {
if (_game.version <= 2 && _objs[i].state & kObjectStateUntouchable)
@@ -524,8 +530,11 @@ int ScummEngine::findObject(int x, int y) {
#endif
if (_objs[i].x_pos <= x && _objs[i].width + _objs[i].x_pos > x &&
_objs[i].y_pos <= y && _objs[i].height + _objs[i].y_pos > y) {
+ // MMC64: Set the object search flag
if (_game.version == 0)
- return OBJECT_V0(_objs[i].obj_nr, _objs[i].obj_type);
+ _v0ObjectFlag = _objs[i].flags;
+ if (_game.version == 0 && _v0ObjectIndex)
+ return i;
else
return _objs[i].obj_nr;
}
@@ -835,7 +844,7 @@ void ScummEngine_v3old::resetRoomObjects() {
char buf[32];
sprintf(buf, "roomobj-%d-", _roomResource);
if (_game.version == 0)
- sprintf(buf + 11, "%d-", od->obj_type);
+ sprintf(buf + 11, "%d-", od->flags);
dumpResource(buf, od->obj_nr, room + od->OBCDoffset);
}
@@ -903,7 +912,7 @@ void ScummEngine_v0::resetRoomObject(ObjectData *od, const byte *room, const byt
ptr -= 2;
od->obj_nr = *(ptr + 6);
- od->obj_type = *(ptr + 7);
+ od->flags = *(ptr + 7);
od->x_pos = *(ptr + 8) * 8;
od->y_pos = ((*(ptr + 9)) & 0x7F) * 8;
@@ -1063,8 +1072,8 @@ void ScummEngine::updateObjectStates() {
int i;
ObjectData *od = &_objs[1];
for (i = 1; i < _numLocalObjects; i++, od++) {
- // V0 MM, objects with type == 1 are room objects (room specific objects, non-pickup)
- if (_game.version == 0 && od->obj_type == 1)
+ // V0 MM, Room objects with Flag == 1 are objects with 'no-state' (room specific objects, non-pickup)
+ if (_game.version == 0 && od->flags == 1)
continue;
if (od->obj_nr > 0)
@@ -1164,7 +1173,7 @@ const byte *ScummEngine::getObjOrActorName(int obj) {
}
}
- objptr = getOBCDFromObject(obj, true);
+ objptr = getOBCDFromObject(obj);
if (objptr == NULL)
return NULL;
@@ -1217,15 +1226,15 @@ void ScummEngine::setObjectName(int obj) {
uint32 ScummEngine::getOBCDOffs(int object) const {
int i;
- if ((_game.version != 0 || OBJECT_V0_TYPE(object) == 0) &&
- _objectOwnerTable[object] != OF_OWNER_ROOM)
+ if ((_objectOwnerTable[object] != OF_OWNER_ROOM && (_game.version != 0)) || _v0ObjectInInventory)
return 0;
+ // V0 MM Return by Index
+ if (_v0ObjectIndex)
+ return _objs[object].OBCDoffset;
+
for (i = (_numLocalObjects-1); i > 0; i--) {
- int nr = (_game.version != 0) ? object : OBJECT_V0_NR(object);
- if (_objs[i].obj_nr == nr) {
- if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(object))
- continue;
+ if (_objs[i].obj_nr == object) {
if (_objs[i].fl_object_index != 0)
return 8;
return _objs[i].OBCDoffset;
@@ -1234,25 +1243,21 @@ uint32 ScummEngine::getOBCDOffs(int object) const {
return 0;
}
-byte *ScummEngine::getOBCDFromObject(int obj, bool v0CheckInventory) {
+byte *ScummEngine::getOBCDFromObject(int obj) {
+ bool useInventory = _v0ObjectInInventory;
int i;
byte *ptr;
- if ((_game.version != 0 || OBJECT_V0_TYPE(obj) == 0) &&
- _objectOwnerTable[obj] != OF_OWNER_ROOM)
- {
- if (_game.version == 0 && !v0CheckInventory)
- return 0;
+ _v0ObjectInInventory = false;
+
+ if ((_objectOwnerTable[obj] != OF_OWNER_ROOM && (_game.version != 0)) || useInventory) {
for (i = 0; i < _numInventory; i++) {
if (_inventory[i] == obj)
return getResourceAddress(rtInventory, i);
}
} else {
for (i = (_numLocalObjects-1); i > 0; --i) {
- int nr = (_game.version != 0) ? obj : OBJECT_V0_NR(obj);
- if (_objs[i].obj_nr == nr) {
- if (_game.version == 0 && _objs[i].obj_type != OBJECT_V0_TYPE(obj))
- continue;
+ if ((_objs[i].obj_nr == obj && !_v0ObjectIndex) || (_v0ObjectIndex && i == obj)) {
if (_objs[i].fl_object_index) {
assert(_objs[i].OBCDoffset == 8);
ptr = getResourceAddress(rtFlObject, _objs[i].fl_object_index);
diff --git a/engines/scumm/object.h b/engines/scumm/object.h
index 7e4a5b5..cdf8b09 100644
--- a/engines/scumm/object.h
+++ b/engines/scumm/object.h
@@ -24,14 +24,6 @@
namespace Scumm {
-static inline int OBJECT_V0(int id, byte type) {
- assert(id < 255);
- return (type << 8 | id);
-}
-#define OBJECT_V0_NR(obj) (obj & 0xFF)
-#define OBJECT_V0_TYPE(obj) ((obj >> 8) & 0xFF)
-
-
enum ObjectClass {
kObjectClassNeverClip = 20,
kObjectClassAlwaysClip = 21,
@@ -70,12 +62,7 @@ struct ObjectData {
byte parentstate;
byte state;
byte fl_object_index;
- // extra engine specific data
- union {
- byte extra;
- byte obj_type; // v0
- byte flags; // v8
- };
+ byte flags;
};
#include "common/pack-start.h" // START STRUCT PACKING
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 1713562..38dbd82 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -822,7 +822,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
MKLINE(ObjectData, parent, sleByte, VER(8)),
MKLINE(ObjectData, state, sleByte, VER(8)),
MKLINE(ObjectData, fl_object_index, sleByte, VER(8)),
- MKLINE(ObjectData, extra, sleByte, VER(46)),
+ MKLINE(ObjectData, flags, sleByte, VER(46)),
MKEND()
};
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index eb0f7bf..37ea3a9 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -28,7 +28,6 @@
#include "scumm/object.h"
#include "scumm/resource.h"
#include "scumm/util.h"
-#include "scumm/scumm_v0.h"
#include "scumm/scumm_v2.h"
#include "scumm/sound.h"
#include "scumm/verbs.h"
@@ -132,6 +131,8 @@ void ScummEngine::runObjectScript(int object, int entry, bool freezeResistant, b
initializeLocals(slot, vars);
+ // V0 Ensure we don't try and access objects via index inside the script
+ _v0ObjectIndex = false;
runScriptNested(slot);
}
@@ -195,10 +196,9 @@ int ScummEngine::getVerbEntrypoint(int obj, int entry) {
return verboffs + 8 + READ_LE_UINT32(ptr + 1);
} else if (_game.version <= 2) {
do {
- const int kFallbackEntry = (_game.version == 0 ? 0x0F : 0xFF);
if (!*verbptr)
return 0;
- if (*verbptr == entry || *verbptr == kFallbackEntry)
+ if (*verbptr == entry || *verbptr == 0xFF)
break;
verbptr += 2;
} while (1);
@@ -1130,128 +1130,6 @@ void ScummEngine::checkAndRunSentenceScript() {
runScript(sentenceScript, 0, 0, localParamList);
}
-void ScummEngine_v0::walkToActorOrObject(int object) {
- int x, y, dir;
- ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "walkToObject");
-
- _walkToObject = object;
- _walkToObjectIdx = getObjectIndex(object);
-
- if (OBJECT_V0_TYPE(object) == kObjectTypeActor) {
- walkActorToActor(VAR(VAR_EGO), OBJECT_V0_NR(object), 4);
- x = a->getRealPos().x;
- y = a->getRealPos().y;
- } else {
- walkActorToObject(VAR(VAR_EGO), object);
- getObjectXYPos(object, x, y, dir);
- }
-
- VAR(6) = x;
- VAR(7) = y;
-
- if (!(a->_miscflags & kActorMiscFlagFreeze)) {
- // FIXME: walking already started -> should be stopped if condition not true
- //actorStartWalk();
- }
-}
-
-void ScummEngine_v0::checkAndRunSentenceScript() {
- if (_walkToObjectIdx) {
- ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "checkAndRunSentenceScript");
- if (a->_moving)
- return;
- // TODO: change actor facing
- _walkToObjectIdx = 0;
- runSentenceScript();
- return;
- }
-
- if (!_sentenceNum || _sentence[_sentenceNum - 1].freezeCount)
- return;
-
- SentenceTab &st = _sentence[_sentenceNum - 1];
-
- if (st.preposition && st.objectB == st.objectA) {
- _sentenceNum--;
- return;
- }
-
- // FIXME: should this be executed?
- //_currentScript = 0xFF;
-
- int obj1Nr = OBJECT_V0_NR(st.objectA);
- int obj1Type = OBJECT_V0_TYPE(st.objectA);
- int obj2Nr = OBJECT_V0_NR(st.objectB);
- int obj2Type = OBJECT_V0_TYPE(st.objectB);
- assert(obj1Nr);
-
- // If two objects are involved, at least one must be in the actors inventory
- if (obj2Nr &&
- (obj1Type != kObjectTypeFG || _objectOwnerTable[obj1Nr] != VAR(VAR_EGO)) &&
- (obj2Type != kObjectTypeFG || _objectOwnerTable[obj2Nr] != VAR(VAR_EGO)))
- {
- if (getVerbEntrypoint(st.objectA, kVerbPickUp))
- doSentence(kVerbPickUp, st.objectA, 0);
- else if (getVerbEntrypoint(st.objectB, kVerbPickUp))
- doSentence(kVerbPickUp, st.objectB, 0);
- else
- _sentenceNum--;
- return;
- }
-
- _cmdVerb = st.verb;
- _cmdObjectNr = obj1Nr;
- _cmdObjectType = obj1Type;
- _cmdObject2Nr = obj2Nr;
- _cmdObject2Type = obj2Type;
- _sentenceNum--;
-
- // TODO: check sentenceNum
-
- if (whereIsObject(st.objectA) != WIO_INVENTORY) {
- if (_currentMode != kModeKeypad) {
- walkToActorOrObject(st.objectA);
- return;
- }
- } else if (st.objectB && whereIsObject(st.objectB) != WIO_INVENTORY) {
- walkToActorOrObject(st.objectB);
- return;
- }
-
- runSentenceScript();
- if (_currentMode == kModeKeypad) {
- _walkToObjectIdx = 0;
- }
-}
-
-void ScummEngine_v0::runSentenceScript() {
- int obj = OBJECT_V0(_cmdObjectNr, _cmdObjectType);
-
- drawSentenceLine();
-
- if (getVerbEntrypoint(obj, _cmdVerb) != 0) {
- // do not read in the dark
- if (!(_cmdVerb == kVerbRead && _currentLights == 0)) {
- VAR(VAR_ACTIVE_OBJECT2) = _cmdObject2Nr;
- runObjectScript(obj, _cmdVerb, false, false, NULL);
- return;
- }
- } else {
- if (_cmdVerb == kVerbGive) {
- // no "give to"-script: give to other kid or ignore
- if (_cmdObject2Nr < 8)
- setOwnerOf(obj, _cmdObject2Nr);
- return;
- }
- }
-
- if (_cmdVerb != kVerbWalkTo) {
- // perform verb's fallback action
- VAR(VAR_ACTIVE_VERB) = _cmdVerb;
- runScript(3, 0, 0, 0);
- }
-}
-
void ScummEngine_v2::runInputScript(int clickArea, int val, int mode) {
int args[24];
int verbScript;
diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp
index cd2e896..e2d3f40 100644
--- a/engines/scumm/script_v0.cpp
+++ b/engines/scumm/script_v0.cpp
@@ -79,7 +79,7 @@ void ScummEngine_v0::setupOpcodes() {
OPCODE(0x22, o4_saveLoadGame);
OPCODE(0x23, o_stopCurrentScript);
/* 24 */
- OPCODE(0x24, o_ifNotEqualActiveObject2);
+ OPCODE(0x24, o_unknown2);
OPCODE(0x25, o5_loadRoom);
OPCODE(0x26, o_getClosestObjActor);
OPCODE(0x27, o2_getActorY);
@@ -159,7 +159,7 @@ void ScummEngine_v0::setupOpcodes() {
OPCODE(0x62, o2_stopScript);
OPCODE(0x63, o_stopCurrentScript);
/* 64 */
- OPCODE(0x64, o_ifEqualActiveObject2);
+ OPCODE(0x64, o_ifActiveObject);
OPCODE(0x65, o_stopCurrentScript);
OPCODE(0x66, o_getClosestObjActor);
OPCODE(0x67, o5_getActorFacing);
@@ -177,7 +177,7 @@ void ScummEngine_v0::setupOpcodes() {
OPCODE(0x70, o_lights);
OPCODE(0x71, o_getBitVar);
OPCODE(0x72, o_nop);
- OPCODE(0x73, o_getObjectOwner);
+ OPCODE(0x73, o5_getObjectOwner);
/* 74 */
OPCODE(0x74, o5_getDist);
OPCODE(0x75, o_printEgo_c64);
@@ -239,7 +239,7 @@ void ScummEngine_v0::setupOpcodes() {
OPCODE(0xa2, o4_saveLoadGame);
OPCODE(0xa3, o_stopCurrentScript);
/* A4 */
- OPCODE(0xa4, o_ifNotEqualActiveObject2);
+ OPCODE(0xa4, o_unknown2);
OPCODE(0xa5, o5_loadRoom);
OPCODE(0xa6, o_stopCurrentScript);
OPCODE(0xa7, o2_getActorY);
@@ -319,7 +319,7 @@ void ScummEngine_v0::setupOpcodes() {
OPCODE(0xe2, o2_stopScript);
OPCODE(0xe3, o_stopCurrentScript);
/* E4 */
- OPCODE(0xe4, o_ifEqualActiveObject2);
+ OPCODE(0xe4, o_ifActiveObject);
OPCODE(0xe5, o_loadRoomWithEgo);
OPCODE(0xe6, o_stopCurrentScript);
OPCODE(0xe7, o5_getActorFacing);
@@ -337,7 +337,7 @@ void ScummEngine_v0::setupOpcodes() {
OPCODE(0xf0, o_lights);
OPCODE(0xf1, o_getBitVar);
OPCODE(0xf2, o_nop);
- OPCODE(0xf3, o_getObjectOwner);
+ OPCODE(0xf3, o5_getObjectOwner);
/* F4 */
OPCODE(0xf4, o5_getDist);
OPCODE(0xf5, o_stopCurrentScript);
@@ -365,7 +365,7 @@ uint ScummEngine_v0::fetchScriptWord() {
int ScummEngine_v0::getActiveObject() {
if (_opcode & PARAM_2)
- return _cmdObjectNr;
+ return _activeObject;
return fetchScriptByte();
}
@@ -406,16 +406,136 @@ void ScummEngine_v0::decodeParseString() {
actorTalk(buffer);
}
-void ScummEngine_v0::clearSentenceLine() {
- Common::Rect sentenceline;
- sentenceline.top = _virtscr[kVerbVirtScreen].topline;
- sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
- sentenceline.left = 0;
- sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
- restoreBackground(sentenceline);
+void ScummEngine_v0::drawSentenceWord(int object, bool usePrep, bool objInInventory) {
+ const byte *temp;
+ int sentencePrep = 0;
+
+ // If object not in inventory, we except an index
+ if (!objInInventory)
+ _v0ObjectIndex = true;
+ else
+ _v0ObjectInInventory = true;
+
+ temp = getObjOrActorName(object);
+
+ _v0ObjectInInventory = false;
+ _v0ObjectIndex = false;
+
+ // Append the 'object-name'
+ if (temp) {
+ _sentenceBuf += " ";
+ _sentenceBuf += (const char *)temp;
+ }
+
+ // Append the modifier? (With / On / To / In)
+ if (!usePrep)
+ return;
+
+ if (_verbs[_activeVerb].prep == 0xFF) {
+ _v0ObjectInInventory = objInInventory;
+ sentencePrep = verbPrep(object);
+ } else {
+ sentencePrep = _verbs[_activeVerb].prep;
+ }
+
+ if (sentencePrep > 0 && sentencePrep <= 4) {
+ // The prepositions, like the fonts, were hard code in the engine. Thus
+ // we have to do that, too, and provde localized versions for all the
+ // languages MM/Zak are available in.
+ static const char *const prepositions[][5] = {
+ { " ", " in", " with", " on", " to" }, // English
+ { " ", " mit", " mit", " mit", " zu" }, // German
+ { " ", " dans", " avec", " sur", " <" }, // French
+ { " ", " in", " con", " su", " a" }, // Italian
+ { " ", " en", " con", " en", " a" }, // Spanish
+ };
+ int lang;
+ switch (_language) {
+ case Common::DE_DEU:
+ lang = 1;
+ break;
+ case Common::FR_FRA:
+ lang = 2;
+ break;
+ case Common::IT_ITA:
+ lang = 3;
+ break;
+ case Common::ES_ESP:
+ lang = 4;
+ break;
+ default:
+ lang = 0; // Default to english
+ }
+
+ _sentenceBuf += prepositions[lang][sentencePrep];
+ }
}
-void ScummEngine_v0::flushSentenceLine() {
+void ScummEngine_v0::drawSentence() {
+ Common::Rect sentenceline;
+ bool inventoryFirst = false;
+
+ if (!(_userState & 32))
+ return;
+
+ // Current Verb, Walk/Use
+ if (getResourceAddress(rtVerb, _activeVerb)) {
+ _sentenceBuf = (char *)getResourceAddress(rtVerb, _activeVerb);
+ } else {
+ return;
+ }
+
+ // If using inventory first, draw it first
+ if (_activeInvExecute && _activeInventory) {
+ drawSentenceWord(_activeInventory, true, true);
+ } else {
+ // Not using inventory, use selected object
+ if (_activeObject)
+ drawSentenceWord(_activeObjectIndex, true, false);
+ else
+ inventoryFirst = true;
+ }
+
+
+ // Draw the inventory?
+ if (_activeInventory > 0 && _activeObject2 == 0) {
+ // Only if inventory isnt first (it will already be drawn by now)
+ if (!_activeInvExecute) {
+ drawSentenceWord(_activeInventory, inventoryFirst, true);
+ } else {
+ // Draw the active object, which could be inventory based, or room based
+ if (_activeObject && !_activeObjectIndex) {
+ drawSentenceWord(_activeObject, inventoryFirst, true);
+ } else // Room based
+ drawSentenceWord(_activeObjectIndex, inventoryFirst, false);
+ }
+
+ // Draw the 2nd active object
+ } else if (_activeObject2) {
+
+ // 2nd Object is in inventory
+ if (_activeObject2Inv) {
+ _v0ObjectInInventory = true;
+ drawSentenceWord(_activeObject2, inventoryFirst, true);
+ } else {
+ drawSentenceWord(_activeObject2Index, inventoryFirst, false);
+ }
+ }
+
+ // Draw the active actor
+ if (_activeActor) {
+ Actor *a = derefActor(_activeActor, "");
+
+ _sentenceBuf += " ";
+ _sentenceBuf += (const char *)a->getActorName();
+ }
+
+ _string[2].charset = 1;
+ _string[2].ypos = _virtscr[kVerbVirtScreen].topline;
+ _string[2].xpos = 0;
+ _string[2].right = _virtscr[kVerbVirtScreen].w - 1;
+ _string[2].color = 16;
+
byte string[80];
const char *ptr = _sentenceBuf.c_str();
int i = 0, len = 0;
@@ -434,77 +554,24 @@ void ScummEngine_v0::flushSentenceLine() {
}
string[i] = 0;
- _string[2].charset = 1;
- _string[2].ypos = _virtscr[kVerbVirtScreen].topline;
- _string[2].xpos = 0;
- _string[2].right = _virtscr[kVerbVirtScreen].w - 1;
- _string[2].color = 16;
- drawString(2, (byte *)string);
-}
+ sentenceline.top = _virtscr[kVerbVirtScreen].topline;
+ sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
+ sentenceline.left = 0;
+ sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
+ restoreBackground(sentenceline);
-void ScummEngine_v0::drawSentenceObject(int object) {
- const byte *temp;
- temp = getObjOrActorName(object);
- if (temp) {
- _sentenceBuf += " ";
- _sentenceBuf += (const char *)temp;
- }
+ drawString(2, (byte *)string);
}
+void ScummEngine_v0::o_stopCurrentScript() {
+ int script;
-void ScummEngine_v0::drawSentenceLine() {
- if (!(_userState & 32))
- return;
-
- clearSentenceLine();
-
- if (_activeVerb == kVerbNewKid) {
- _sentenceBuf = "";
- for (int i = 0; i < 3; ++i) {
- Actor *a = derefActor(VAR(97 + i), "drawSentence");
- _sentenceBuf += Common::String::format("%-13s", a->getActorName());
- }
- flushSentenceLine();
- return;
- }
-
- // Current Verb
- if (_activeVerb == kVerbNone)
- _activeVerb = kVerbWalkTo;
-
- char *verbName = (char *)getResourceAddress(rtVerb, _activeVerb);
- assert(verbName);
- _sentenceBuf = verbName;
-
- if (_activeObjectNr) {
- // Draw the 1st active object
- drawSentenceObject(OBJECT_V0(_activeObjectNr, _activeObjectType));
-
- // Append verb preposition
- int sentencePrep = activeVerbPrep();
- if (sentencePrep) {
- drawPreposition(sentencePrep);
-
- // Draw the 2nd active object
- if (_activeObject2Nr) {
- // 2nd Object is an actor
- if (_activeObject2Type == kObjectTypeActor) {
- Actor *a = derefActor(_activeObject2Nr, "");
- _sentenceBuf += " ";
- _sentenceBuf += (const char *)a->getActorName();
- // 2nd Object is an inventory or room object
- } else {
- drawSentenceObject(OBJECT_V0(_activeObject2Nr, _activeObject2Type));
- }
- }
- }
- }
-
- flushSentenceLine();
-}
+ script = vm.slot[_currentScript].number;
-void ScummEngine_v0::o_stopCurrentScript() {
- stopScriptCommon(0);
+ if (_currentScript != 0 && vm.slot[_currentScript].number == script)
+ stopObjectCode();
+ else
+ stopScript(script);
}
void ScummEngine_v0::o_loadSound() {
@@ -558,16 +625,16 @@ void ScummEngine_v0::o_loadRoom() {
}
void ScummEngine_v0::o_loadRoomWithEgo() {
- ActorC64 *a;
+ Actor *a;
int obj, room, x, y, dir;
obj = fetchScriptByte();
room = fetchScriptByte();
- a = (ActorC64 *)derefActor(VAR(VAR_EGO), "o_loadRoomWithEgo");
+ a = derefActor(VAR(VAR_EGO), "o_loadRoomWithEgo");
//0x634F
- if (a->_miscflags & kActorMiscFlagFreeze) {
+ if (((ActorC64 *)a)->_miscflags & 0x40) {
// TODO: Check if this is the correct function
// to be calling here
stopObjectCode();
@@ -618,15 +685,15 @@ void ScummEngine_v0::o_cursorCommand() {
_currentMode = fetchScriptByte();
switch (_currentMode) {
- case kModeCutscene:
+ case 0:
state = 15;
break;
- case kModeKeypad:
+ case 1:
state = 31;
break;
- case kModeNoNewKid:
+ case 2:
break;
- case kModeNormal:
+ case 3:
state = 247;
break;
}
@@ -708,13 +775,21 @@ void ScummEngine_v0::o_putActorAtObject() {
}
void ScummEngine_v0::o_pickupObject() {
- int objNr = fetchScriptByte();
- int obj = OBJECT_V0((objNr ? objNr : _cmdObjectNr), 0);
+ int obj = fetchScriptByte();
+ if (obj == 0) {
+ obj = _activeObject;
+ }
+
+ if (obj < 1) {
+ error("pickupObject received invalid index %d (script %d)", obj, vm.slot[_currentScript].number);
+ }
- /* Don't take an object twice */
- if (whereIsObject(obj) == WIO_INVENTORY)
+ if (getObjectIndex(obj) == -1)
return;
+ if (whereIsObjectInventory(_activeObject2) == WIO_INVENTORY) /* Don't take an */
+ return; /* object twice */
+
addObjectToInventory(obj, _roomResource);
markObjectRectAsDirty(obj);
putOwner(obj, VAR(VAR_EGO));
@@ -750,20 +825,14 @@ void ScummEngine_v0::o_setActorBitVar() {
a->_miscflags &= ~mask;
// This flag causes the actor to stop moving (used by script #158, Green Tentacle 'Oomph!')
- if (a->_miscflags & kActorMiscFlagFreeze)
+ if (a->_miscflags & 0x40)
a->stopActorMoving();
- if (a->_miscflags & kActorMiscFlagHide)
+ if (a->_miscflags & 0x80)
a->setActorCostume(0);
debug(0, "o_setActorBitVar(%d, %d, %d)", act, mask, mod);
}
-void ScummEngine_v0::o_getObjectOwner() {
- getResultPos();
- int obj = getVarOrDirectWord(PARAM_1);
- setResult(getOwner(obj ? obj : _cmdObjectNr));
-}
-
void ScummEngine_v0::o_getActorBitVar() {
getResultPos();
byte act = getVarOrDirectByte(PARAM_1);
@@ -809,46 +878,22 @@ void ScummEngine_v0::o_printEgo_c64() {
}
void ScummEngine_v0::o_doSentence() {
- byte verb = fetchScriptByte();
- int obj, obj2;
- byte b;
-
- b = fetchScriptByte();
- if (b == 0xFF) {
- obj = OBJECT_V0(_cmdObject2Nr, _cmdObject2Type);
- } else if (b == 0xFE) {
- obj = OBJECT_V0(_cmdObjectNr, _cmdObjectType);
- } else {
- obj = OBJECT_V0(b, (_opcode & 0x80) ? 1 : 0);
- }
-
- b = fetchScriptByte();
- if (b == 0xFF) {
- obj2 = OBJECT_V0(_cmdObject2Nr, _cmdObject2Type);
- } else if (b == 0xFE) {
- obj2 = OBJECT_V0(_cmdObjectNr, _cmdObjectType);
- } else {
- obj2 = OBJECT_V0(b, (_opcode & 0x40) ? 1 : 0);
- }
+ byte entry = fetchScriptByte();
+ byte obj = fetchScriptByte();
+ fetchScriptByte();
- doSentence(verb, obj, obj2);
+ runObjectScript(obj, entry, false, false, NULL);
}
-bool ScummEngine_v0::ifEqualActiveObject2Common(bool ignoreType) {
- byte obj = fetchScriptByte();
- if (!ignoreType || (_cmdObject2Type == kObjectTypeFG))
- return (obj == _cmdObject2Nr);
- return false;
+void ScummEngine_v0::o_unknown2() {
+ byte var1 = fetchScriptByte();
+ error("STUB: o_unknown2(%d)", var1);
}
-void ScummEngine_v0::o_ifEqualActiveObject2() {
- bool equal = ifEqualActiveObject2Common((_opcode & 0x80) == 0);
- jumpRelative(equal);
-}
+void ScummEngine_v0::o_ifActiveObject() {
+ byte obj = fetchScriptByte();
-void ScummEngine_v0::o_ifNotEqualActiveObject2() {
- bool equal = ifEqualActiveObject2Common((_opcode & 0x80) == 0);
- jumpRelative(!equal);
+ jumpRelative(obj == _activeInventory);
}
void ScummEngine_v0::o_getClosestObjActor() {
@@ -934,26 +979,33 @@ void ScummEngine_v0::o_setOwnerOf() {
owner = getVarOrDirectByte(PARAM_2);
if (obj == 0)
- obj = _cmdObjectNr;
-
- // FIXME: the original interpreter seems to set the owner of
- // an item to remove (new owner 0) to 13 (purple tentacle).
- // Ignore this behavior for now.
- /*
- if (owner == 0)
- owner = 13;
- */
+ obj = _activeInventory;
setOwnerOf(obj, owner);
}
void ScummEngine_v0::resetSentence(bool walking) {
- _activeVerb = kVerbWalkTo;
- _activeObjectNr = 0;
- _activeObjectType = kObjectTypeBG;
- _activeObject2Nr = 0;
- _activeObject2Type = kObjectTypeBG;
- _walkToObjectIdx = 0;
+ _activeVerb = 13;
+
+ // If the actor is walking, or the screen is a keypad (no sentence verbs/objects are drawn)
+ // Then reset all active objects (stops the radio crash, bug #3077966)
+ if (!walking || !(_userState & 32)) {
+ _v0ObjectFlag = 0;
+ _activeInventory = 0;
+ _activeObject = 0;
+ _activeObject2 = 0;
+ _activeObjectIndex = 0;
+ _activeObject2Index = 0;
+ }
+
+ _verbExecuting = false;
+ _verbPickup = false;
+
+ _activeActor = 0;
+ _activeInvExecute = false;
+ _activeObject2Inv = false;
+ _activeObjectObtained = false;
+ _activeObject2Obtained = false;
}
} // End of namespace Scumm
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index 6f6138d..edb046d 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -953,41 +953,6 @@ void ScummEngine_v2::o2_doSentence() {
}
}
-void ScummEngine_v2::drawPreposition(int index) {
- // The prepositions, like the fonts, were hard code in the engine. Thus
- // we have to do that, too, and provde localized versions for all the
- // languages MM/Zak are available in.
- const char *prepositions[][5] = {
- { " ", " in", " with", " on", " to" }, // English
- { " ", " mit", " mit", " mit", " zu" }, // German
- { " ", " dans", " avec", " sur", " <" }, // French
- { " ", " in", " con", " su", " a" }, // Italian
- { " ", " en", " con", " en", " a" }, // Spanish
- };
- int lang;
- switch (_language) {
- case Common::DE_DEU:
- lang = 1;
- break;
- case Common::FR_FRA:
- lang = 2;
- break;
- case Common::IT_ITA:
- lang = 3;
- break;
- case Common::ES_ESP:
- lang = 4;
- break;
- default:
- lang = 0; // Default to english
- }
-
- if (_game.platform == Common::kPlatformNES) {
- _sentenceBuf += (const char *)(getResourceAddress(rtCostume, 78) + VAR(VAR_SENTENCE_PREPOSITION) * 8 + 2);
- } else
- _sentenceBuf += prepositions[lang][index];
-}
-
void ScummEngine_v2::o2_drawSentence() {
Common::Rect sentenceline;
const byte *temp;
@@ -1021,7 +986,38 @@ void ScummEngine_v2::o2_drawSentence() {
}
if (0 < VAR(VAR_SENTENCE_PREPOSITION) && VAR(VAR_SENTENCE_PREPOSITION) <= 4) {
- drawPreposition(VAR(VAR_SENTENCE_PREPOSITION));
+ // The prepositions, like the fonts, were hard code in the engine. Thus
+ // we have to do that, too, and provde localized versions for all the
+ // languages MM/Zak are available in.
+ const char *prepositions[][5] = {
+ { " ", " in", " with", " on", " to" }, // English
+ { " ", " mit", " mit", " mit", " zu" }, // German
+ { " ", " dans", " avec", " sur", " <" }, // French
+ { " ", " in", " con", " su", " a" }, // Italian
+ { " ", " en", " con", " en", " a" }, // Spanish
+ };
+ int lang;
+ switch (_language) {
+ case Common::DE_DEU:
+ lang = 1;
+ break;
+ case Common::FR_FRA:
+ lang = 2;
+ break;
+ case Common::IT_ITA:
+ lang = 3;
+ break;
+ case Common::ES_ESP:
+ lang = 4;
+ break;
+ default:
+ lang = 0; // Default to english
+ }
+
+ if (_game.platform == Common::kPlatformNES) {
+ _sentenceBuf += (const char *)(getResourceAddress(rtCostume, 78) + VAR(VAR_SENTENCE_PREPOSITION) * 8 + 2);
+ } else
+ _sentenceBuf += prepositions[lang][VAR(VAR_SENTENCE_PREPOSITION)];
}
if (VAR(VAR_SENTENCE_OBJECT2) > 0) {
@@ -1190,7 +1186,11 @@ void ScummEngine_v2::o2_startScript() {
runScript(script, 0, 0, 0);
}
-void ScummEngine_v2::stopScriptCommon(int script) {
+void ScummEngine_v2::o2_stopScript() {
+ int script;
+
+ script = getVarOrDirectByte(PARAM_1);
+
if (_game.id == GID_MANIAC && _roomResource == 26 && vm.slot[_currentScript].number == 10001) {
// FIXME: Nasty hack for bug #915575
// Don't let the exit script for room 26 stop the script (116), when
@@ -1211,31 +1211,26 @@ void ScummEngine_v2::stopScriptCommon(int script) {
stopScript(script);
}
-void ScummEngine_v2::o2_stopScript() {
- stopScriptCommon(getVarOrDirectByte(PARAM_1));
-}
-
void ScummEngine_v2::o2_panCameraTo() {
panCameraTo(getVarOrDirectByte(PARAM_1) * V12_X_MULTIPLIER, 0);
}
-void ScummEngine_v2::walkActorToObject(int actor, int obj) {
- int x, y, dir;
- getObjectXYPos(obj, x, y, dir);
-
- Actor *a = derefActor(actor, "walkActorToObject");
- AdjustBoxResult r = a->adjustXYToBeInBox(x, y);
- x = r.x;
- y = r.y;
+void ScummEngine_v2::o2_walkActorToObject() {
+ int obj;
+ Actor *a;
- a->startWalkActor(x, y, dir);
-}
+ _v0ObjectFlag = 0;
-void ScummEngine_v2::o2_walkActorToObject() {
- int actor = getVarOrDirectByte(PARAM_1);
- int obj = getVarOrDirectWord(PARAM_2);
+ a = derefActor(getVarOrDirectByte(PARAM_1), "o2_walkActorToObject");
+ obj = getVarOrDirectWord(PARAM_2);
if (whereIsObject(obj) != WIO_NOT_FOUND) {
- walkActorToObject(actor, obj);
+ int x, y, dir;
+ getObjectXYPos(obj, x, y, dir);
+ AdjustBoxResult r = a->adjustXYToBeInBox(x, y);
+ x = r.x;
+ y = r.y;
+
+ a->startWalkActor(x, y, dir);
}
}
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 707c3c2..6426b75 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -2464,40 +2464,8 @@ void ScummEngine_v5::o5_walkActorTo() {
a->startWalkActor(x, y, -1);
}
-void ScummEngine_v5::walkActorToActor(int actor, int toActor, int dist) {
- Actor *a = derefActor(actor, "walkActorToActor");
- Actor *to = derefActor(toActor, "walkActorToActor(2)");
-
- if (_game.version <= 2) {
- dist *= V12_X_MULTIPLIER;
- } else if (dist == 0xFF) {
- dist = a->_scalex * a->_width / 0xFF;
- dist += (to->_scalex * to->_width / 0xFF) / 2;
- }
- int x = to->getPos().x;
- int y = to->getPos().y;
- if (x < a->getPos().x)
- x += dist;
- else
- x -= dist;
-
- if (_game.version <= 2) {
- x /= V12_X_MULTIPLIER;
- y /= V12_Y_MULTIPLIER;
- }
- if (_game.version <= 3) {
- AdjustBoxResult abr = a->adjustXYToBeInBox(x, y);
- x = abr.x;
- y = abr.y;
- }
- a->startWalkActor(x, y, -1);
-
- // WORKAROUND: See bug #2971126 for details on why this is here.
- if (_game.version == 0)
- o5_breakHere();
-}
-
void ScummEngine_v5::o5_walkActorToActor() {
+ int x, y;
Actor *a, *a2;
int nr = getVarOrDirectByte(PARAM_1);
int nr2 = getVarOrDirectByte(PARAM_2);
@@ -2531,7 +2499,33 @@ void ScummEngine_v5::o5_walkActorToActor() {
if (!a2->isInCurrentRoom())
return;
- walkActorToActor(nr, nr2, dist);
+ if (_game.version <= 2) {
+ dist *= V12_X_MULTIPLIER;
+ } else if (dist == 0xFF) {
+ dist = a->_scalex * a->_width / 0xFF;
+ dist += (a2->_scalex * a2->_width / 0xFF) / 2;
+ }
+ x = a2->getPos().x;
+ y = a2->getPos().y;
+ if (x < a->getPos().x)
+ x += dist;
+ else
+ x -= dist;
+
+ if (_game.version <= 2) {
+ x /= V12_X_MULTIPLIER;
+ y /= V12_Y_MULTIPLIER;
+ }
+ if (_game.version <= 3) {
+ AdjustBoxResult abr = a->adjustXYToBeInBox(x, y);
+ x = abr.x;
+ y = abr.y;
+ }
+ a->startWalkActor(x, y, -1);
+
+ // WORKAROUND: See bug #2971126 for details on why this is here.
+ if (_game.version == 0)
+ o5_breakHere();
}
void ScummEngine_v5::o5_walkActorToObject() {
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 2eda5ca..d3cc218 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -151,6 +151,9 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_fileHandle = 0;
// Init all vars
+ _v0ObjectIndex = false;
+ _v0ObjectInInventory = false;
+ _v0ObjectFlag = 0;
_imuse = NULL;
_imuseDigital = NULL;
_musicEngine = NULL;
@@ -698,6 +701,10 @@ ScummEngine_v2::ScummEngine_v2(OSystem *syst, const DetectorResult &dr)
_inventoryOffset = 0;
+ _activeInventory = 0;
+ _activeObject = 0;
+ _activeVerb = 0;
+
VAR_SENTENCE_VERB = 0xFF;
VAR_SENTENCE_OBJECT1 = 0xFF;
VAR_SENTENCE_OBJECT2 = 0xFF;
@@ -712,21 +719,19 @@ ScummEngine_v2::ScummEngine_v2(OSystem *syst, const DetectorResult &dr)
ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)
: ScummEngine_v2(syst, dr) {
+ _verbExecuting = false;
+ _verbPickup = false;
_currentMode = 0;
- _activeVerb = kVerbNone;
- _activeObjectNr = 0;
- _activeObjectType = 0;
- _activeObject2Nr = 0;
- _activeObject2Type = 0;
-
- _cmdVerb = kVerbNone;
- _cmdObjectNr = 0;
- _cmdObjectType = 0;
- _cmdObject2Nr = 0;
- _cmdObject2Type = 0;
+ _activeObject2 = 0;
+ _activeObjectIndex = 0;
+ _activeObject2Index = 0;
+ _activeInvExecute = false;
+ _activeObject2Inv = false;
+ _activeObjectObtained = false;
+ _activeObject2Obtained = false;
- VAR_ACTIVE_OBJECT2 = 0xFF;
+ VAR_ACTIVE_ACTOR = 0xFF;
VAR_IS_SOUND_RUNNING = 0xFF;
VAR_ACTIVE_VERB = 0xFF;
}
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index fadc390..d9237b2 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -502,6 +502,10 @@ protected:
int32 *_scummVars;
byte *_bitVars;
+ bool _v0ObjectIndex; // V0 Use object index, instead of object number
+ bool _v0ObjectInInventory; // V0 Use object number from inventory
+ byte _v0ObjectFlag;
+
/* Global resource tables */
int _numVariables, _numBitVariables, _numLocalObjects;
int _numGlobalObjects, _numArray, _numVerbs, _numFlObject;
@@ -642,7 +646,7 @@ protected:
void updateScriptPtr();
virtual void runInventoryScript(int i);
void inventoryScriptIndy3Mac();
- virtual void checkAndRunSentenceScript();
+ void checkAndRunSentenceScript();
void runExitScript();
void runEntryScript();
void runAllScripts();
@@ -795,6 +799,7 @@ protected:
int getObjNewDir(int obj);
int getObjectIndex(int object) const;
int getObjectImageCount(int object);
+ int whereIsObjectInventory(int object);
int whereIsObject(int object) const;
int findObject(int x, int y);
void findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint object, uint room);
@@ -815,7 +820,7 @@ protected:
virtual void clearDrawQueues();
uint32 getOBCDOffs(int object) const;
- byte *getOBCDFromObject(int obj, bool v0CheckInventory = true);
+ byte *getOBCDFromObject(int obj);
const byte *getOBIMFromObjectData(const ObjectData &od);
const byte *getObjectImage(const byte *ptr, int state);
virtual int getObjectIdFromOBIM(const byte *obim);
diff --git a/engines/scumm/scumm_v0.h b/engines/scumm/scumm_v0.h
index c2af6d4..af481df 100644
--- a/engines/scumm/scumm_v0.h
+++ b/engines/scumm/scumm_v0.h
@@ -32,43 +32,20 @@ namespace Scumm {
*/
class ScummEngine_v0 : public ScummEngine_v2 {
protected:
- enum CurrentMode {
- kModeCutscene = 0, // cutscene active
- kModeKeypad = 1, // kid selection / dial pad / save-load dialog
- kModeNoNewKid = 2, // verb "new kid" disabled (e.g. when entering lab)
- kModeNormal = 3, // normal playing mode
- };
-
- enum ObjectType {
- kObjectTypeFG = 0, // foreground object
- // - with owner/state, might (but has not to) be pickupable
- // -> with entry in _objectOwner/StateTable
- // -> all objects in _inventory have this type
- // - image can be exchanged (background overlay)
- kObjectTypeBG = 1, // background object
- // - without owner/state, not pickupable (room only)
- // -> without entry in _objectOwner/StateTable
- // - image cannot be exchanged (part of background image)
- kObjectTypeActor = 2 // object is an actor
- };
-
-protected:
byte _currentMode;
+ bool _verbExecuting; // is a verb executing
+ bool _verbPickup; // are we picking up an object during a verb execute
- int _activeVerb;
- int _activeObjectNr; // 1st Object Number
- int _activeObjectType; // 1st Object Type (0: inventory (or room), 1: room)
- int _activeObject2Nr; // 2nd Object Number
- int _activeObject2Type; // 2nd Object Type (0: inventory (or room), 1: room, 2: actor)
+ int _activeActor; // Actor Number
+ int _activeObject2; // 2nd Object Number
- int _cmdVerb;
- int _cmdObjectNr;
- int _cmdObjectType;
- int _cmdObject2Nr;
- int _cmdObject2Type;
+ bool _activeInvExecute; // is activeInventory first to be executed
+ bool _activeObject2Inv; // is activeobject2 in the inventory
+ bool _activeObjectObtained; // collected _activeobject?
+ bool _activeObject2Obtained; // collected _activeObject2?
- int _walkToObject;
- int _walkToObjectIdx;
+ int _activeObjectIndex;
+ int _activeObject2Index;
public:
ScummEngine_v0(OSystem *syst, const DetectorResult &dr);
@@ -87,26 +64,26 @@ protected:
virtual void processInput();
+ virtual void runObject(int obj, int entry);
virtual void saveOrLoad(Serializer *s);
// V0 MM Verb commands
- int getVerbPrepId();
- int activeVerbPrep();
- void walkToActorOrObject(int object);
- void verbExec();
-
- virtual void runSentenceScript();
- virtual void checkAndRunSentenceScript();
- bool checkSentenceComplete();
+ int verbPrep(int object);
+ bool verbMove(int object, int objectIndex, bool invObject);
+ bool verbMoveToActor(int actor);
+ bool verbObtain(int object, int objIndex);
+ bool verbExecutes(int object, bool inventory = false);
+ bool verbExec();
+
+ int findObjectIndex(int x, int y);
+
virtual void checkExecVerbs();
virtual void handleMouseOver(bool updateInventory);
- int verbPrepIdType(int verbid);
void resetVerbs();
+ void setNewKidVerbs();
- void clearSentenceLine();
- void flushSentenceLine();
- void drawSentenceObject(int object);
- void drawSentenceLine();
+ void drawSentenceWord(int object, bool usePrep, bool objInInventory);
+ void drawSentence();
void switchActor(int slot);
@@ -119,8 +96,6 @@ protected:
virtual bool areBoxesNeighbors(int box1nr, int box2nr);
- bool ifEqualActiveObject2Common(bool ignoreType);
-
/* Version C64 script opcodes */
void o_stopCurrentScript();
void o_loadSound();
@@ -143,14 +118,13 @@ protected:
void o_unlockScript();
void o_decrement();
void o_nop();
- void o_getObjectOwner();
void o_getActorBitVar();
void o_setActorBitVar();
void o_getBitVar();
void o_setBitVar();
void o_doSentence();
- void o_ifEqualActiveObject2();
- void o_ifNotEqualActiveObject2();
+ void o_unknown2();
+ void o_ifActiveObject();
void o_getClosestObjActor();
void o_printEgo_c64();
void o_print_c64();
@@ -161,7 +135,7 @@ protected:
void o_beginOverride();
void o_setOwnerOf();
- byte VAR_ACTIVE_OBJECT2;
+ byte VAR_ACTIVE_ACTOR;
byte VAR_IS_SOUND_RUNNING;
byte VAR_ACTIVE_VERB;
};
diff --git a/engines/scumm/scumm_v2.h b/engines/scumm/scumm_v2.h
index b407fd3..47c5fa2 100644
--- a/engines/scumm/scumm_v2.h
+++ b/engines/scumm/scumm_v2.h
@@ -44,13 +44,17 @@ protected:
Common::String _sentenceBuf;
uint16 _inventoryOffset;
+ int _activeInventory;
+ int _activeObject;
+ int _activeVerb;
+
public:
ScummEngine_v2(OSystem *syst, const DetectorResult &dr);
virtual void resetScumm();
void checkV2MouseOver(Common::Point pos);
- int checkV2Inventory(int x, int y);
+ void checkV2Inventory(int x, int y);
void redrawV2Inventory();
protected:
@@ -85,7 +89,6 @@ protected:
void ifNotStateCommon(byte type);
void setStateCommon(byte type);
void clearStateCommon(byte type);
- void stopScriptCommon(int script);
virtual void resetSentence(bool walking);
void setUserState(byte state);
@@ -97,10 +100,6 @@ protected:
virtual void setBuiltinCursor(int index);
- void drawPreposition(int index);
-
- void walkActorToObject(int actor, int obj);
-
/* Version 2 script opcodes */
void o2_actorFromPos();
void o2_actorOps();
diff --git a/engines/scumm/scumm_v5.h b/engines/scumm/scumm_v5.h
index 0eef04b..b8a61c1 100644
--- a/engines/scumm/scumm_v5.h
+++ b/engines/scumm/scumm_v5.h
@@ -87,8 +87,6 @@ protected:
void drawFlashlight();
- void walkActorToActor(int actor, int toActor, int dist);
-
/**
* Fetch the next script word, then if cond is *false*, perform a relative jump.
* So this corresponds to a "jne" jump instruction.
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index 6365a72..26a6a2f 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -115,7 +115,7 @@ void ScummEngine_v0::setupScummVars() {
VAR_CAMERA_POS_X = 2;
VAR_HAVE_MSG = 3;
VAR_ROOM = 4;
- VAR_ACTIVE_OBJECT2 = 5;
+ VAR_ACTIVE_ACTOR = 5;
VAR_OVERRIDE = 6;
VAR_IS_SOUND_RUNNING = 8;
VAR_ACTIVE_VERB = 9;
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index 30d0d02..67ed17c 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -41,59 +41,47 @@ struct VerbSettings {
int id;
int x_pos;
int y_pos;
+ int prep;
const char *name;
};
static const VerbSettings v0VerbTable_English[] = {
- {kVerbOpen, 8, 0, "Open"},
- {kVerbClose, 8, 1, "Close"},
- {kVerbGive, 0, 2, "Give"},
- {kVerbTurnOn, 32, 0, "Turn on"},
- {kVerbTurnOff, 32, 1, "Turn off"},
- {kVerbFix, 32, 2, "Fix"},
- {kVerbNewKid, 24, 0, "New Kid"},
- {kVerbUnlock, 24, 1, "Unlock"},
- {kVerbPush, 0, 0, "Push"},
- {kVerbPull, 0, 1, "Pull"},
- {kVerbUse, 24, 2, "Use"},
- {kVerbRead, 8, 2, "Read"},
- {kVerbWalkTo, 15, 0, "Walk to"},
- {kVerbPickUp, 15, 1, "Pick up"},
- {kVerbWhatIs, 15, 2, "What is"}
+ { 1, 8, 0, 0, "Open"},
+ { 2, 8, 1, 0, "Close"},
+ { 3, 0, 2, 4, "Give"},
+ { 4, 32, 0, 0, "Turn on"},
+ { 5, 32, 1, 0, "Turn off"},
+ { 6, 32, 2, 2, "Fix"},
+ { 7, 24, 0, 0, "New Kid"},
+ { 8, 24, 1, 2, "Unlock"},
+ { 9, 0, 0, 0, "Push"},
+ {10, 0, 1, 0, "Pull"},
+ {11, 24, 2, 255, "Use"},
+ {12, 8, 2, 0, "Read"},
+ {13, 15, 0, 0, "Walk to"},
+ {14, 15, 1, 0, "Pick up"},
+ {15, 15, 2, 0, "What is"}
};
// FIXME: Replace * with the correct character
static const VerbSettings v0VerbTable_German[] = {
- {kVerbOpen, 7, 0, "$ffne"},
- {kVerbClose, 13, 1, "Schlie*e"},
- {kVerbGive, 0, 2, "Gebe"},
- {kVerbTurnOn, 37, 1, "Ein"},
- {kVerbTurnOff, 37, 0, "Aus"},
- {kVerbFix, 23, 1, "Repariere"},
- {kVerbNewKid, 34, 2, "Person"},
- {kVerbUnlock, 23, 0, "Schlie*e auf"},
- {kVerbPush, 0, 0, "Dr<cke"},
- {kVerbPull, 0, 1, "Ziehe"},
- {kVerbUse, 23, 2, "Benutz"},
- {kVerbRead, 7, 2, "Lese"},
- {kVerbWalkTo, 13, 0, "Gehe zu"},
- {kVerbPickUp, 7, 1, "Nimm"},
- {kVerbWhatIs, 13, 2, "Was ist"}
+ { 1, 7, 0, 0, "$ffne"},
+ { 2, 13, 1, 0, "Schlie*e"},
+ { 3, 0, 2, 4, "Gebe"},
+ { 4, 37, 1, 0, "Ein"},
+ { 5, 37, 0, 0, "Aus"},
+ { 6, 23, 1, 2, "Repariere"},
+ { 7, 34, 2, 0, "Person"},
+ { 8, 23, 0, 2, "Schlie*e auf"},
+ { 9, 0, 0, 0, "Dr<cke"},
+ {10, 0, 1, 0, "Ziehe"},
+ {11, 23, 2, 255, "Benutz"},
+ {12, 7, 2, 0, "Lese"},
+ {13, 13, 0, 0, "Gehe zu"},
+ {14, 7, 1, 0, "Nimm"},
+ {15, 13, 2, 0, "Was ist"}
};
-int ScummEngine_v0::verbPrepIdType(int verbid) {
- switch (verbid) {
- case kVerbUse: // depends on object1
- return kVerbPrepObject;
- case kVerbGive:
- return kVerbPrepTo;
- case kVerbUnlock: case kVerbFix:
- return kVerbPrepWith;
- default:
- return kVerbPrepNone;
- }
-}
-
void ScummEngine_v0::resetVerbs() {
VirtScreen *virt = &_virtscr[kVerbVirtScreen];
VerbSlot *vs;
@@ -124,13 +112,44 @@ void ScummEngine_v0::resetVerbs() {
vs->key = 0;
vs->center = 0;
vs->imgindex = 0;
- vs->prep = verbPrepIdType(vtable[i - 1].id);
+ vs->prep = vtable[i - 1].prep;
vs->curRect.left = vtable[i - 1].x_pos * 8;
vs->curRect.top = vtable[i - 1].y_pos * 8 + virt->topline + 8;
loadPtrToResource(rtVerb, i, (const byte*)vtable[i - 1].name);
}
}
+void ScummEngine_v0::setNewKidVerbs() {
+ VirtScreen *virt = &_virtscr[kVerbVirtScreen];
+ VerbSlot *vs;
+ int i;
+
+ for (i = 1; i < 16; i++)
+ killVerb(i);
+
+ for (i = 1; i < 4; i++) {
+ vs = &_verbs[i];
+ vs->verbid = i;
+ vs->color = 5;
+ vs->hicolor = 7;
+ vs->dimcolor = 11;
+ vs->type = kTextVerbType;
+ vs->charset_nr = _string[0]._default.charset;
+ vs->curmode = 1;
+ vs->saveid = 0;
+ vs->key = 0;
+ vs->center = 0;
+ vs->imgindex = 0;
+ vs->prep = 0;
+ vs->curRect.left = (i * 8) * 8;
+ vs->curRect.top = virt->topline + 8;
+
+ Actor *a = derefActor(VAR(96 + i), "setNewKidVerbs");
+ loadPtrToResource(rtVerb, i, (const byte*)a->getActorName());
+ }
+ setUserState(191);
+}
+
void ScummEngine_v0::switchActor(int slot) {
resetSentence(false);
@@ -142,7 +161,7 @@ void ScummEngine_v0::switchActor(int slot) {
return;
// verbs disabled? or just new kid button?
- if (_currentMode == kModeCutscene || _currentMode == kModeKeypad || _currentMode == kModeNoNewKid)
+ if (_currentMode == 0 || _currentMode == 1 || _currentMode == 2)
return;
VAR(VAR_EGO) = VAR(97 + slot);
@@ -335,14 +354,14 @@ void ScummEngine_v2::checkV2MouseOver(Common::Point pos) {
}
}
-int ScummEngine_v2::checkV2Inventory(int x, int y) {
+void ScummEngine_v2::checkV2Inventory(int x, int y) {
int inventoryArea = (_game.platform == Common::kPlatformNES) ? 48: 32;
int object = 0;
y -= _virtscr[kVerbVirtScreen].topline;
if ((y < inventoryArea) || !(_mouseAndKeyboardStat & MBS_LEFT_CLICK))
- return 0;
+ return;
if (_mouseOverBoxesV2[kInventoryUpArrow].rect.contains(x, y)) {
if (_inventoryOffset >= 2) {
@@ -363,9 +382,18 @@ int ScummEngine_v2::checkV2Inventory(int x, int y) {
}
if (object >= 4)
- return 0;
+ return;
+
+ object = findInventory(_scummVars[VAR_EGO], object + 1 + _inventoryOffset);
- return findInventory(_scummVars[VAR_EGO], object + 1 + _inventoryOffset);
+ if (object > 0) {
+ if (_game.version == 0) {
+ _activeInventory = object;
+
+ } else {
+ runInputScript(kInventoryClickArea, object, 0);
+ }
+ }
}
void ScummEngine_v2::redrawV2Inventory() {
@@ -403,7 +431,9 @@ void ScummEngine_v2::redrawV2Inventory() {
_string[1].right = _mouseOverBoxesV2[i].rect.right - 1;
_string[1].color = _mouseOverBoxesV2[i].color;
+ _v0ObjectInInventory = true;
const byte *tmp = getObjOrActorName(obj);
+ _v0ObjectInInventory = false;
assert(tmp);
// Prevent inventory entries from overflowing by truncating the text
@@ -486,7 +516,7 @@ void ScummEngine_v2::handleMouseOver(bool updateInventory) {
}
void ScummEngine_v0::handleMouseOver(bool updateInventory) {
- //drawSentence();
+ drawSentence();
ScummEngine_v2::handleMouseOver(updateInventory);
}
@@ -644,8 +674,15 @@ void ScummEngine_v2::checkExecVerbs() {
if (object != -1) {
object = findInventory(_scummVars[VAR_EGO], object + 1 + _inventoryOffset);
- if (object > 0)
- runInputScript(kInventoryClickArea, object, 0);
+
+ if (object > 0) {
+ if (_game.version == 0) {
+ _activeInventory = object;
+
+ } else {
+ runInputScript(kInventoryClickArea, object, 0);
+ }
+ }
return;
}
@@ -666,9 +703,7 @@ void ScummEngine_v2::checkExecVerbs() {
runInputScript(kSentenceClickArea, 0, 0);
} else if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + inventoryArea) {
// Click into V2 inventory
- int object = checkV2Inventory(_mouse.x, _mouse.y);
- if (object > 0)
- runInputScript(kInventoryClickArea, object, 0);
+ checkV2Inventory(_mouse.x, _mouse.y);
} else {
over = findVerbAtPos(_mouse.x, _mouse.y);
if (over != 0) {
@@ -682,62 +717,313 @@ void ScummEngine_v2::checkExecVerbs() {
}
}
-int ScummEngine_v0::getVerbPrepId() {
- if (_verbs[_activeVerb].prep != 0xFF) {
- return _verbs[_activeVerb].prep;
+void ScummEngine_v0::runObject(int obj, int entry) {
+ bool prev = _v0ObjectInInventory;
+
+ if (getVerbEntrypoint(obj, entry) == 0) {
+ // If nothing was found, attempt to find the 'WHAT-IS' verb script
+ // (which is not really the what-is script, as this verb never actually executes
+ // it merely seems to be some type of fallback)
+ if (getVerbEntrypoint(obj, 0x0F) != 0) {
+ entry = 0x0F;
+ }
+ }
+
+ _v0ObjectInInventory = prev;
+
+ if (getVerbEntrypoint(obj, entry) != 0) {
+ _v0ObjectInInventory = prev;
+ runObjectScript(obj, entry, false, false, NULL);
+ } else if (entry != 13 && entry != 15) {
+ if (_activeVerb != 3) {
+ VAR(VAR_ACTIVE_VERB) = entry;
+ runScript(3, 0, 0, 0);
+
+ // For some reasons, certain objects don't have a "give" script
+ } else if (VAR(VAR_ACTIVE_ACTOR) > 0 && VAR(VAR_ACTIVE_ACTOR) < 8) {
+ if (_activeInventory)
+ setOwnerOf(_activeInventory, VAR(VAR_ACTIVE_ACTOR));
+ }
+ }
+}
+
+bool ScummEngine_v0::verbMoveToActor(int actor) {
+ Actor *a = derefActor(VAR(VAR_EGO), "verbMoveToActor");
+ Actor *a2 = derefActor(actor, "verbMoveToActor");
+ int dist = getDist(a->getRealPos().x, a->getRealPos().y, a2->getRealPos().x, a2->getRealPos().y);
+
+ if (!a->_moving && dist > 4) {
+ a->startWalkActor(a2->getRealPos().x, a2->getRealPos().y, -1);
} else {
- byte *ptr = getOBCDFromObject(OBJECT_V0(_activeObjectNr, _activeObjectType), true);
- assert(ptr);
- return (*(ptr + 11) >> 5);
+ if (dist <= 4) {
+ a->stopActorMoving();
+ return false;
+ }
}
+
+ return true;
}
-int ScummEngine_v0::activeVerbPrep() {
- if (!_activeVerb || !_activeObjectNr)
- return 0;
- return getVerbPrepId();
+bool ScummEngine_v0::verbMove(int object, int objectIndex, bool invObject) {
+ int x, y, dir;
+ Actor *a = derefActor(VAR(VAR_EGO), "verbMove");
+
+ if (_currentMode != 3 && _currentMode != 2)
+ return false;
+
+ _v0ObjectIndex = true;
+ getObjectXYPos(objectIndex, x, y, dir);
+ _v0ObjectIndex = false;
+
+ // Detect distance from target object
+ int dist = getDist(a->getRealPos().x, a->getRealPos().y, x, y);
+
+ if (a->_moving)
+ return true;
+
+ if (dist > 5) {
+ a->startWalkActor(x, y, dir);
+ VAR(6) = x;
+ VAR(7) = y;
+ return true;
+ } else {
+ // Finished walk, are we picking up the item?
+ if (_verbPickup) {
+ int oldActive = _activeObject, oldIndex = _activeObjectIndex;
+ _activeObject = object;
+ _activeObjectIndex = objectIndex;
+
+ _v0ObjectIndex = true;
+ // Execute pickup
+ runObject(objectIndex, 14);
+ _v0ObjectIndex = false;
+
+ _activeObject = oldActive;
+ _activeObjectIndex = oldIndex;
+
+ // Finished picking up
+ _verbPickup = false;
+ }
+ }
+
+ return false;
}
-void ScummEngine_v0::verbExec() {
- if (_activeVerb == kVerbWhatIs)
- return;
-
- if (_activeVerb != kVerbWalkTo || _activeObjectNr != 0) {
- doSentence(_activeVerb,
- OBJECT_V0(_activeObjectNr, _activeObjectType),
- OBJECT_V0(_activeObject2Nr, _activeObject2Type));
- if (_activeVerb != kVerbWalkTo) {
- _activeVerb = kVerbWalkTo;
- _activeObjectNr = 0;
- _activeObjectType = 0;
- _activeObject2Nr = 0;
- _activeObject2Type = 0;
+bool ScummEngine_v0::verbObtain(int obj, int objIndex) {
+ bool didPickup = false;
+
+ int prep, where = whereIsObjectInventory(obj);
+
+ if (objIndex == 0)
+ return false;
+
+ // Object in inventory ?
+ if (where != WIO_INVENTORY) {
+ _v0ObjectIndex = true;
+ prep = verbPrep(objIndex);
+
+ if (prep == 1 || prep == 4) {
+ if (_activeVerb != 13 && _activeVerb != 14) {
+ _verbPickup = true;
+ didPickup = true;
+ }
+ } else {
+ _verbPickup = false;
}
- _walkToObjectIdx = 0;
- return;
+
+ // Ignore verbs?
+ Actor *a = derefActor(VAR(VAR_EGO), "verbObtain");
+ if (((ActorC64 *)a)->_miscflags & 0x40) {
+ resetSentence(false);
+ return false;
+ }
+
+ //attempt move to object
+ if (verbMove(obj, objIndex, false))
+ return true;
+
+ if (didPickup && (prep == 1 || prep == 4))
+ if (_activeVerb != 13 && _activeVerb != 14) {
+ _v0ObjectInInventory = true;
+
+ if (whereIsObject(obj) == WIO_INVENTORY)
+ _activeInventory = obj;
+ else
+ resetSentence(false);
+
+ _v0ObjectInInventory = false;
+ }
}
- ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "verbExec");
- int x = _virtualMouse.x / V12_X_MULTIPLIER;
- int y = _virtualMouse.y / V12_Y_MULTIPLIER;
- //actorSetPosInBox();
+ return false;
+}
- // 0xB31
- VAR(6) = x;
- VAR(7) = y;
+int ScummEngine_v0::verbPrep(int object) {
+ if (!_v0ObjectInInventory)
+ _v0ObjectIndex = true;
+ else
+ _v0ObjectIndex = false;
- if (a->_miscflags & kActorMiscFlagFreeze)
- return;
+ byte *ptr = getOBCDFromObject(object);
+ _v0ObjectIndex = false;
+ assert(ptr);
+ return (*(ptr + 11) >> 5);
+}
+
+bool ScummEngine_v0::verbExecutes(int object, bool inventory) {
+ _v0ObjectInInventory = inventory;
+ int prep = verbPrep(object);
- a->stopActorMoving();
- a->startWalkActor(VAR(6), VAR(7), -1);
+ if (prep == 2 || prep == 0) {
+ return true;
+ }
+
+ return false;
}
-bool ScummEngine_v0::checkSentenceComplete() {
- if (_activeVerb && _activeVerb != kVerbWalkTo && _activeVerb != kVerbWhatIs) {
- if (_activeObjectNr && (!activeVerbPrep() || _activeObject2Nr))
+bool ScummEngine_v0::verbExec() {
+ int prep = 0;
+ int entry = (_currentMode != 0 && _currentMode != 1) ? _activeVerb : 15;
+
+ if ((!_activeInvExecute && _activeObject && getObjectIndex(_activeObject) == -1)) {
+ resetSentence(false);
+ return false;
+ }
+
+ // Lets try walk to the object
+ if (_activeObject && _activeObjectIndex && !_activeObjectObtained && _currentMode != 0) {
+ prep = verbPrep(_activeObjectIndex);
+
+ if (verbObtain(_activeObject, _activeObjectIndex))
+ return true;
+
+ _activeObjectObtained = true;
+ }
+
+ // Attempt to obtain/reach object2
+ if (_activeObject2 && _activeObject2Index && !_activeObject2Obtained && _currentMode != 0) {
+ prep = verbPrep(_activeObject2Index);
+
+ _v0ObjectInInventory = false;
+ if (verbObtain(_activeObject2, _activeObject2Index))
+ return true;
+
+ if (prep != 1 && prep != 4) {
+ _activeInventory = _activeObject;
+ _activeObject = _activeObject2;
+ _activeObjectIndex = _activeObject2Index;
+ _activeObject2 = 0;
+ _activeObject2Index = 0;
+ }
+
+ _activeObject2Obtained = true;
+ }
+
+ // Give-To
+ if (_activeVerb == 3 && _activeInventory && _activeActor) {
+ // FIXME: Actors need to turn and face each other
+ if (verbMoveToActor(_activeActor)) {
+ // Ignore verbs?
+ Actor *a = derefActor(VAR(VAR_EGO), "verbExec");
+ if (((ActorC64 *)a)->_miscflags & 0x40) {
+ resetSentence(false);
+ return false;
+ }
+
return true;
+ }
+ _v0ObjectInInventory = true;
+ VAR(VAR_ACTIVE_ACTOR) = _activeActor;
+ runObject(_activeInventory , 3);
+ _v0ObjectInInventory = false;
+
+ resetSentence(false);
+ return false;
+ }
+
+ // Where we performing an action on an actor?
+ if (_activeActor) {
+ _v0ObjectIndex = true;
+ runObject(_activeActor, entry);
+ _v0ObjectIndex = false;
+ _verbExecuting = false;
+
+ resetSentence(false);
+ return false;
+ }
+
+ // If we've finished walking (now near target), execute the action
+ if (_activeObject && _activeObjectIndex && verbPrep(_activeObjectIndex) == 2) {
+ _v0ObjectIndex = true;
+ runObject(_activeObjectIndex, entry);
+ _v0ObjectIndex = false;
+ _verbExecuting = false;
+
+ if ((_currentMode == 3 || _currentMode == 2) && _activeVerb == 13)
+ return false;
+
+ resetSentence(false);
+ return false;
}
+
+ // We acted on an inventory item
+ if (_activeInventory && verbExecutes(_activeInventory, true) && _activeVerb != 3) {
+ _v0ObjectInInventory = true;
+ _activeObject = _activeInventory;
+ runObject(_activeInventory, _activeVerb);
+
+ _verbExecuting = false;
+
+ if (_currentMode == 3 && _activeVerb == 13) {
+ resetSentence(true);
+ return false;
+ }
+
+ resetSentence(false);
+ return false;
+ }
+
+ // Item not in inventory is executed
+ if (_activeObject) {
+ _v0ObjectIndex = true;
+ runObject(_activeObjectIndex, entry);
+ _v0ObjectIndex = false;
+ } else if (_activeInventory) {
+ // Not sure this is the correct way to do this,
+ // however its working for most situations - segra
+ if (verbExecutes(_activeInventory, true) == false) {
+ if (_activeObject2 && _activeObject2Inv && verbExecutes(_activeObject2, true)) {
+ _v0ObjectInInventory = true;
+
+ _activeObject = _activeInventory;
+ _activeInventory = _activeObject2;
+
+ runObject(_activeObject, _activeVerb);
+ } else {
+ _v0ObjectInInventory = true;
+
+ if (_activeObject2) {
+ _activeObject = _activeObject2;
+
+ runObject(_activeObject, _activeVerb);
+ } else
+ runObject(_activeInventory, _activeVerb);
+ }
+ } else {
+ _v0ObjectInInventory = true;
+ runObject(_activeInventory, _activeVerb);
+ }
+ }
+
+ _verbExecuting = false;
+
+ if (_activeVerb == 13) {
+ resetSentence(true);
+ return false;
+ }
+
+ resetSentence(false);
+
return false;
}
@@ -745,154 +1031,231 @@ void ScummEngine_v0::checkExecVerbs() {
ActorC64 *a = (ActorC64 *)derefActor(VAR(VAR_EGO), "checkExecVerbs");
VirtScreen *zone = findVirtScreen(_mouse.y);
- int sentenceLineChanged = false;
- bool execute = false;
-
- //if (_userPut <= 0)
- // return;
-
- if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
- int over = findVerbAtPos(_mouse.x, _mouse.y);
- // click region: verbs
- if (over) {
- if (_activeVerb != over) { // new verb
- // keep first object if no preposition is used yet
- if (activeVerbPrep()) {
- _activeObjectNr = 0;
- _activeObjectType = 0;
- }
- _activeObject2Nr = 0;
- _activeObject2Type = 0;
+ // Is a verb currently executing
+ if (_verbExecuting) {
+ // Check if mouse click
+ if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
+ int over = findVerbAtPos(_mouse.x, _mouse.y);
+ int act = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
+ int obj = findObject(_virtualMouse.x, _virtualMouse.y);
+
+ if (over && over != _activeVerb) {
_activeVerb = over;
- sentenceLineChanged = true;
+ _verbExecuting = false;
+ return;
+ }
+
+ if (!obj && !act && !over) {
+ resetSentence(false);
} else {
- // execute sentence if complete
- if (checkSentenceComplete())
- execute = true;
+ a->stopActorMoving();
}
+ } else {
+
+ if (_verbExecuting && !verbExec())
+ return;
}
}
- if (a->_miscflags & kActorMiscFlagHide) {
- if (_activeVerb != kVerbNewKid) {
- _activeVerb = kVerbNone;
- }
+ // What-Is selected, any object we hover over is selected, on mouse press we set to WalkTo
+ if (_activeVerb == 15) {
+ int obj = findObject(_virtualMouse.x, _virtualMouse.y);
+ int objIdx = findObjectIndex(_virtualMouse.x, _virtualMouse.y);
+ _activeObject = obj;
+ _activeObjectIndex = objIdx;
+
+ if ((_mouseAndKeyboardStat & MBS_MOUSE_MASK))
+ _activeVerb = 13; // Walk-To
+
+ return;
}
- if (_currentMode != kModeCutscene) {
- if (_currentMode == kModeKeypad) {
- _activeVerb = kVerbPush;
- }
+ if (_userPut <= 0 || _mouseAndKeyboardStat == 0)
+ return;
+
+ if (_mouseAndKeyboardStat < MBS_MAX_KEY) {
+ /* Check keypresses */
+ // TODO
+ } else if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
+ if (zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
+ // TODO
+ } else if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) {
+ int prevInventory = _activeInventory;
+ int invOff = _inventoryOffset;
+
+ // Click into V2 inventory
+ checkV2Inventory(_mouse.x, _mouse.y);
+
+ // Did the Inventory position changed (arrows pressed, do nothing)
+ if (invOff != _inventoryOffset)
+ return;
- if (_mouseAndKeyboardStat > 0 && _mouseAndKeyboardStat < MBS_MAX_KEY) {
- // TODO: check keypresses
- } else if ((_mouseAndKeyboardStat & MBS_MOUSE_MASK) || _activeVerb == kVerbWhatIs) {
- // click region: sentence line
- if (zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
- if (_activeVerb == kVerbNewKid) {
- if (_currentMode == kModeNormal) {
- int kid;
- int lineX = _mouse.x >> V12_X_SHIFT;
- if (lineX < 11)
- kid = 0;
- else if (lineX < 25)
- kid = 1;
- else
- kid = 2;
- _activeVerb = kVerbWalkTo;
- drawSentenceLine();
- switchActor(kid);
+ // No inventory selected?
+ if (!_activeInventory)
+ return;
+
+ // Did we just change the selected inventory item?
+ if (prevInventory && prevInventory != _activeInventory && _activeInventory != _activeObject2) {
+ _v0ObjectInInventory = true;
+ int prep = verbPrep(_activeInventory);
+ _v0ObjectInInventory = true;
+ int prep2 = verbPrep(prevInventory);
+
+ // Should the new inventory object remain as the secondary selected object
+ // Or should the new inventory object become primary?
+ if (prep != prep2 || prep != 1) {
+ if (prep == 1 || prep == 3) {
+ int tmp = _activeInventory;
+ _activeInventory = prevInventory;
+ prevInventory = tmp;
}
- _activeVerb = kVerbWalkTo;
+ }
+
+ // Setup object2
+ _activeObject = 0;
+ _activeInvExecute = true;
+ _activeObject2Inv = true;
+ _activeObject2 = _activeInventory;
+ _activeInventory = prevInventory;
+ return;
+ }
+
+ // is the new selected inventory the same as the last selected?, reset to previous if it is
+ if (_activeInventory == _activeObject2)
+ _activeInventory = prevInventory;
+
+ // Inventory Selected changed
+ if (prevInventory != _activeInventory)
+ if (!_activeObject2 || prevInventory != _activeObject2)
+ return;
+
+ if (_activeVerb == 11 && !(((_activeObject || _activeInventory)) || !_activeObject2))
+ return;
+ } else {
+ int over = findVerbAtPos(_mouse.x, _mouse.y);
+ int act = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
+ int obj = findObject(_virtualMouse.x, _virtualMouse.y);
+ int objIdx = findObjectIndex(_virtualMouse.x, _virtualMouse.y);
+
+ // If we already have an object selected, and we just clicked an actor
+ // Clear any object we may of also clicked on
+ if ((_activeObject || _activeInventory) && act) {
+ obj = 0;
+ objIdx = 0;
+ }
+
+ if (a->_miscflags & 0x80) {
+ if (_activeVerb != 7 && over != 7) {
+ _activeVerb = 0;
+ over = 0;
+ }
+ }
+
+ // Handle New Kid verb options
+ if (_activeVerb == 7 || over == 7) {
+ // Disable New-Kid (in the secret lab)
+ if (_currentMode == 2 || _currentMode == 0)
+ return;
+
+ if (_activeVerb == 7 && over) {
+ _activeVerb = 13;
+ switchActor(_verbs[over].verbid - 1);
return;
- } else {
- // execute sentence if complete
- if (checkSentenceComplete())
- execute = true;
}
- // click region: inventory or main screen
- } else if ((zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) ||
- (zone->number == kMainVirtScreen))
- {
- int obj = 0;
-
- // click region: inventory
- if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) {
- // click into inventory
- int invOff = _inventoryOffset;
- obj = checkV2Inventory(_mouse.x, _mouse.y);
- if (invOff != _inventoryOffset) {
- // inventory position changed (arrows pressed, do nothing)
+
+ setNewKidVerbs();
+ _activeVerb = 7;
+
+ return;
+ }
+
+ // Clicked on nothing, walk here?
+ if (!over && !act && _activeVerb == 13 && !obj && _currentMode != 0) {
+ // Clear all selected
+ resetSentence(false);
+
+ // 0xB31
+ VAR(6) = _virtualMouse.x / V12_X_MULTIPLIER;
+ VAR(7) = _virtualMouse.y / V12_Y_MULTIPLIER;
+
+ if (zone->number == kMainVirtScreen) {
+ // Ignore verbs?
+ if (a->_miscflags & 0x40) {
+ resetSentence(false);
return;
}
- // click region: main screen
- } else if (zone->number == kMainVirtScreen) {
- // click into main screen
- if (_activeVerb == kVerbGive && _activeObjectNr) {
- obj = OBJECT_V0(getActorFromPos(_virtualMouse.x, _virtualMouse.y), kObjectTypeActor);
- } else {
- obj = findObject(_virtualMouse.x, _virtualMouse.y);
- }
+ a->stopActorMoving();
+ a->startWalkActor(VAR(6), VAR(7), -1);
+ _verbExecuting = true;
}
+ return;
+ }
- int id = OBJECT_V0_NR(obj);
- int type = OBJECT_V0_TYPE(obj);
- debug("found 0x%03x", obj);
+ // No new verb, use previous
+ if (over == 0)
+ over = _activeVerb;
- if (!id) {
- if (_activeVerb == kVerbWalkTo) {
- _activeObjectNr = 0;
- _activeObjectType = 0;
- _activeObject2Nr = 0;
- _activeObject2Type = 0;
+ // No verb selected, use walk-to
+ if (!_activeVerb)
+ _activeVerb = over = 13; // Walk-To
+
+ // New verb selected
+ if (_activeVerb != over) {
+ _activeVerb = over;
+ if (_activeVerb == 13) {
+ resetSentence(false);
+ }
+ return;
+ }
+
+ // Only allowing targetting actors if its the GIVE/USE verb
+ if (_activeVerb == 3 || _activeVerb == 11) {
+ // Different actor selected?
+ if (act) {
+ if (_activeActor != act) {
+ _activeActor = act;
+ return;
}
- } else {
- if (activeVerbPrep() == kVerbPrepNone) {
- if (id == _activeObjectNr && type == _activeObjectType) {
- execute = true;
+ }
+ }
+
+ if (obj && obj != _activeObject) {
+ if (!_activeObject)
+ if (_activeInventory)
+ _activeInvExecute = true;
+
+ // USE
+ if (_activeVerb == 11 || _activeVerb == 8) {
+ if (obj != _activeObject || obj != _activeObject2) {
+ if (!_activeObject || _activeInventory) {
+ _activeObject = obj;
+ _activeObjectIndex = objIdx;
+ return;
} else {
- _activeObjectNr = id;
- _activeObjectType = type;
- }
- // immediately execute action in keypad/selection mode
- if (_currentMode == kModeKeypad)
- execute = true;
- } else {
- if (id == _activeObject2Nr && type == _activeObject2Type)
- execute = true;
- if (!(id == _activeObjectNr && type == _activeObjectType)) {
- _activeObject2Nr = id;
- _activeObject2Type = type;
- if (_currentMode == kModeKeypad)
- execute = true;
+ if (_activeObject2 != obj) {
+ _activeObject2 = obj;
+ _activeObject2Index = objIdx;
+ return;
+ }
}
}
- }
+ } else {
+ a->stopActorMoving();
+
+ _activeObject = obj;
+ _activeObjectIndex = objIdx;
- sentenceLineChanged = true;
- if (_activeVerb == kVerbWalkTo && zone->number == kMainVirtScreen) {
- _walkToObjectIdx = 0;
- execute = true;
+ if (_activeVerb != 13)
+ return;
+
+ //return;
}
}
}
- }
-
- if (sentenceLineChanged) {
- drawSentenceLine();
- sentenceLineChanged = false;
- }
- if (!execute || !_activeVerb)
- return;
+ _verbExecuting = true;
- if (_activeVerb == kVerbWalkTo)
- verbExec();
- else if (_activeObjectNr) {
- // execute if we have a 1st object and either have or do not need a 2nd
- if (activeVerbPrep() == kVerbPrepNone || _activeObject2Nr)
- verbExec();
- }
+ } // mouse k/b action
}
void ScummEngine::verbMouseOver(int verb) {
diff --git a/engines/scumm/verbs.h b/engines/scumm/verbs.h
index fce260e..fb4dc96 100644
--- a/engines/scumm/verbs.h
+++ b/engines/scumm/verbs.h
@@ -57,34 +57,6 @@ struct VerbSlot {
uint16 imgindex;
};
-enum VerbsV0 {
- kVerbNone = 0,
- kVerbOpen = 1,
- kVerbClose = 2,
- kVerbGive = 3,
- kVerbTurnOn = 4,
- kVerbTurnOff = 5,
- kVerbFix = 6,
- kVerbNewKid = 7,
- kVerbUnlock = 8,
- kVerbPush = 9,
- kVerbPull = 10,
- kVerbUse = 11,
- kVerbRead = 12,
- kVerbWalkTo = 13,
- kVerbPickUp = 14,
- kVerbWhatIs = 15
-};
-
-enum VerbPrepsV0 {
- kVerbPrepNone = 0,
- kVerbPrepIn = 1,
- kVerbPrepWith = 2,
- kVerbPrepOn = 3,
- kVerbPrepTo = 4,
- kVerbPrepObject = 0xFF, // prep depends on object (USE)
-};
-
} // End of namespace Scumm
#endif
More information about the Scummvm-git-logs
mailing list