Add patch #2821100 - MM C64 Objects / Verb fixes, with minor clean up applied.

svn-id: r42737
This commit is contained in:
Travis Howell 2009-07-25 06:27:41 +00:00
parent 41ef4938ac
commit c02ad3b7bf
11 changed files with 647 additions and 99 deletions

View File

@ -181,7 +181,11 @@ 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) {
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);
_inventory[i] = 0;
@ -286,7 +290,7 @@ int ScummEngine::getState(int obj) {
// it. Fortunately this does not prevent frustrated players from
// blowing up the mansion, should they feel the urge to.
if (_game.id == GID_MANIAC && (obj == 182 || obj == 193))
if (_game.id == GID_MANIAC && _game.version != 0 && (obj == 182 || obj == 193))
_objectStateTable[obj] |= kObjectState_08;
}
@ -317,6 +321,15 @@ int ScummEngine::getObjectIndex(int object) const {
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;
@ -326,7 +339,7 @@ int ScummEngine::whereIsObject(int object) const {
if (object < 1)
return WIO_NOT_FOUND;
if (_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;
@ -334,7 +347,7 @@ int ScummEngine::whereIsObject(int object) const {
}
for (i = (_numLocalObjects-1); i > 0; i--)
if (_objs[i].obj_nr == object) {
if ((_objs[i].obj_nr == object && !_v0ObjectIndex) || (_v0ObjectIndex && i == object)) {
if (_objs[i].fl_object_index)
return WIO_FLOBJECT;
return WIO_ROOM;
@ -379,7 +392,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,7 +447,7 @@ void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) {
dir = oldDirToNewDir(od.actordir & 3);
}
static int getDist(int x, int y, int x2, int y2) {
int ScummEngine::getDist(int x, int y, int x2, int y2) {
int a = ABS(y - y2);
int b = ABS(x - x2);
return MAX(a, b);
@ -475,6 +488,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;
@ -505,6 +526,9 @@ 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)
if (_game.version == 0 && _v0ObjectIndex)
return i;
else
return _objs[i].obj_nr;
break;
}
@ -811,6 +835,9 @@ void ScummEngine_v3old::resetRoomObjects() {
if (_dumpScripts) {
char buf[32];
sprintf(buf, "roomobj-%d-", _roomResource);
if (_game.version == 0)
sprintf(buf + 11, "%d-", od->flags);
dumpResource(buf, od->obj_nr, room + od->OBCDoffset);
}
}
@ -1033,6 +1060,10 @@ void ScummEngine::updateObjectStates() {
int i;
ObjectData *od = &_objs[1];
for (i = 1; i < _numLocalObjects; i++, od++) {
// 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)
od->state = getState(od->obj_nr);
}
@ -1155,7 +1186,7 @@ const byte *ScummEngine::getObjOrActorName(int obj) {
void ScummEngine::setObjectName(int obj) {
int i;
if (obj < _numActors)
if (obj < _numActors && _game.version != 0)
error("Can't set actor %d name with new-name-of", obj);
for (i = 0; i < _numNewNames; i++) {
@ -1181,8 +1212,13 @@ void ScummEngine::setObjectName(int obj) {
uint32 ScummEngine::getOBCDOffs(int object) const {
int i;
if (_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--) {
if (_objs[i].obj_nr == object) {
if (_objs[i].fl_object_index != 0)
@ -1194,17 +1230,20 @@ uint32 ScummEngine::getOBCDOffs(int object) const {
}
byte *ScummEngine::getOBCDFromObject(int obj) {
bool useInventory = _v0ObjectInInventory;
int i;
byte *ptr;
if (_objectOwnerTable[obj] != OF_OWNER_ROOM) {
_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) {
if (_objs[i].obj_nr == obj) {
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);

View File

@ -1384,9 +1384,12 @@ void ScummEngine::saveOrLoad(Serializer *s) {
void ScummEngine_v0::saveOrLoad(Serializer *s) {
ScummEngine::saveOrLoad(s);
// TODO: Save additional variables
// _currentMode
// _currentLights
const SaveLoadEntry v0Entrys[] = {
MKLINE(ScummEngine_v0, _currentMode, sleByte, VER(78)),
MKLINE(ScummEngine_v0, _currentLights, sleByte, VER(78)),
MKEND()
};
s->saveLoadEntries(this, v0Entrys);
}
void ScummEngine_v5::saveOrLoad(Serializer *s) {

View File

@ -50,7 +50,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
#define CURRENT_VER 77
#define CURRENT_VER 78
/**
* An auxillary macro, used to specify savegame versions. We use this instead

View File

@ -133,6 +133,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);
}

View File

@ -410,41 +410,43 @@ void ScummEngine_v0::decodeParseString() {
actorTalk(buffer);
}
void ScummEngine_v0::drawSentence() {
Common::Rect sentenceline;
void ScummEngine_v0::drawSentenceWord(int object, bool usePrep, bool objInInventory) {
const byte *temp;
int sentencePrep = 0;
if (!(_userState & 32))
return;
// If object not in inventory, we except an index
if (!objInInventory)
_v0ObjectIndex = true;
else
_v0ObjectInInventory = true;
if (getResourceAddress(rtVerb, _activeVerb)) {
strcpy(_sentenceBuf, (char*)getResourceAddress(rtVerb, _activeVerb));
} else {
return;
}
temp = getObjOrActorName(object);
if (_activeObject > 0) {
temp = getObjOrActorName(_activeObject);
_v0ObjectInInventory = false;
_v0ObjectIndex = false;
// Append the 'object-name'
if (temp) {
strcat(_sentenceBuf, " ");
strcat(_sentenceBuf, (const char*)temp);
}
// Append the modifier? (With / On / To / In)
if (!usePrep)
return;
if (_verbs[_activeVerb].prep == 0xFF) {
byte *ptr = getOBCDFromObject(_activeObject);
assert(ptr);
sentencePrep = (*(ptr + 11) >> 5);
_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.
const char *prepositions[][5] = {
static const char *prepositions[][5] = {
{ " ", " in", " with", " on", " to" }, // English
{ " ", " mit", " mit", " mit", " zu" }, // German
{ " ", " dans", " avec", " sur", " <" }, // French
@ -471,13 +473,65 @@ void ScummEngine_v0::drawSentence() {
strcat(_sentenceBuf, prepositions[lang][sentencePrep]);
}
if (_activeInventory > 0) {
temp = getObjOrActorName(_activeInventory);
if (temp) {
strcat(_sentenceBuf, " ");
strcat(_sentenceBuf, (const char*)temp);
}
void ScummEngine_v0::drawSentence() {
Common::Rect sentenceline;
bool inventoryFirst = false;
if (!(_userState & 32))
return;
// Current Verb, Walk/Use
if (getResourceAddress(rtVerb, _activeVerb)) {
strcpy(_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, "");
strcat(_sentenceBuf, " ");
strcat(_sentenceBuf, (const char*)a->getActorName());
}
_string[2].charset = 1;
@ -664,6 +718,7 @@ void ScummEngine_v0::o_animateActor() {
int act = getVarOrDirectByte(PARAM_1);
int anim = getVarOrDirectByte(PARAM_2);
int unk = fetchScriptByte();
debug(0,"o_animateActor: unk %d", unk);
ActorC64 *a = (ActorC64*) derefActor(act, "o_animateActor");
@ -725,7 +780,7 @@ void ScummEngine_v0::o_pickupObject() {
if (getObjectIndex(obj) == -1)
return;
if (whereIsObject(obj) == WIO_INVENTORY) /* Don't take an */
if (whereIsObjectInventory(_activeObject2) == WIO_INVENTORY) /* Don't take an */
return; /* object twice */
addObjectToInventory(obj, _roomResource);
@ -917,10 +972,25 @@ void ScummEngine_v0::o_setOwnerOf() {
setOwnerOf(obj, owner);
}
void ScummEngine_v0::resetSentence() {
void ScummEngine_v0::resetSentence(bool walking) {
_activeVerb = 13;
if (!walking) {
_activeInventory = 0;
_activeObject = 0;
_activeVerb = 13;
_activeObject2 = 0;
_activeObjectIndex = 0;
_activeObject2Index = 0;
}
_verbExecuting = false;
_verbPickup = false;
_activeActor = 0;
_activeInvExecute = false;
_activeObject2Inv = false;
_activeObjectObtained = false;
_activeObject2Obtained = false;
}
} // End of namespace Scumm

View File

@ -134,6 +134,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
// Init all vars
_v0ObjectIndex = false;
_v0ObjectInInventory = false;
_imuse = NULL;
_imuseDigital = NULL;
_musicEngine = NULL;
@ -664,7 +666,17 @@ 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;
_activeObject2 = 0;
_activeObjectIndex = 0;
_activeObject2Index = 0;
_activeInvExecute = false;
_activeObject2Inv = false;
_activeObjectObtained = false;
_activeObject2Obtained = false;
}
ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr)

View File

@ -565,6 +565,9 @@ protected:
int32 *_scummVars;
byte *_bitVars;
bool _v0ObjectIndex; // V0 Use object index, instead of object number
bool _v0ObjectInInventory; // V0 Use object number from inventory
/* Global resource tables */
int _numVariables, _numBitVariables, _numLocalObjects;
int _numGlobalObjects, _numArray, _numVerbs, _numFlObject;
@ -858,12 +861,14 @@ 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);
public:
int getObjectOrActorXY(int object, int &x, int &y); // Used in actor.cpp, hence public
protected:
int getDist(int x, int y, int x2, int y2);
int getObjActToObjActDist(int a, int b); // Not sure how to handle
const byte *getObjOrActorName(int obj); // these three..
void setObjectName(int obj);

View File

@ -35,7 +35,20 @@ namespace Scumm {
*/
class ScummEngine_v0 : public ScummEngine_v2 {
protected:
int _currentMode;
byte _currentMode;
bool _verbExecuting; // is a verb executing
bool _verbPickup; // are we picking up an object during a verb execute
int _activeActor; // Actor Number
int _activeObject2; // 2nd Object Number
bool _activeInvExecute; // is activeInventory first to be executed
bool _activeObject2Inv; // is activeobject2 in the inventory
bool _activeObjectObtained; // collected _activeobject?
bool _activeObject2Obtained; // collected _activeObject2?
int _activeObjectIndex;
int _activeObject2Index;
public:
ScummEngine_v0(OSystem *syst, const DetectorResult &dr);
@ -53,12 +66,25 @@ protected:
virtual void processInput();
virtual void runObject(int obj, int entry);
virtual void saveOrLoad(Serializer *s);
// V0 MM Verb commands
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);
void resetVerbs();
void setNewKidVerbs();
void drawSentenceWord(int object, bool usePrep, bool objInInventory);
void drawSentence();
void switchActor(int slot);
@ -68,7 +94,7 @@ protected:
virtual int getActiveObject();
virtual void resetSentence();
virtual void resetSentence(bool walking = false);
/* Version C64 script opcodes */
void o_stopCurrentScript();

View File

@ -100,7 +100,7 @@ protected:
virtual void setBuiltinCursor(int index);
void runObject(int obj, int entry);
virtual void runObject(int obj, int entry);
/* Version 2 script opcodes */
void o2_actorFromPos();

View File

@ -538,9 +538,7 @@ void ScummEngine_v8::setupScummVars() {
#endif
void ScummEngine_v0::resetScummVars() {
_activeInventory = 0;
_activeObject = 0;
_activeVerb = 13;
resetSentence();
VAR(VAR_EGO) = 3;

View File

@ -155,6 +155,7 @@ void ScummEngine_v0::switchActor(int slot) {
VAR(VAR_EGO) = VAR(97 + slot);
actorFollowCamera(VAR(VAR_EGO));
resetVerbs();
resetSentence(false);
setUserState(247);
}
@ -376,14 +377,8 @@ void ScummEngine_v2::checkV2Inventory(int x, int y) {
if (object > 0) {
if (_game.version == 0) {
if (_activeInventory != object) {
_activeInventory = object;
} else if (_activeVerb != 3 && _activeVerb != 13) {
if (_activeObject)
runObject(_activeObject, _activeVerb);
else
runObject(_activeInventory, _activeVerb);
}
} else {
runInputScript(kInventoryClickArea, object, 0);
}
@ -425,7 +420,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
@ -666,6 +663,25 @@ void ScummEngine_v2::checkExecVerbs() {
}
}
void ScummEngine_v0::runObject(int obj, int entry) {
int prev = _v0ObjectInInventory;
if (getVerbEntrypoint(obj, entry) != 0) {
_v0ObjectInInventory = prev;
runObjectScript(obj, entry, false, false, NULL);
} else if (entry != 13 && entry != 15) {
if (_activeVerb != 3) {
VAR(9) = entry;
runScript(3, 0, 0, 0);
// For some reasons, certain objects don't have a "give" script
} else if (VAR(5) > 0 && VAR(5) < 8) {
if (_activeInventory)
setOwnerOf(_activeInventory, VAR(5));
}
}
}
void ScummEngine_v2::runObject(int obj, int entry) {
if (getVerbEntrypoint(obj, entry) != 0) {
runObjectScript(obj, entry, false, false, NULL);
@ -679,10 +695,299 @@ void ScummEngine_v2::runObject(int obj, int entry) {
_activeVerb = 13;
}
bool ScummEngine_v0::verbMoveToActor(int actor) {
Actor *a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
Actor *a2 =derefActor(actor, "checkExecVerbs");
if (!a->_moving) {
int dist = getDist(a->getRealPos().x, a->getRealPos().y, a2->getRealPos().x, a2->getRealPos().y);
if (dist>5)
a->startWalkActor(a2->getRealPos().x, a2->getRealPos().y, 1);
else
return false;
return true;
}
return true;
}
bool ScummEngine_v0::verbMove(int object, int objectIndex, bool invObject) {
int x, y, dir;
Actor *a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
if (_currentMode != 3 && _currentMode != 2)
return false;
if (a->_moving)
return true;
_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);
// FIXME: This should be changed once the walkbox problem is fixed
if (dist>0x5) {
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;
}
bool ScummEngine_v0::verbObtain(int obj, int objIndex) {
bool didPickup = false;
int prep, where = whereIsObjectInventory(obj);
if (objIndex == 0)
return false;
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;
}
if (verbMove(obj, objIndex, false))
return true;
if (didPickup && (prep == 1 || prep == 4))
if (_activeVerb != 13 && _activeVerb != 14)
_activeInventory = obj;
}
return false;
}
int ScummEngine_v0::verbPrep(int object) {
if (!_v0ObjectInInventory)
_v0ObjectIndex = true;
else
_v0ObjectIndex = false;
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);
if (prep == 2 || prep == 0) {
return true;
}
return false;
}
bool ScummEngine_v0::verbExec() {
int prep = 0;
int entry = (_currentMode != 0 && _currentMode != 1) ? _activeVerb : 15;
if ((!_activeInvExecute && _activeObject && getObjectIndex(_activeObject) == -1)) {
resetSentence();
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;
}
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
// And walk to each other
//
if (verbMoveToActor(_activeActor))
return true;
_v0ObjectInInventory = true;
VAR(5) = _activeActor;
runObject(_activeInventory , 3);
_v0ObjectInInventory = false;
resetSentence();
return false;
}
if (_activeActor) {
_v0ObjectIndex = true;
runObject(_activeActor, entry);
_v0ObjectIndex = false;
_verbExecuting = false;
resetSentence();
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();
return false;
}
// We acted on an inventory item
if (_activeInventory && verbExecutes(_activeInventory, true) && _activeVerb != 3) {
_v0ObjectInInventory = true;
runObject(_activeInventory, _activeVerb);
_verbExecuting = false;
if (_currentMode == 3 && _activeVerb == 13) {
resetSentence(true);
return false;
}
resetSentence();
return false;
}
if (_activeObject) {
_v0ObjectIndex = true;
runObject(_activeObjectIndex, entry);
_v0ObjectIndex = false;
} else if (_activeInventory) {
if (verbExecutes(_activeInventory, true) == false) {
if (_activeObject2 && verbExecutes(_activeObject2, true)) {
_v0ObjectInInventory = true;
_activeObject = _activeInventory;
_activeInventory = _activeObject2;
runObject(_activeObject, _activeVerb);
} else {
_v0ObjectInInventory = true;
runObject(_activeInventory, _activeVerb);
}
} else {
runObject(_activeInventory, _activeVerb);
_v0ObjectInInventory = true;
}
}
_verbExecuting = false;
if (_activeVerb == 13) {
resetSentence(true);
return false;
}
resetSentence();
return false;
}
void ScummEngine_v0::checkExecVerbs() {
Actor *a;
VirtScreen *zone = findVirtScreen(_mouse.y);
// 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;
_verbExecuting = false;
return;
}
if (!obj && !act && !over) {
resetSentence(false);
} else {
a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
a->stopActorMoving();
}
} else {
if (_verbExecuting && !verbExec())
return;
}
}
// 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 (_userPut <= 0 || _mouseAndKeyboardStat == 0)
return;
@ -693,61 +998,149 @@ void ScummEngine_v0::checkExecVerbs() {
if (zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
// TODO
} else if (zone->number == kVerbVirtScreen && _mouse.y > zone->topline + 32) {
int prevInventory = _activeInventory;
// Click into V2 inventory
checkV2Inventory(_mouse.x, _mouse.y);
} else {
int over = findVerbAtPos(_mouse.x, _mouse.y);
if (!_activeInventory)
return;
// Handle New Kid verb options
if (_activeVerb == 7) {
if (over) {
_activeVerb = 13;
switchActor(_verbs[over].verbid - 1);
}
// Did we just change the selected inventory item?
if (prevInventory && prevInventory != _activeInventory && _activeInventory != _activeObject2) {
_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 ((_activeObject || _activeInventory) && act) {
obj = 0;
objIdx = 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) {
_activeVerb = over;
over = 0;
}
if (over) {
_activeVerb = _verbs[over].verbid;
// Selected New Kid verb
if (_activeVerb == 7)
_activeVerb = 13;
switchActor(_verbs[over].verbid - 1);
return;
}
setNewKidVerbs();
return;
}
int act = getActorFromPos(_virtualMouse.x, _virtualMouse.y);
int obj = findObject(_virtualMouse.x, _virtualMouse.y);
if (act != 0 && _activeVerb == 3 && _activeInventory != 0) {
// Give inventory item to actor
VAR(5) = act;
runObject(_activeInventory, _activeVerb);
} else if (obj) {
if (_currentMode == 3 && _activeVerb != 13 && obj != _activeObject) {
_activeObject = obj;
// Clicked on nothing, walk here?
if (!over && !act && _activeVerb == 13 && !obj && _currentMode != 0) {
// Clear all selected
resetSentence();
// 0xB31
VAR(6) = _virtualMouse.x / V12_X_MULTIPLIER;
VAR(7) = _virtualMouse.y / V12_Y_MULTIPLIER;
if (zone->number == kMainVirtScreen) {
a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
a->stopActorMoving();
a->startWalkActor(_virtualMouse.x / V12_X_MULTIPLIER, _virtualMouse.y / V12_Y_MULTIPLIER, -1);
}
return;
}
// No new verb, use previous
if (over == 0)
over = _activeVerb;
// 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();
}
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;
}
}
}
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;
if (_currentMode == 3) {
int x, y, dir;
a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
getObjectXYPos(obj, x, y, dir);
a->startWalkActor(x, y, dir);
_activeObjectIndex = objIdx;
return;
} else {
if (_activeObject2 != obj) {
_activeObject2 = obj;
_activeObject2Index = objIdx;
return;
}
}
}
} else {
_activeObject = obj;
_activeObjectIndex = objIdx;
if (_activeVerb != 13)
return;
//return;
}
}
}
int entry = (_currentMode == 3) ? _activeVerb : 15;
runObject(_activeObject, entry);
} else if (zone->number == kMainVirtScreen) {
a = derefActor(VAR(VAR_EGO), "checkExecVerbs");
a->startWalkActor(_virtualMouse.x / V12_X_MULTIPLIER, _virtualMouse.y / V12_Y_MULTIPLIER, -1);
}
_verbExecuting = true;
_activeInventory = 0;
_activeObject = 0;
_activeVerb = 13;
}
}
} // mouse k/b action
}
void ScummEngine::verbMouseOver(int verb) {