mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 03:40:25 +00:00
380 lines
10 KiB
C++
380 lines
10 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 "trecision/anim.h"
|
|
#include "trecision/dialog.h"
|
|
#include "trecision/logic.h"
|
|
#include "trecision/pathfinding3d.h"
|
|
#include "trecision/scheduler.h"
|
|
#include "trecision/text.h"
|
|
#include "trecision/trecision.h"
|
|
#include "trecision/video.h"
|
|
|
|
namespace Trecision {
|
|
|
|
#define ATF_WAITTEXT 1
|
|
|
|
AnimTypeManager::AnimTypeManager(TrecisionEngine *vm) : _vm(vm) {
|
|
for (int i = 0; i < 3; ++i) {
|
|
_animType[i]._curFrame = 1;
|
|
_animType[i]._lastFrame = 0;
|
|
_animType[i]._object = 0;
|
|
_animType[i]._status = 0;
|
|
_animType[i]._curAnim = nullptr;
|
|
}
|
|
|
|
_oneSpeakDialogCount = 0;
|
|
}
|
|
|
|
AnimTypeManager::~AnimTypeManager() {
|
|
|
|
}
|
|
|
|
void AnimTypeManager::executeAtFrameDoit(ATFHandle *h, int doit, uint16 objectId) {
|
|
SAnim *anim = &_vm->_animMgr->_animTab[_vm->_room[_vm->_curRoom]._bkgAnim];
|
|
|
|
switch (doit) {
|
|
case fCLROBJSTATUS:
|
|
_vm->setObjectVisible(objectId, false);
|
|
break;
|
|
case fSETOBJSTATUS:
|
|
_vm->setObjectVisible(objectId, true);
|
|
break;
|
|
case fONETIME:
|
|
_vm->setObjectAnim(objectId, 0);
|
|
break;
|
|
case fCREPACCIO:
|
|
if (_vm->_room[kRoom2E].hasExtra())
|
|
_vm->_obj[oCRACK2E]._position = 7;
|
|
else
|
|
_vm->_obj[oCRACK2E]._position = 6;
|
|
break;
|
|
case fSERPVIA:
|
|
_vm->_scheduler->doEvent(_vm->_snake52._class, _vm->_snake52._event, _vm->_snake52._priority, _vm->_snake52._u16Param1, _vm->_snake52._u16Param2, _vm->_snake52._u8Param, _vm->_snake52._u32Param);
|
|
break;
|
|
case fPIRANHA:
|
|
_vm->setObjectAnim(oLUCCHETTO53, 0);
|
|
_vm->setObjectAnim(oGRATAC53, 0);
|
|
_vm->setObjectAnim(oGRATAA53, 0);
|
|
_vm->_obj[oLUCCHETTO53]._action = 1240;
|
|
_vm->_obj[oGRATAC53]._action = 1243;
|
|
_vm->_obj[oGRATAA53]._action = 1246;
|
|
_vm->_obj[oLAGO53]._examine = 1237;
|
|
break;
|
|
case fMOREAU:
|
|
_vm->setObjectAnim(oWINDOWB58, 0);
|
|
_vm->_obj[oWINDOWB58]._action = 1358;
|
|
break;
|
|
case fDOOR58:
|
|
_vm->_scheduler->leftClick(468, 180 + TOP);
|
|
break;
|
|
case fHELLEN:
|
|
_vm->_scheduler->leftClick(336, 263 + TOP);
|
|
break;
|
|
case fVALVEON34:
|
|
if (!(_vm->_dialogMgr->isDialogFinished(616)) && // if the fmv is not done
|
|
(_vm->isObjectVisible(oTUBOA34)) && // if there's a cut pipe
|
|
!(_vm->isObjectVisible(oTUBOFT34))) // if there's not tube outside
|
|
_vm->_animMgr->smkToggleTrackAudio(0, 2, true);
|
|
break;
|
|
case fVALVEOFF34:
|
|
_vm->_animMgr->smkToggleTrackAudio(0, 2, false);
|
|
break;
|
|
|
|
case fCHARACTEROFF:
|
|
_vm->_flagShowCharacter = false;
|
|
break;
|
|
case fCHARACTERON:
|
|
_vm->_flagShowCharacter = true;
|
|
break;
|
|
case fCHARACTERFOREGROUND:
|
|
_vm->_pathFind->setForcedActorPos(BOX_FOREGROUND);
|
|
break;
|
|
case fCHARACTERBACKGROUND:
|
|
_vm->_pathFind->setForcedActorPos(BOX_BACKGROUND);
|
|
break;
|
|
case fCHARACTERNORM:
|
|
_vm->_pathFind->setForcedActorPos(BOX_NORMAL);
|
|
break;
|
|
case fSETEXTRA:
|
|
_vm->_obj[objectId].setFlagExtra(true);
|
|
break;
|
|
case fCLREXTRA:
|
|
_vm->_obj[objectId].setFlagExtra(false);
|
|
break;
|
|
|
|
case fANIMOFF1:
|
|
anim->toggleAnimArea(1, false);
|
|
if (_vm->_curRoom == kRoom11 ||
|
|
_vm->_curRoom == kRoom1D ||
|
|
_vm->_curRoom == kRoom14 ||
|
|
_vm->_curRoom == kRoom22 ||
|
|
_vm->_curRoom == kRoom48 ||
|
|
_vm->_curRoom == kRoom4P)
|
|
_vm->_animMgr->smkToggleTrackAudio(0, 1, false);
|
|
break;
|
|
case fANIMOFF2:
|
|
anim->toggleAnimArea(2, false);
|
|
if (_vm->_curRoom == kRoom2E)
|
|
_vm->_animMgr->smkToggleTrackAudio(0, 2, false);
|
|
break;
|
|
case fANIMOFF3:
|
|
anim->toggleAnimArea(3, false);
|
|
break;
|
|
case fANIMOFF4:
|
|
anim->toggleAnimArea(4, false);
|
|
if (_vm->_curRoom == kRoom28)
|
|
_vm->_animMgr->smkToggleTrackAudio(0, 1, false);
|
|
break;
|
|
|
|
case fANIMON1:
|
|
anim->toggleAnimArea(1, true);
|
|
if (_vm->_curRoom == kRoom14 || _vm->_curRoom == kRoom1D || _vm->_curRoom == kRoom22 || _vm->_curRoom == kRoom48 || _vm->_curRoom == kRoom4P) {
|
|
_vm->_animMgr->smkToggleTrackAudio(0, 1, true);
|
|
}
|
|
break;
|
|
case fANIMON2:
|
|
anim->toggleAnimArea(2, true);
|
|
if (_vm->_curRoom == kRoom2E)
|
|
_vm->_animMgr->smkToggleTrackAudio(0, 2, true);
|
|
break;
|
|
case fANIMON3:
|
|
anim->toggleAnimArea(3, true);
|
|
break;
|
|
case fANIMON4:
|
|
anim->toggleAnimArea(4, true);
|
|
break;
|
|
case fENDDEMO:
|
|
_vm->demoOver();
|
|
_vm->quitGame();
|
|
break;
|
|
case fSTOP2TXT:
|
|
h->_status |= ATF_WAITTEXT;
|
|
// Sets a flag that is always cleared when you finish speaking
|
|
// if the flag is cleared the anim no longer plays
|
|
// (to be done in the smacker player)
|
|
// also the counters in next() stops
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AnimTypeManager::processAtFrame(ATFHandle *h, int type, int atf) {
|
|
const uint16 index = h->_curAnim->_atFrame[atf]._index;
|
|
|
|
switch (type) {
|
|
case ATFTEXT:
|
|
_vm->_textMgr->characterSayInAction(index);
|
|
break;
|
|
case ATFTEXTACT:
|
|
_vm->_textMgr->characterSayInAction(_vm->_obj[h->_object]._action);
|
|
break;
|
|
case ATFTEXTEX:
|
|
_vm->_textMgr->characterSayInAction(_vm->_obj[h->_object]._examine);
|
|
break;
|
|
case ATFCLR:
|
|
_vm->setObjectVisible(index, false);
|
|
break;
|
|
case ATFCLRI:
|
|
_vm->removeIcon(index);
|
|
break;
|
|
case ATFCEX:
|
|
_vm->_obj[h->_object]._examine = index;
|
|
break;
|
|
case ATFCACT:
|
|
_vm->_obj[h->_object]._action = index;
|
|
break;
|
|
case ATFSET:
|
|
_vm->setObjectVisible(index, true);
|
|
break;
|
|
case ATFSETI:
|
|
_vm->addIcon(index);
|
|
break;
|
|
case ATFDO:
|
|
executeAtFrameDoit(h, index, h->_object);
|
|
break;
|
|
case ATFROOM:
|
|
_vm->changeRoom(index);
|
|
break;
|
|
case ATFSETPOS:
|
|
_vm->_pathFind->setPosition(index);
|
|
break;
|
|
case ATFDIALOG:
|
|
_vm->_dialogMgr->playDialog(index);
|
|
break;
|
|
case ATFCOBJANIM:
|
|
_vm->_obj[h->_object]._anim = index;
|
|
break;
|
|
case ATFCOBJBOX:
|
|
_vm->_obj[h->_object]._nbox = index;
|
|
break;
|
|
case ATFCOBJPOS:
|
|
_vm->_obj[h->_object]._position = index;
|
|
break;
|
|
case ATFSETFORE:
|
|
_vm->_obj[index]._nbox = BOX_FOREGROUND;
|
|
break;
|
|
case ATFSETBACK:
|
|
_vm->_obj[index]._nbox = BOX_BACKGROUND;
|
|
break;
|
|
case ATFSWITCH:
|
|
_vm->setObjectVisible(index, !_vm->isObjectVisible(index));
|
|
break;
|
|
case ATFSETROOMT:
|
|
_vm->_logicMgr->setupAltRoom(index, true);
|
|
break;
|
|
case ATFSETROOMF:
|
|
_vm->_logicMgr->setupAltRoom(index, false);
|
|
break;
|
|
case ATFREADBOX:
|
|
switch (index) {
|
|
case 1: {
|
|
const Common::String filename = Common::String::format("%s.3d", _vm->_room[_vm->_curRoom]._baseName);
|
|
_vm->read3D(filename);
|
|
_vm->_room[_vm->_curRoom].setExtra(false);
|
|
}
|
|
break;
|
|
case 2: {
|
|
const Common::String filename = Common::String::format("%s2.3d", _vm->_room[_vm->_curRoom]._baseName);
|
|
_vm->read3D(filename);
|
|
_vm->_room[_vm->_curRoom].setExtra(true);
|
|
if (_vm->_curRoom == kRoom37)
|
|
_vm->_animMgr->smkToggleTrackAudio(0, 1, true);
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ATFONESPEAK:
|
|
switch (index) {
|
|
case 1: // Storekeeper's wife
|
|
if (_vm->_room[kRoom1D].hasExtra())
|
|
break;
|
|
|
|
// Quotes spoken by the storekeeper's wife while she is in the cellar
|
|
_vm->_textMgr->someoneSay(307 + _oneSpeakDialogCount, oDONNA1D);
|
|
if (_oneSpeakDialogCount < 6)
|
|
++_oneSpeakDialogCount;
|
|
break;
|
|
|
|
case 2: // Storekeeper
|
|
// Quote when you enter the liquor store: "Ah, it's you again... look round
|
|
// if you want, but don't disturb me, I've got a lot to do"
|
|
_vm->_textMgr->someoneSay(1788, ocNEGOZIANTE1A);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ATFEND:
|
|
_vm->demoOver();
|
|
_vm->quitGame();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AnimTypeManager::init(uint16 an, uint16 obj) {
|
|
SAnim *anim = &_vm->_animMgr->_animTab[an];
|
|
ATFHandle *handle = &_animType[kAnimTypeCharacter];
|
|
|
|
if (anim->_flag & SMKANIM_BKG)
|
|
handle = &_animType[kAnimTypeBackground];
|
|
if (anim->_flag & SMKANIM_ICON)
|
|
handle = &_animType[kAnimTypeIcon];
|
|
|
|
handle->_curAnim = anim;
|
|
handle->_object = obj ? obj : _vm->_curObj;
|
|
handle->_curFrame = 0;
|
|
handle->_lastFrame = -1;
|
|
handle->_status = 0;
|
|
}
|
|
|
|
void AnimTypeManager::next() {
|
|
for (int i = 0; i < 3; ++i) {
|
|
if (!(_animType[i]._status & ATF_WAITTEXT) || !_vm->_flagCharacterSpeak)
|
|
++_animType[i]._curFrame;
|
|
}
|
|
}
|
|
|
|
void AnimTypeManager::end(int type) {
|
|
ATFHandle *h = &_animType[type];
|
|
SAnim *anim = h->_curAnim;
|
|
h->_curFrame = 0;
|
|
|
|
// if this ATFrame has already been handled
|
|
if (h->_curFrame == h->_lastFrame)
|
|
return;
|
|
|
|
h->_lastFrame = h->_curFrame;
|
|
|
|
for (int32 i = 0; i < MAXATFRAME; ++i) {
|
|
// if it's time to run this AtFrame
|
|
if (anim->_atFrame[i]._numFrame == 0 && anim->_atFrame[i]._type) {
|
|
const uint8 area = anim->_atFrame[i]._area;
|
|
if ( area == 0 ||
|
|
(area == 1 && anim->isAnimAreaShown(1)) ||
|
|
(area == 2 && anim->isAnimAreaShown(2)) ||
|
|
(area == 3 && anim->isAnimAreaShown(3)) ||
|
|
(area == 4 && anim->isAnimAreaShown(4)))
|
|
processAtFrame(h, anim->_atFrame[i]._type, i);
|
|
}
|
|
}
|
|
|
|
h->_curAnim = nullptr;
|
|
}
|
|
|
|
void AnimTypeManager::handler(int type) {
|
|
ATFHandle *h = &_animType[type];
|
|
SAnim *anim = h->_curAnim;
|
|
if (anim == nullptr)
|
|
return;
|
|
|
|
if (h->_curFrame == 0)
|
|
++h->_curFrame;
|
|
// if this ATFrame has already been applied
|
|
if (h->_curFrame <= h->_lastFrame)
|
|
return;
|
|
|
|
for (int32 i = 0; i < MAXATFRAME; ++i) {
|
|
// if it's time to run this AtFrame
|
|
if (anim->_atFrame[i]._numFrame > h->_lastFrame &&
|
|
anim->_atFrame[i]._numFrame <= h->_curFrame &&
|
|
anim->_atFrame[i]._numFrame != 0) {
|
|
const uint8 child = anim->_atFrame[i]._area;
|
|
if ( child == 0 ||
|
|
(child == 1 && anim->isAnimAreaShown(1)) ||
|
|
(child == 2 && anim->isAnimAreaShown(2)) ||
|
|
(child == 3 && anim->isAnimAreaShown(3)) ||
|
|
(child == 4 && anim->isAnimAreaShown(4)))
|
|
processAtFrame(h, anim->_atFrame[i]._type, i);
|
|
}
|
|
}
|
|
|
|
// set _lastFrame
|
|
h->_lastFrame = h->_curFrame;
|
|
}
|
|
|
|
} // End of namespace Trecision
|