ILLUSIONS: Work on interaction; work on Cause related code

This commit is contained in:
johndoe123 2014-03-26 14:04:17 +01:00 committed by Eugene Sandulenko
parent e05a789975
commit 22e898f7eb
11 changed files with 279 additions and 22 deletions

View File

@ -861,15 +861,14 @@ bool Controls::getOverlappedObject(Control *control, Common::Point pt, Control *
(!testControl->_actor || (testControl->_actor->_flags & 1))) {
Common::Rect collisionRect;
testControl->getCollisionRect(collisionRect);
debug("collisionRect(%d, %d, %d, %d)", collisionRect.left, collisionRect.top, collisionRect.right, collisionRect.bottom);
debug("pt(%d, %d)", pt.x, pt.y);
//debug("collisionRect(%d, %d, %d, %d)", collisionRect.left, collisionRect.top, collisionRect.right, collisionRect.bottom);
//debug("pt(%d, %d)", pt.x, pt.y);
if (!collisionRect.isEmpty() && collisionRect.contains(pt)) {
int testPriority = testControl->getPriority();
debug("testPriority: %d; minPriority: %d", testPriority, minPriority);
//debug("testPriority: %d; minPriority: %d", testPriority, minPriority);
if ((!foundControl || foundPriority < testPriority) &&
testPriority >= minPriority) {
debug("overlapped() %08X; pauseCtr: %d; flags: %04X",
testControl->_objectId, testControl->_pauseCtr, testControl->_flags);
//debug("overlapped() %08X; pauseCtr: %d; flags: %04X", testControl->_objectId, testControl->_pauseCtr, testControl->_flags);
foundControl = testControl;
foundPriority = testPriority;
}
@ -877,8 +876,6 @@ bool Controls::getOverlappedObject(Control *control, Common::Point pt, Control *
}
}
debug("OVERLAPPED DONE\n");
if (foundControl) {
if (foundControl->_actor && foundControl->_actor->_parentObjectId && (foundControl->_actor->_flags & 0x40)) {
uint32 parentObjectId = foundControl->getSubActorParent();

View File

@ -72,7 +72,7 @@ void BbdouCursor::init(uint32 objectId, uint32 progResKeywordId) {
_data._item10._objectIds[1] = 0;
_data._item10._index = 0;
_data._item10._flag56 = 0;
clearCursorDataField14();
control->setActorIndexTo1();
@ -111,8 +111,32 @@ uint32 BbdouCursor::findCursorSequenceId(uint32 objectId) {
return 0;
}
void BbdouCursor::setStruct8bsValue(uint32 objectId, int value) {
// TODO Clean this up, preliminary
Struct8b *struct8b = 0;
for (uint i = 0; i < 512; ++i)
if (_cursorStruct8bs[i]._objectId == objectId) {
struct8b = &_cursorStruct8bs[i];
break;
}
if (!struct8b) {
for (uint i = 0; i < 512; ++i)
if (_cursorStruct8bs[i]._objectId == 0) {
struct8b = &_cursorStruct8bs[i];
break;
}
}
if (value != 11) {
struct8b->_objectId = objectId;
struct8b->_value = value;
} else if (struct8b->_objectId == objectId) {
struct8b->_objectId = 0;
struct8b->_value = 0;
}
}
int BbdouCursor::findStruct8bsValue(uint32 objectId) {
for (uint i = 0; i < kMaxCursorSequences; ++i)
for (uint i = 0; i < 512; ++i)
if (_cursorStruct8bs[i]._objectId == objectId)
return _cursorStruct8bs[i]._value;
return 11;

View File

@ -92,6 +92,7 @@ public:
void disable(uint32 objectId);
void addCursorSequence(uint32 objectId, uint32 sequenceId);
uint32 findCursorSequenceId(uint32 objectId);
void setStruct8bsValue(uint32 objectId, int value);
int findStruct8bsValue(uint32 objectId);
void saveInfo();
void restoreInfo();

View File

@ -33,6 +33,24 @@
namespace Illusions {
CauseThread::CauseThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThreadId,
BbdouSpecialCode *bbdou, uint32 cursorObjectId, uint32 sceneId, uint32 verbId,
uint32 objectId2, uint32 objectId)
: Thread(vm, threadId, callingThreadId, 0), _bbdou(bbdou), _cursorObjectId(cursorObjectId),
_sceneId(sceneId), _verbId(verbId), _objectId2(objectId2), _objectId(objectId) {
_type = kTTSpecialThread;
}
void CauseThread::onNotify() {
_bbdou->_cursor->_data._causeThreadId1 = 0;
terminate();
}
void CauseThread::onTerminated() {
_bbdou->_cursor->_data._causeThreadId1 = 0;
_bbdou->_cursor->enable(_cursorObjectId);
}
// BbdouSpecialCode
BbdouSpecialCode::BbdouSpecialCode(IllusionsEngine *vm)
@ -125,7 +143,7 @@ void BbdouSpecialCode::spcSetObjectInteractMode(OpCall &opCall) {
ARG_SKIP(4);
ARG_UINT32(objectId);
ARG_INT16(value);
// TODO Cursor_updateStruct8bs(objectId, v3);
_cursor->setStruct8bsValue(objectId, value);
_vm->notifyThreadId(opCall._callerThreadId);
}
@ -176,19 +194,26 @@ Common::Point BbdouSpecialCode::getBackgroundCursorPos(Common::Point cursorPos)
return pt;
}
bool BbdouSpecialCode::runCause(Control *control, CursorData &cursorData,
uint32 verbId, uint32 objectId1, uint32 objectId2, int soundIndex) {
// TODO
return false;
}
void BbdouSpecialCode::showBubble(uint32 objectId, uint32 overlappedObjectId, uint32 holdingObjectId,
Item10 *item10, uint32 progResKeywordId) {
// TODO
}
bool BbdouSpecialCode::findVerbId(Item10 *item10, uint32 currOverlappedObjectId, int always0, uint32 &outVerbId) {
// TODO
if (item10->_playSound48) {
int verbNum = item10->_verbId & 0xFFFF;
int verbNumI = verbNum + 1;
while (1) {
if (verbNumI >= 32)
verbNumI = 0;
if (verbNumI++ == verbNum)
break;
if (item10->_verbActive[verbNumI] && testVerbId(verbNumI | 0x1B0000, always0, currOverlappedObjectId)) {
outVerbId = verbNumI | 0x1B0000;
return true;
}
}
}
return false;
}
@ -221,21 +246,22 @@ void BbdouSpecialCode::cursorInteractControlRoutine(Control *cursorControl, uint
if (cursorData._flags & 1) {
foundOverlapped = 0;
} else if (_vm->_scriptMan->_activeScenes.getCurrentScene() == 0x1000D) {
} else if (_vm->getCurrentScene() == 0x1000D) {
/* TODO foundOverlapped = artcntrlGetOverlappedObjectAccurate(cursorControl, cursorPos,
&overlappedControl, cursorData._item10._field58);*/
} else {
foundOverlapped = _vm->_controls->getOverlappedObject(cursorControl, cursorPos,
&overlappedControl, cursorData._item10._field58);
debug("overlappedControl: %p", (void*)overlappedControl);
}
if (foundOverlapped) {
debug("overlappedControl: %p", (void*)overlappedControl);
if (overlappedControl->_objectId != cursorData._currOverlappedObjectId) {
if (cursorData._item10._playSound48)
playSoundEffect(4);
resetItem10(cursorControl->_objectId, &cursorData._item10);
int value = _cursor->findStruct8bsValue(overlappedControl->_objectId);
debug("object value: %d", value);
if (!testValueRange(value)) {
if (cursorData._mode == 3)
_cursor->restoreInfo();
@ -346,4 +372,119 @@ bool BbdouSpecialCode::updateTrackingCursor(Control *cursorControl) {
return false;
}
bool BbdouSpecialCode::testVerbId(uint32 verbId, uint32 holdingObjectId, uint32 overlappedObjectId) {
static const uint32 kVerbIdsEE[] = {0x001B0002, 0x001B0001, 0};
static const uint32 kVerbIdsE9[] = {0x001B0005, 0};
static const uint32 kVerbIdsE8[] = {0x001B0005, 0x001B0001, 0};
static const uint32 kVerbIdsHE[] = {0x001B0003, 0x001B0001, 0};
static const uint32 kVerbIdsH9[] = {0x001B0003, 0};
static const uint32 kVerbIdsH8[] = {0x001B0003, 0x001B0001, 0};
const uint32 *verbIds;
int value = _cursor->findStruct8bsValue(overlappedObjectId);
if (holdingObjectId) {
if (value == 9)
verbIds = kVerbIdsH9;
else if (value == 9)
verbIds = kVerbIdsH8;
else
verbIds = kVerbIdsHE;
} else {
if (value == 9)
verbIds = kVerbIdsE9;
else if (value == 8)
verbIds = kVerbIdsE8;
else
verbIds = kVerbIdsEE;
}
for (; *verbIds; ++verbIds)
if (*verbIds == verbId)
return true;
return false;
}
bool BbdouSpecialCode::getCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId,
uint32 &outVerbId, uint32 &outObjectId2, uint32 &outObjectId) {
bool success = false;
objectId2 = verbId != 0x1B0003 ? 0 : objectId2;
if (_vm->causeIsDeclared(sceneId, verbId, objectId2, objectId)) {
outVerbId = verbId;
outObjectId2 = objectId2;
outObjectId = objectId;
success = true;
} else if (objectId2 != 0 && _vm->causeIsDeclared(sceneId, 0x1B0008, 0, objectId)) {
outVerbId = 0x1B0008;
outObjectId2 = 0;
outObjectId = objectId;
success = true;
} else if (_vm->causeIsDeclared(sceneId, verbId, objectId2, 0x40001)) {
outVerbId = verbId;
outObjectId2 = objectId2;
outObjectId = 0x40001;
success = true;
} else if (objectId2 != 0 && _vm->causeIsDeclared(sceneId, 0x1B0008, 0, 0x40001)) {
outVerbId = 0x1B0008;
outObjectId2 = 0;
outObjectId = 0x40001;
success = true;
}
if (success) {
debug("getCause() -> %08X %08X %08X", outVerbId, outObjectId2, outObjectId);
}
return success;
}
bool BbdouSpecialCode::runCause(Control *cursorControl, CursorData &cursorData,
uint32 verbId, uint32 objectId2, uint32 objectId, int soundIndex) {
debug("runCause(%08X, %08X, %08X)", verbId, objectId2, objectId);
uint32 sceneId = _vm->getCurrentScene();
uint32 outVerbId, outObjectId2, outObjectId;
bool success = false;
if (getCause(_vm->getCurrentScene(), verbId, objectId2, objectId, outVerbId, outObjectId2, outObjectId)) {
sceneId = _vm->getCurrentScene();
success = true;
} else if (getCause(0x10003, verbId, objectId2, objectId, outVerbId, outObjectId2, outObjectId)) {
sceneId = 0x10003;
success = true;
}
debug("runCause() success: %d", success);
if (!success)
return false;
_cursor->hide(cursorControl->_objectId);
uint32 threadId = startCauseThread(cursorControl->_objectId, _vm->getCurrentScene(), outVerbId, outObjectId2, outObjectId);
if (cursorData._field90) {
_vm->_scriptMan->_threads->killThread(cursorData._causeThreadId2);
cursorData._field90 = 0;
}
if (soundIndex)
playSoundEffect(soundIndex);
cursorData._causeThreadId1 = _vm->causeTrigger(sceneId, outVerbId, outObjectId2, outObjectId, threadId);
cursorData._causeThreadId2 = cursorData._causeThreadId1;
return true;
}
uint32 BbdouSpecialCode::startCauseThread(uint32 cursorObjectId, uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) {
uint32 tempThreadId = _vm->_scriptMan->newTempThreadId();
debug("staring cause thread %08X...", tempThreadId);
CauseThread *causeThread = new CauseThread(_vm, tempThreadId, 0, this,
cursorObjectId, sceneId, verbId, objectId2, objectId);
_vm->_scriptMan->_threads->startThread(causeThread);
causeThread->suspend();
return tempThreadId;
}
} // End of namespace Illusions

View File

@ -24,6 +24,7 @@
#define ILLUSIONS_BBDOU_BBDOU_SPECIALCODE_H
#include "illusions/specialcode.h"
#include "illusions/thread.h"
#include "common/hashmap.h"
namespace Illusions {
@ -36,6 +37,24 @@ struct Item10;
typedef Common::Functor1<OpCall&, void> SpecialCodeFunction;
class BbdouSpecialCode;
class CauseThread : public Thread {
public:
CauseThread(IllusionsEngine *vm, uint32 threadId, uint32 callingThreadId,
BbdouSpecialCode *bbdou, uint32 cursorObjectId, uint32 sceneId,
uint32 verbId, uint32 objectId2, uint32 objectId);
virtual void onNotify();
virtual void onTerminated();
public:
BbdouSpecialCode *_bbdou;
uint32 _cursorObjectId;
uint32 _sceneId;
uint32 _verbId;
uint32 _objectId2;
uint32 _objectId;
};
class BbdouSpecialCode : public SpecialCode {
public:
BbdouSpecialCode(IllusionsEngine *vm);
@ -63,14 +82,18 @@ protected:
bool testValueRange(int value);
void setCursorControlRoutine(uint32 objectId, int num);
Common::Point getBackgroundCursorPos(Common::Point cursorPos);
bool runCause(Control *control, CursorData &cursorData,
uint32 verbId, uint32 objectId1, uint32 objectId2, int soundIndex);
void showBubble(uint32 objectId, uint32 overlappedObjectId, uint32 holdingObjectId,
Item10 *item10, uint32 progResKeywordId);
bool findVerbId(Item10 *item10, uint32 currOverlappedObjectId, int always0, uint32 &outVerbId);
void cursorInteractControlRoutine(Control *cursorControl, uint32 deltaTime);
void cursorControlRoutine2(Control *cursorControl, uint32 deltaTime);
bool updateTrackingCursor(Control *cursorControl);
bool testVerbId(uint32 verbId, uint32 holdingObjectId, uint32 overlappedObjectId);
bool getCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId,
uint32 &outVerbId, uint32 &outObjectId2, uint32 &outObjectId);
bool runCause(Control *cursorControl, CursorData &cursorData,
uint32 verbId, uint32 objectId2, uint32 objectId, int soundIndex);
uint32 startCauseThread(uint32 cursorObjectId, uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId);
};
} // End of namespace Illusions

View File

@ -169,6 +169,7 @@ Common::Error IllusionsEngine::run() {
#endif
_scriptMan->startScriptThread(0x00020004, 0, 0, 0, 0);
_scriptMan->_doScriptThreadInit = true;
//_camera->panToPoint(Common::Point(800, 0), 500, 0);
@ -347,6 +348,26 @@ int IllusionsEngine::getRandom(int max) {
return _random->getRandomNumber(max - 1);
}
bool IllusionsEngine::causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) {
uint32 codeOffs;
// TODO Also search for native trigger functions later (findCauseFunc)
bool r = _scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs);
debug("causeIsDeclared() sceneId: %08X; verbId: %08X; objectId2: %08X; objectId: %08X -> %d",
sceneId, verbId, objectId2, objectId, r);
return r;
}
uint32 IllusionsEngine::causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId) {
uint32 codeOffs;
uint32 causeThreadId = 0;
// TODO Also search for native trigger functions later and run it (findCauseFunc)
if (_scriptMan->findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs)) {
causeThreadId = _scriptMan->startTempScriptThread(_scriptMan->_scriptResource->getCode(codeOffs),
callingThreadId, verbId, objectId2, objectId);
}
return causeThreadId;
}
int IllusionsEngine::convertPanXCoord(int16 x) {
// TODO
return 0;
@ -389,4 +410,8 @@ bool IllusionsEngine::isVoicePlaying() {
return false;
}
uint32 IllusionsEngine::getCurrentScene() {
return _scriptMan->_activeScenes.getCurrentScene();
}
} // End of namespace Illusions

View File

@ -112,6 +112,11 @@ public:
int updateSequences();
int updateGraphics();
int getRandom(int max);
// TODO Move to ScriptMan?
bool causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId);
uint32 causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId);
int convertPanXCoord(int16 x);
Common::Point getNamedPointPosition(uint32 namedPointId);
void playVideo(uint32 videoId, uint32 objectId, uint32 value, uint32 threadId);
@ -121,7 +126,9 @@ public:
bool isVoiceCued();
void startVoice(int volume, int panX);
void stopVoice();
bool isVoicePlaying();
bool isVoicePlaying();
uint32 getCurrentScene();
#if 0

View File

@ -198,6 +198,13 @@ uint32 ScriptMan::startTalkThread(int16 duration, uint32 objectId, uint32 talkId
return tempThreadId;
}
bool ScriptMan::findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs) {
ProgInfo *progInfo = _scriptResource->getProgInfo(sceneId & 0xFFFF);
if (progInfo)
return progInfo->findTriggerCause(verbId, objectId2, objectId, codeOffs);
return false;
}
void ScriptMan::setCurrFontId(uint32 fontId) {
_fontId = fontId;
}

View File

@ -83,6 +83,7 @@ public:
uint32 startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId);
uint32 startTalkThread(int16 duration, uint32 objectId, uint32 talkId, uint32 sequenceId1,
uint32 sequenceId2, uint32 namedPointId, uint32 callingThreadId);
bool findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs);
void setCurrFontId(uint32 fontId);
bool checkActiveTalkThreads();
uint32 clipTextDuration(uint32 duration);

View File

@ -144,6 +144,15 @@ void TriggerObject::load(byte *dataStart, Common::SeekableReadStream &stream) {
_causes[i].load(stream);
}
bool TriggerObject::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs) {
for (uint i = 0; i < _causesCount; ++i)
if (_causes[i]._verbId == verbId && _causes[i]._objectId2 == objectId2) {
codeOffs = _causes[i]._codeOffs;
return true;
}
return false;
}
// ProgInfo
ProgInfo::ProgInfo()
@ -186,6 +195,20 @@ void ProgInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
}
}
bool ProgInfo::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs) {
TriggerObject *triggerObject = findTriggerObject(objectId);
if (triggerObject)
return triggerObject->findTriggerCause(verbId, objectId2, codeOffs);
return false;
}
TriggerObject *ProgInfo::findTriggerObject(uint32 objectId) {
for (uint i = 0; i < _triggerObjectsCount; ++i)
if (_triggerObjects[i]._objectId == objectId)
return &_triggerObjects[i];
return 0;
}
// ScriptResource
ScriptResource::ScriptResource()
@ -241,6 +264,10 @@ byte *ScriptResource::getThreadCode(uint32 threadId) {
return _data + _codeOffsets[(threadId & 0xFFFF) - 1];
}
byte *ScriptResource::getCode(uint32 codeOffs) {
return _data + codeOffs;
}
ProgInfo *ScriptResource::getProgInfo(uint32 index) {
if (index > 0 && index <= _progInfosCount)
return &_progInfos[index - 1];

View File

@ -78,6 +78,7 @@ public:
TriggerObject();
~TriggerObject();
void load(byte *dataStart, Common::SeekableReadStream &stream);
bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs);
public:
uint32 _objectId;
uint _causesCount;
@ -89,12 +90,14 @@ public:
ProgInfo();
~ProgInfo();
void load(byte *dataStart, Common::SeekableReadStream &stream);
bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs);
protected:
uint16 _id;
uint16 _unk;
byte *_name;
uint _triggerObjectsCount;
TriggerObject *_triggerObjects;
TriggerObject *findTriggerObject(uint32 objectId);
};
class ScriptResource {
@ -103,6 +106,7 @@ public:
~ScriptResource();
void load(byte *data, uint32 dataSize);
byte *getThreadCode(uint32 threadId);
byte *getCode(uint32 codeOffs);
ProgInfo *getProgInfo(uint32 index);
public:
byte *_data;