2017-09-20 20:53:12 -04:00

751 lines
19 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 "titanic/npcs/barbot.h"
#include "titanic/support/files_manager.h"
#include "titanic/titanic.h"
#include "titanic/translation.h"
namespace Titanic {
int CBarbot::_timesCalled;
BEGIN_MESSAGE_MAP(CBarbot, CTrueTalkNPC)
ON_MESSAGE(ActMsg)
ON_MESSAGE(EnterViewMsg)
ON_MESSAGE(TurnOn)
ON_MESSAGE(TurnOff)
ON_MESSAGE(LeaveViewMsg)
ON_MESSAGE(MovieEndMsg)
ON_MESSAGE(TrueTalkSelfQueueAnimSetMsg)
ON_MESSAGE(TrueTalkQueueUpAnimSetMsg)
ON_MESSAGE(TrueTalkGetStateValueMsg)
ON_MESSAGE(TrueTalkTriggerActionMsg)
ON_MESSAGE(FrameMsg)
ON_MESSAGE(LoadSuccessMsg)
ON_MESSAGE(MovieFrameMsg)
ON_MESSAGE(EnterRoomMsg)
ON_MESSAGE(TimerMsg)
END_MESSAGE_MAP()
CBarbot::FrameRanges::FrameRanges() : Common::Array<FrameRange>() {
resize(60);
Common::SeekableReadStream *stream = g_vm->_filesManager->getResource("FRAMES/BARBOT");
for (int idx = 0; idx < 60; ++idx) {
(*this)[idx]._startFrame = stream->readUint32LE();
(*this)[idx]._endFrame = stream->readUint32LE();
}
delete stream;
}
/*------------------------------------------------------------------------*/
CBarbot::CBarbot() : CTrueTalkNPC() {
_field108 = 0;
_field10C = 0;
_field110 = 0;
_addedLemon = false;
_addedTV = false;
_addedPuret = false;
_field120 = 0;
_field124 = 0;
_visCenterOnCounter = false;
_addedVodka = false;
_gottenDrunk = false;
_field134 = 0;
_field138 = 0;
_field13C = -1;
_volume = 30;
_frameNum = -1;
_field148 = -1;
_field14C = 0;
_field150 = 0;
_field154 = 0;
_glassContent = GG_DEFAULT;
_drunkFlag = false;
_field160 = 0;
}
void CBarbot::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_field108, indent);
file->writeNumberLine(_field10C, indent);
file->writeNumberLine(_field110, indent);
file->writeNumberLine(_addedLemon, indent);
file->writeNumberLine(_addedTV, indent);
file->writeNumberLine(_addedPuret, indent);
file->writeNumberLine(_field120, indent);
file->writeNumberLine(_field124, indent);
file->writeNumberLine(_visCenterOnCounter, indent);
file->writeNumberLine(_timesCalled, indent);
file->writeNumberLine(_addedVodka, indent);
file->writeNumberLine(_gottenDrunk, indent);
file->writeNumberLine(_field134, indent);
file->writeNumberLine(_field138, indent);
file->writeNumberLine(_field13C, indent);
file->writeNumberLine(_volume, indent);
file->writeNumberLine(_frameNum, indent);
file->writeNumberLine(_field148, indent);
file->writeNumberLine(_field14C, indent);
file->writeNumberLine(_field150, indent);
file->writeNumberLine(_field154, indent);
file->writeNumberLine(_glassContent, indent);
file->writeNumberLine(_drunkFlag, indent);
file->writeNumberLine(_field160, indent);
CTrueTalkNPC::save(file, indent);
}
void CBarbot::load(SimpleFile *file) {
file->readNumber();
_field108 = file->readNumber();
_field10C = file->readNumber();
_field110 = file->readNumber();
_addedLemon = file->readNumber();
_addedTV = file->readNumber();
_addedPuret = file->readNumber();
_field120 = file->readNumber();
_field124 = file->readNumber();
_visCenterOnCounter = file->readNumber();
_timesCalled = file->readNumber();
_addedVodka = file->readNumber();
_gottenDrunk = file->readNumber();
_field134 = file->readNumber();
_field138 = file->readNumber();
_field13C = file->readNumber();
_volume = file->readNumber();
_frameNum = file->readNumber();
_field148 = file->readNumber();
_field14C = file->readNumber();
_field150 = file->readNumber();
_field154 = file->readNumber();
_glassContent = (GlassGiven)file->readNumber();
_drunkFlag = file->readNumber();
_field160 = file->readNumber();
CTrueTalkNPC::load(file);
}
bool CBarbot::ActMsg(CActMsg *msg) {
if (msg->_action == "Vodka") {
if (!_addedVodka) {
playRange(_frames[47], MOVIE_NOTIFY_OBJECT);
playRange(_frames[46], MOVIE_NOTIFY_OBJECT);
playRange(_frames[40]);
playRange(_frames[7]);
playRange(_frames[13]);
playRange(_frames[8]);
playRange(_frames[40]);
playRange(_frames[7]);
playRange(_frames[13]);
playRange(_frames[8]);
playRange(_frames[7]);
playRange(_frames[40]);
playRange(_frames[13]);
playRange(_frames[40]);
playRange(_frames[7]);
playRange(_frames[8]);
playRange(_frames[13]);
playRange(_frames[40], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_frameNum = _frames[40]._endFrame;
}
} else if (msg->_action == "GiveBackVisCentre") {
if (_field134) {
playRange(_frames[27]);
_frameNum = _frames[27]._endFrame;
}
} else if (msg->_action == "Bird") {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 2;
statusMsg.execute("PickUpGlass");
_glassContent = GG_BIRD;
playRange(_frames[32], MOVIE_NOTIFY_OBJECT);
movieEvent();
playRange(_frames[30], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[30]._endFrame;
if (areIngredientsMissing()) {
playRange(_frames[42], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[42]._endFrame;
}
CActMsg actMsg("InTitilator");
actMsg.execute("BeerGlass");
} else if (msg->_action == "None") {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 2;
statusMsg.execute("PickUpGlass");
_glassContent = GG_EMPTY;
playRange(_frames[55], MOVIE_NOTIFY_OBJECT);
movieEvent();
playRange(_frames[54], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[54]._endFrame;
} else if (msg->_action == "Mustard" || msg->_action == "Tomato") {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 2;
statusMsg.execute("PickUpGlass");
_glassContent = GG_CONDIMENT;
playRange(_frames[55], MOVIE_NOTIFY_OBJECT);
movieEvent();
playRange(_frames[54], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[54]._endFrame;
CActMsg actMsg("InTitilator");
actMsg.execute("BeerGlass");
} else if (msg->_action == "Fruit") {
if (!_addedLemon) {
CActMsg visibleMsg;
visibleMsg.execute("LemonOnBar");
startTalking(this, 250576);
_addedLemon = true;
playRange(_frames[36], MOVIE_NOTIFY_OBJECT);
movieEvent();
_frameNum = _frames[36]._endFrame;
if (areIngredientsMissing()) {
playRange(_frames[43], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[43]._endFrame;
}
CRemoveFromGameMsg removeMsg;
removeMsg.execute("Lemon");
}
} else if (msg->_action == "CrushedTV") {
if (!_addedTV) {
CVisibleMsg visibleMsg;
visibleMsg.execute("TVOnBar");
startTalking(this, 250584);
_field160 = 1;
_addedTV = true;
playSound(TRANSLATE("c#5.wav", "c#65.wav"), _volume);
playRange(_frames[35], MOVIE_NOTIFY_OBJECT);
movieEvent();
playRange(_frames[34]);
playRange(_frames[33], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[33]._endFrame;
if (areIngredientsMissing()) {
playRange(_frames[41], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[41]._endFrame;
}
CRemoveFromGameMsg removeMsg;
removeMsg.execute("CrushedTV");
}
} else if (msg->_action == "PlayerTakesGlass") {
playRange(_frames[53]);
_field124 = 0;
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 0;
statusMsg.execute("PickUpGlass");
} else if (msg->_action == "PlayerTakesVisCentre") {
_visCenterOnCounter = false;
loadFrame(0);
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 0;
statusMsg.execute("PickUpVisCentre");
} else if (msg->_action == "BellRing1") {
startTalking(this, 251105);
} else if (msg->_action == "BellRing2") {
startTalking(this, 251107);
} else if (msg->_action == "BellRing3") {
startTalking(this, 250285);
} else if (msg->_action == "GoRingBell") {
startTalking(this, 250285);
} else if (msg->_action == "ClickOnVision") {
startTalking(this, 251858);
}
return true;
}
bool CBarbot::EnterViewMsg(CEnterViewMsg *msg) {
// I think this is a remnant of early debugging code
if (getName() != "Barbot")
playMovie(MOVIE_REPEAT);
return true;
}
bool CBarbot::EnterRoomMsg(CEnterRoomMsg *msg) {
// I think this is a remnant of early debugging code
if (getName() != "Barbot")
addTimer(g_vm->getRandomNumber(20000));
return true;
}
bool CBarbot::TurnOn(CTurnOn *msg) {
if (!_fieldC4) {
_field13C = -1;
setVisible(true);
CGameObject *glass = findInRoom("BeerGlass");
if (!_gottenDrunk) {
CVisibleMsg visibleMsg(false);
visibleMsg.execute("BarShelfVisCentre");
}
if (glass && !_addedPuret) {
playRange(_frames[38], MOVIE_NOTIFY_OBJECT);
playRange(_frames[58], MOVIE_NOTIFY_OBJECT);
playRange(_frames[57], MOVIE_NOTIFY_OBJECT);
playRange(_frames[56], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_frameNum = _frames[56]._endFrame;
} else {
playRange(_frames[38]);
playRange(_frames[23], MOVIE_NOTIFY_OBJECT);
playRange(_frames[21], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[21]._endFrame;
switch (g_vm->getRandomNumber(2)) {
case 0:
playRange(_frames[10], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[10]._endFrame;
break;
case 1:
playRange(_frames[12], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[12]._endFrame;
break;
default:
break;
}
_field124 = 0;
}
_fieldC4 = 1;
++_timesCalled;
petSetArea(PET_CONVERSATION);
setTalking(this, true);
}
return true;
}
bool CBarbot::TurnOff(CTurnOff *msg) {
if (_fieldC4) {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 0;
statusMsg.execute("PickUpGlass");
statusMsg.execute("PickUpVisCentre");
if (_field124) {
playRange(_frames[17], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[17]._endFrame;
_field124 = 0;
}
if (_visCenterOnCounter) {
// Barbot will put away the vision center
playRange(_frames[28], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_frameNum = _frames[28]._endFrame;
_visCenterOnCounter = false;
_field134 = 1;
}
playRange(_frames[29], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
movieEvent(_frames[29]._startFrame);
_frameNum = _frames[29]._endFrame;
_fieldC4 = 0;
}
return true;
}
bool CBarbot::LeaveViewMsg(CLeaveViewMsg *msg) {
CTurnOff offMsg;
offMsg.execute(this);
return true;
}
bool CBarbot::MovieEndMsg(CMovieEndMsg *msg) {
if (msg->_endFrame == _frameNum) {
_frameNum = -1;
_field14C = getTicksCount();
}
if (msg->_endFrame == _field148) {
_field148 = -1;
_field150 = getTicksCount();
}
if (msg->_endFrame == _field13C) {
if (_field124)
playMovie(_frames[53]._startFrame, _frames[53]._startFrame, 0);
else if (_visCenterOnCounter)
playMovie(_frames[27]._endFrame, _frames[27]._endFrame, 0);
_field13C = -1;
return true;
}
if (msg->_endFrame == _frames[58]._endFrame || msg->_endFrame == _frames[21]._endFrame) {
if (!_gottenDrunk) {
CVisibleMsg visibleMsg(true);
visibleMsg.execute("BarShelfVisCentre");
}
}
if (msg->_endFrame == _frames[57]._endFrame) {
startTalking(this, 250575);
playSound(TRANSLATE("c#10.wav", "c#70.wav"), _volume);
return true;
}
if (msg->_endFrame == _frames[55]._endFrame) {
playSound(TRANSLATE("c#10.wav", "c#70.wav"), _volume);
return true;
}
if (msg->_endFrame == _frames[56]._endFrame
|| msg->_endFrame == _frames[54]._endFrame) {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 1;
statusMsg.execute("PickUpGlass");
CMoveToStartPosMsg moveMsg;
moveMsg.execute("BeerGlass");
return true;
}
if (msg->_endFrame == _frames[30]._endFrame) {
_field124 = 0;
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 0;
statusMsg.execute("PickUpGlass");
}
if (msg->_endFrame == _frames[45]._endFrame) {
if (!_gottenDrunk) {
CVisibleMsg visibleMsg(false);
visibleMsg.execute("BarShelfVisCentre");
}
return true;
}
if (msg->_endFrame == _frames[44]._endFrame) {
_visCenterOnCounter = true;
_gottenDrunk = true;
startTalking(this, 250586);
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 1;
statusMsg.execute("PickUpVisCentre");
CPuzzleSolvedMsg solvedMsg;
solvedMsg.execute("VisionCentre");
}
if (msg->_endFrame == _frames[46]._endFrame) {
if (!_gottenDrunk && !areIngredientsMissing())
startTalking(this, 250571);
return true;
}
if (msg->_endFrame == _frames[43]._endFrame
|| msg->_endFrame == _frames[42]._endFrame
|| msg->_endFrame == _frames[41]._endFrame) {
if (_field124)
playMovie(_frames[53]._startFrame, _frames[53]._startFrame, 0);
return true;
}
if (msg->_endFrame == _frames[38]._endFrame || msg->_endFrame == _frames[23]._endFrame) {
playSound(TRANSLATE("c#3.wav", "c#63.wav"), _volume);
} else if (msg->_endFrame == _frames[36]._endFrame) {
playSound(TRANSLATE("c#6.wav", "c#66.wav"), _volume);
} else if (msg->_endFrame == _frames[35]._endFrame) {
playSound(TRANSLATE("c#8.wav", "c#68.wav"), _volume);
} else if (msg->_endFrame == _frames[33]._endFrame) {
playSound(TRANSLATE("c#4.wav", "c#64.wav"), _volume);
} else if (msg->_endFrame == _frames[32]._endFrame) {
startTalking(this, 145);
playSound(TRANSLATE("c#9.wav", "c#69.wav"), _volume);
} else if (msg->_endFrame == _frames[47]._endFrame) {
playSound(TRANSLATE("c#9.wav", "c#69.wav"), _volume);
_addedVodka = true;
_drunkFlag = true;
} else if (msg->_endFrame == _frames[30]._endFrame) {
playSound(TRANSLATE("c#4.wav", "c#64.wav"), 60);
} else if (msg->_endFrame == _frames[29]._endFrame) {
if (!_fieldC4) {
performAction(true, nullptr);
setVisible(false);
CActMsg actMsg("ResetCount");
actMsg.execute("BarBell");
}
} else if (msg->_endFrame == _frames[27]._endFrame) {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 1;
statusMsg.execute("PickUpVisCentre");
_visCenterOnCounter = true;
_field134 = 0;
startTalking(this, 250586);
}
return true;
}
bool CBarbot::TrueTalkSelfQueueAnimSetMsg(CTrueTalkSelfQueueAnimSetMsg *msg) {
return true;
}
bool CBarbot::TrueTalkQueueUpAnimSetMsg(CTrueTalkQueueUpAnimSetMsg *msg) {
return true;
}
bool CBarbot::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) {
switch (msg->_stateNum) {
case 2:
if (!_gottenDrunk) {
if (_drunkFlag) {
msg->_stateVal = _field134 | 1;
return true;
}
}
msg->_stateVal = _field134;
break;
case 3:
msg->_stateVal = 0;
if (_addedLemon)
msg->_stateVal = 1;
if (_addedVodka)
msg->_stateVal |= 2;
if (_addedPuret)
msg->_stateVal |= 4;
if (_addedTV)
msg->_stateVal |= 8;
break;
case 9:
msg->_stateVal = _drunkFlag ? 1 : 0;
break;
default:
break;
}
return true;
}
bool CBarbot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) {
switch (msg->_action) {
case 6:
if (_field134) {
playRange(_frames[27], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[27]._endFrame;
} else if (!_gottenDrunk && _drunkFlag) {
playRange(_frames[45], MOVIE_NOTIFY_OBJECT);
playRange(_frames[44], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_frameNum = _frames[44]._endFrame;
}
break;
case 7: {
// "add vodka"
CActMsg actMsg("Vodka");
actMsg.execute(this);
break;
}
case 30:
// "starling puret"
_addedPuret = true;
break;
default:
break;
}
return true;
}
bool CBarbot::FrameMsg(CFrameMsg *msg) {
if (!_fieldC4 || _frameNum != -1 || _field148 != -1
|| (msg->_ticks - _field14C) <= 5000
|| (msg->_ticks - _field150) <= 1000)
return true;
if (!_drunkFlag) {
if (++_field154 > 2) {
playRange(_frames[0]);
playRange(_frames[1], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[1]._endFrame;
_field154 = 0;
return true;
}
switch (g_vm->getRandomNumber(5)) {
case 0:
playRange(_frames[4], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[4]._endFrame;
break;
case 1:
playRange(_frames[10], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[10]._endFrame;
break;
case 2:
playRange(_frames[7], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[7]._endFrame;
break;
case 3:
playRange(_frames[0]);
playRange(_frames[1], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[1]._endFrame;
break;
case 4:
playRange(_frames[3], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[3]._endFrame;
break;
case 5:
if (!_field160 && !_visCenterOnCounter) {
playRange(_frames[15], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[15]._endFrame;
}
break;
default:
break;
}
} else {
static const int CASES[23] = {
0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7
};
switch (CASES[g_vm->getRandomNumber(22)]) {
case 0:
playRange(_frames[13], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[13]._endFrame;
break;
case 1:
playRange(_frames[4], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[4]._endFrame;
break;
case 2:
playRange(_frames[8], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[8]._endFrame;
break;
case 3:
playRange(_frames[7], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[7]._endFrame;
break;
case 4:
playRange(_frames[10], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[10]._endFrame;
break;
case 5:
playRange(_frames[2], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[2]._endFrame;
break;
case 6:
playRange(_frames[6], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[6]._endFrame;
break;
default:
playRange(_frames[3], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[3]._endFrame;
break;
}
}
return true;
}
bool CBarbot::LoadSuccessMsg(CLoadSuccessMsg *msg) {
_field14C = _field150 = getTicksCount();
_frameNum = -1;
_field148 = -1;
return true;
}
bool CBarbot::MovieFrameMsg(CMovieFrameMsg *msg) {
if (msg->_frameNumber == _frames[29]._startFrame) {
playSound(TRANSLATE("c#2.wav", "c#62.wav"), _volume);
} else if (msg->_frameNumber == _frames[55]._startFrame
|| msg->_frameNumber == _frames[32]._startFrame) {
// Finished giving the Barbot a glass
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 0;
statusMsg.execute("PickUpGlass");
if (_glassContent == GG_EMPTY) {
// I'd rather see that full of Starling Puret
startTalking(this, 250574);
} else if (_glassContent > GG_EMPTY) {
// What's this?
startTalking(this, 250580);
petSetArea(PET_CONVERSATION);
}
_glassContent = GG_DEFAULT;
} else if (msg->_frameNumber == _frames[36]._startFrame) {
CVisibleMsg visibleMsg(false);
visibleMsg.execute("LemonOnBar");
} else if (msg->_frameNumber == _frames[35]._startFrame) {
CVisibleMsg visibleMsg(false);
visibleMsg.execute("TVOnBar");
}
return true;
}
bool CBarbot::TimerMsg(CTimerMsg *msg) {
if (!_fieldC4 && compareRoomNameTo("Bar")) {
CParrotSpeakMsg speakMsg("Barbot", "AskForDrink");
speakMsg.execute("PerchedParrot");
addTimer(10000 + getRandomNumber(20000));
}
return true;
}
void CBarbot::playRange(const FrameRange &range, uint flags) {
playMovie(range._startFrame, range._endFrame, flags);
}
} // End of namespace Titanic