mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-03 09:23:37 +00:00
565de60234
(cherry picked from commit 66094e4)
363 lines
9.5 KiB
C++
363 lines
9.5 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "illusions/bbdou/illusions_bbdou.h"
|
|
#include "illusions/bbdou/bbdou_cursor.h"
|
|
#include "illusions/bbdou/bbdou_specialcode.h"
|
|
#include "illusions/actor.h"
|
|
#include "illusions/camera.h"
|
|
#include "illusions/dictionary.h"
|
|
#include "illusions/input.h"
|
|
|
|
namespace Illusions {
|
|
|
|
// NOTE It's assumed there's only one game cursor object
|
|
// The original stores the _data inside the actor, here it's inside the Cursor class.
|
|
|
|
// BbdouCursor
|
|
|
|
BbdouCursor::BbdouCursor(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou)
|
|
: _vm(vm), _bbdou(bbdou) {
|
|
}
|
|
|
|
BbdouCursor::~BbdouCursor() {
|
|
}
|
|
|
|
void BbdouCursor::init(uint32 objectId, uint32 progResKeywordId) {
|
|
|
|
Common::Point pos = _vm->_camera->getCurrentPan();
|
|
_vm->_controls->placeActor(0x50001, pos, 0x6000C, objectId, 0);
|
|
|
|
Control *control = _vm->_dict->getObjectControl(objectId);
|
|
control->_flags |= 8;
|
|
|
|
_data._mode = 1;
|
|
_data._mode2 = 0;
|
|
_data._verbId1 = 0x1B0000;
|
|
_data._progResKeywordId = progResKeywordId;
|
|
_data._currOverlappedObjectId = 0;
|
|
_data._overlappedObjectId = 0;
|
|
_data._sequenceId = 0x6000F;
|
|
_data._holdingObjectId = 0;
|
|
_data._holdingObjectId2 = 0;
|
|
_data._visibleCtr = 0;
|
|
_data._causeThreadId1 = 0;
|
|
_data._causeThreadId2 = 0;
|
|
_data._field90 = 0;
|
|
_data._flags = 0;
|
|
_data._verbState._minPriority = 1;
|
|
_data._currCursorTrackingSequenceId = 0;
|
|
_data._idleCtr = 0;
|
|
_data._verbState._verbId = 0x1B0000;
|
|
_data._verbState._cursorState = 1;
|
|
_data._verbState._isBubbleVisible = 0;
|
|
_data._verbState._objectIds[0] = 0;
|
|
_data._verbState._objectIds[1] = 0;
|
|
_data._verbState._index = 0;
|
|
_data._verbState._flag56 = false;
|
|
|
|
resetActiveVerbs();
|
|
|
|
control->setActorIndexTo1();
|
|
|
|
}
|
|
|
|
void BbdouCursor::enable(uint32 objectId) {
|
|
++_data._visibleCtr;
|
|
if (_data._visibleCtr == 1) {
|
|
Control *control = _vm->_dict->getObjectControl(objectId);
|
|
show(control);
|
|
_vm->_camera->pushCameraMode();
|
|
_vm->_camera->panEdgeFollow(objectId, 360);
|
|
_data._idleCtr = 0;
|
|
}
|
|
_vm->_input->discardAllEvents();
|
|
}
|
|
|
|
void BbdouCursor::disable(uint32 objectId) {
|
|
hide(objectId);
|
|
}
|
|
|
|
void BbdouCursor::reset(uint32 objectId) {
|
|
Control *control = _vm->_dict->getObjectControl(objectId);
|
|
_data._verbState._cursorState = 1;
|
|
_data._mode = 1;
|
|
_data._mode2 = 0;
|
|
_data._verbId1 = 0x1B0000;
|
|
_data._currOverlappedObjectId = 0;
|
|
_data._overlappedObjectId = 0;
|
|
_data._sequenceId = 0x6000F;
|
|
_data._holdingObjectId = 0;
|
|
_data._holdingObjectId2 = 0;
|
|
_data._visibleCtr = 0;
|
|
_data._causeThreadId1 = 0;
|
|
_data._flags = 0;
|
|
_data._verbState._minPriority = 1;
|
|
_data._currCursorTrackingSequenceId = 0;
|
|
_data._idleCtr = 0;
|
|
_data._verbState._verbId = 0x1B0000;
|
|
_data._verbState._isBubbleVisible = 0;
|
|
_data._verbState._objectIds[0] = 0;
|
|
_data._verbState._objectIds[1] = 0;
|
|
_data._verbState._index = 0;
|
|
_data._verbState._flag56 = false;
|
|
resetActiveVerbs();
|
|
control->setActorIndexTo1();
|
|
control->startSequenceActor(0x60029, 2, 0);
|
|
_bbdou->hideVerbBubble(control->_objectId, &_data._verbState);
|
|
}
|
|
|
|
void BbdouCursor::addCursorSequenceId(uint32 objectId, uint32 sequenceId) {
|
|
for (uint i = 0; i < kMaxCursorSequences; ++i) {
|
|
if (_cursorSequences[i]._objectId == 0) {
|
|
_cursorSequences[i]._objectId = objectId;
|
|
_cursorSequences[i]._sequenceId = sequenceId;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32 BbdouCursor::findCursorSequenceId(uint32 objectId) {
|
|
for (uint i = 0; i < kMaxCursorSequences; ++i) {
|
|
if (_cursorSequences[i]._objectId == objectId)
|
|
return _cursorSequences[i]._sequenceId;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool BbdouCursor::updateTrackingCursor(Control *control) {
|
|
uint32 sequenceId;
|
|
if (getTrackingCursorSequenceId(control, sequenceId)) {
|
|
if (_data._currCursorTrackingSequenceId != sequenceId) {
|
|
saveBeforeTrackingCursor(control, sequenceId);
|
|
show(control);
|
|
_data._currCursorTrackingSequenceId = sequenceId;
|
|
}
|
|
return true;
|
|
} else {
|
|
if (_data._currCursorTrackingSequenceId) {
|
|
_data._currCursorTrackingSequenceId = 0;
|
|
restoreAfterTrackingCursor();
|
|
show(control);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void BbdouCursor::saveInfo() {
|
|
_data._mode2 = _data._mode;
|
|
_data._sequenceId2 = _data._sequenceId;
|
|
_data._holdingObjectId2 = _data._holdingObjectId;
|
|
}
|
|
|
|
void BbdouCursor::restoreInfo() {
|
|
_data._mode = _data._mode2;
|
|
_data._holdingObjectId = _data._holdingObjectId2;
|
|
_data._sequenceId = _data._sequenceId2;
|
|
_data._mode2 = 0;
|
|
_data._holdingObjectId2 = 0;
|
|
_data._sequenceId2 = 0;
|
|
}
|
|
|
|
void BbdouCursor::saveBeforeTrackingCursor(Control *control, uint32 sequenceId) {
|
|
if (_data._currOverlappedObjectId || _data._mode == 3) {
|
|
if (_data._mode == 3)
|
|
restoreInfo();
|
|
control->setActorIndexTo1();
|
|
if (_data._verbState._isBubbleVisible)
|
|
_bbdou->playSoundEffect(4);
|
|
_bbdou->hideVerbBubble(control->_objectId, &_data._verbState);
|
|
}
|
|
_data._currOverlappedObjectId = 0;
|
|
if (_data._mode != 4) {
|
|
saveInfo();
|
|
_data._mode = 4;
|
|
_data._holdingObjectId = 0;
|
|
}
|
|
_data._sequenceId = sequenceId;
|
|
}
|
|
|
|
void BbdouCursor::restoreAfterTrackingCursor() {
|
|
_data._holdingObjectId = _data._holdingObjectId2;
|
|
if (_data._holdingObjectId2) {
|
|
_data._mode = 2;
|
|
_data._sequenceId = findCursorSequenceId(_data._holdingObjectId2);
|
|
} else {
|
|
_data._mode = 1;
|
|
_data._sequenceId = 0x6000F;
|
|
}
|
|
_data._mode2 = 0;
|
|
_data._sequenceId2 = 0;
|
|
_data._holdingObjectId2 = 0;
|
|
_data._currCursorTrackingSequenceId = 0;
|
|
}
|
|
|
|
uint32 BbdouCursor::getSequenceId1(int sequenceIndex) {
|
|
switch (sequenceIndex) {
|
|
case 2:
|
|
return 0x60010;
|
|
case 3:
|
|
return 0x60011;
|
|
case 4:
|
|
return 0x60012;
|
|
case 5:
|
|
return 0x60013;
|
|
case 6:
|
|
return 0x60015;
|
|
case 7:
|
|
return 0x60014;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
uint BbdouCursor::calcTrackingFlags(Common::Point actorPos, Common::Point trackingLimits) {
|
|
uint trackingFlags = 0;
|
|
int16 x = actorPos.x - 320;
|
|
int16 y = actorPos.y - 240;
|
|
if (x < -trackingLimits.x)
|
|
trackingFlags = 1;
|
|
else if (x > trackingLimits.x)
|
|
trackingFlags = 3;
|
|
else
|
|
trackingFlags = 2;
|
|
if (y < -trackingLimits.y)
|
|
trackingFlags += 0;
|
|
else if (y > trackingLimits.y)
|
|
trackingFlags += 6;
|
|
else
|
|
trackingFlags += 3;
|
|
return trackingFlags;
|
|
}
|
|
|
|
uint BbdouCursor::calcTrackingCursorIndex(uint trackingFlags) {
|
|
uint cursorIndex = 0;
|
|
switch (trackingFlags) {
|
|
case 1:
|
|
if (_vm->_camera->isAtPanLimit(1)) {
|
|
if (!_vm->_camera->isAtPanLimit(3))
|
|
cursorIndex = 4;
|
|
} else {
|
|
if (!_vm->_camera->isAtPanLimit(3))
|
|
cursorIndex = 1;
|
|
else
|
|
cursorIndex = 2;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (!_vm->_camera->isAtPanLimit(1))
|
|
cursorIndex = 2;
|
|
break;
|
|
case 3:
|
|
if (_vm->_camera->isAtPanLimit(1)) {
|
|
if (!_vm->_camera->isAtPanLimit(4))
|
|
cursorIndex = 6;
|
|
} else {
|
|
if (!_vm->_camera->isAtPanLimit(4))
|
|
cursorIndex = 3;
|
|
else
|
|
cursorIndex = 2;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (!_vm->_camera->isAtPanLimit(3))
|
|
cursorIndex = 4;
|
|
break;
|
|
case 6:
|
|
if (!_vm->_camera->isAtPanLimit(4))
|
|
cursorIndex = 6;
|
|
break;
|
|
case 7:
|
|
if (_vm->_camera->isAtPanLimit(2)) {
|
|
if (!_vm->_camera->isAtPanLimit(3))
|
|
cursorIndex = 4;
|
|
} else {
|
|
if (!_vm->_camera->isAtPanLimit(3))
|
|
cursorIndex = 8;
|
|
else
|
|
cursorIndex = 7;
|
|
}
|
|
break;
|
|
case 8:
|
|
if (!_vm->_camera->isAtPanLimit(2))
|
|
cursorIndex = 8;
|
|
break;
|
|
case 9:
|
|
if (_vm->_camera->isAtPanLimit(2)) {
|
|
if (!_vm->_camera->isAtPanLimit(4))
|
|
cursorIndex = 6;
|
|
} else {
|
|
if (!_vm->_camera->isAtPanLimit(4))
|
|
cursorIndex = 9;
|
|
else
|
|
cursorIndex = 8;
|
|
}
|
|
break;
|
|
}
|
|
return cursorIndex;
|
|
}
|
|
|
|
bool BbdouCursor::getTrackingCursorSequenceId(Control *control, uint32 &outSequenceId) {
|
|
static const uint32 kTrackingCursorSequenceIds[] = {
|
|
0, 0x000609BF, 0x00060018, 0x000609C0, 0x00060016,
|
|
0, 0x00060017, 0x000609C1, 0x00060019, 0x000609C2
|
|
};
|
|
Common::Point trackingLimits = _vm->_camera->getTrackingLimits();
|
|
uint trackingFlags = calcTrackingFlags(control->_actor->_position, trackingLimits);
|
|
uint cursorIndex = calcTrackingCursorIndex(trackingFlags);
|
|
outSequenceId = kTrackingCursorSequenceIds[cursorIndex];
|
|
return outSequenceId != 0;
|
|
}
|
|
|
|
void BbdouCursor::resetActiveVerbs() {
|
|
for (uint i = 0; i < 32; ++i) {
|
|
_data._verbState._verbActive[i] = false;
|
|
}
|
|
if (_data._verbState._cursorState == 1) {
|
|
_data._verbState._verbActive[1] = true;
|
|
_data._verbState._verbActive[2] = true;
|
|
_data._verbState._verbActive[3] = true;
|
|
_data._verbState._verbActive[5] = true;
|
|
} else if (_data._verbState._cursorState == 3) {
|
|
_data._verbState._verbActive[1] = true;
|
|
_data._verbState._verbActive[2] = true;
|
|
}
|
|
}
|
|
|
|
void BbdouCursor::show(Control *control) {
|
|
control->startSequenceActor(_data._sequenceId, 2, 0);
|
|
control->appearActor();
|
|
}
|
|
|
|
void BbdouCursor::hide(uint32 objectId) {
|
|
--_data._visibleCtr;
|
|
if (_data._visibleCtr == 0) {
|
|
Control *control = _vm->_dict->getObjectControl(objectId);
|
|
control->startSequenceActor(0x60029, 2, 0);
|
|
_bbdou->hideVerbBubble(objectId, &_data._verbState);
|
|
_vm->_camera->popCameraMode();
|
|
}
|
|
_vm->_input->discardAllEvents();
|
|
}
|
|
|
|
} // End of namespace Illusions
|