mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-04 16:26:53 +00:00
Add patch #2821100 - MM C64 Objects / Verb fixes, with minor clean up applied.
svn-id: r42737
This commit is contained in:
parent
41ef4938ac
commit
c02ad3b7bf
@ -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) {
|
||||
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);
|
||||
_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,7 +526,10 @@ 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)
|
||||
return _objs[i].obj_nr;
|
||||
if (_game.version == 0 && _v0ObjectIndex)
|
||||
return i;
|
||||
else
|
||||
return _objs[i].obj_nr;
|
||||
break;
|
||||
}
|
||||
} while ((_objs[b].state & mask) == a);
|
||||
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 object not in inventory, we except an index
|
||||
if (!objInInventory)
|
||||
_v0ObjectIndex = true;
|
||||
else
|
||||
_v0ObjectInInventory = true;
|
||||
|
||||
if (!(_userState & 32))
|
||||
return;
|
||||
temp = getObjOrActorName(object);
|
||||
|
||||
if (getResourceAddress(rtVerb, _activeVerb)) {
|
||||
strcpy(_sentenceBuf, (char*)getResourceAddress(rtVerb, _activeVerb));
|
||||
} else {
|
||||
return;
|
||||
_v0ObjectInInventory = false;
|
||||
_v0ObjectIndex = false;
|
||||
|
||||
// Append the 'object-name'
|
||||
if (temp) {
|
||||
strcat(_sentenceBuf, " ");
|
||||
strcat(_sentenceBuf, (const char*)temp);
|
||||
}
|
||||
|
||||
if (_activeObject > 0) {
|
||||
temp = getObjOrActorName(_activeObject);
|
||||
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);
|
||||
} else {
|
||||
sentencePrep = _verbs[_activeVerb].prep;
|
||||
}
|
||||
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.
|
||||
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,9 +780,9 @@ 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);
|
||||
markObjectRectAsDirty(obj);
|
||||
putOwner(obj, VAR(VAR_EGO));
|
||||
@ -917,10 +972,25 @@ void ScummEngine_v0::o_setOwnerOf() {
|
||||
setOwnerOf(obj, owner);
|
||||
}
|
||||
|
||||
void ScummEngine_v0::resetSentence() {
|
||||
_activeInventory = 0;
|
||||
_activeObject = 0;
|
||||
void ScummEngine_v0::resetSentence(bool walking) {
|
||||
_activeVerb = 13;
|
||||
|
||||
if (!walking) {
|
||||
_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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -538,9 +538,7 @@ void ScummEngine_v8::setupScummVars() {
|
||||
#endif
|
||||
|
||||
void ScummEngine_v0::resetScummVars() {
|
||||
_activeInventory = 0;
|
||||
_activeObject = 0;
|
||||
_activeVerb = 13;
|
||||
resetSentence();
|
||||
|
||||
VAR(VAR_EGO) = 3;
|
||||
|
||||
|
@ -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);
|
||||
if (!_activeInventory)
|
||||
return;
|
||||
|
||||
// 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) {
|
||||
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 = 13;
|
||||
switchActor(_verbs[over].verbid - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (over) {
|
||||
_activeVerb = _verbs[over].verbid;
|
||||
// Selected New Kid verb
|
||||
if (_activeVerb == 7)
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
_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);
|
||||
}
|
||||
setNewKidVerbs();
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
_activeInventory = 0;
|
||||
_activeObject = 0;
|
||||
_activeVerb = 13;
|
||||
// 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;
|
||||
_activeObjectIndex = objIdx;
|
||||
return;
|
||||
} else {
|
||||
if (_activeObject2 != obj) {
|
||||
_activeObject2 = obj;
|
||||
_activeObject2Index = objIdx;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_activeObject = obj;
|
||||
_activeObjectIndex = objIdx;
|
||||
|
||||
if (_activeVerb != 13)
|
||||
return;
|
||||
|
||||
//return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_verbExecuting = true;
|
||||
|
||||
} // mouse k/b action
|
||||
}
|
||||
|
||||
void ScummEngine::verbMouseOver(int verb) {
|
||||
|
Loading…
Reference in New Issue
Block a user