2021-12-26 18:48:43 +01:00

760 lines
20 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "titanic/npcs/parrot.h"
#include "titanic/core/project_item.h"
#include "titanic/carry/carry.h"
#include "titanic/carry/chicken.h"
#include "titanic/game_manager.h"
#include "titanic/translation.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CParrot, CTrueTalkNPC)
ON_MESSAGE(ActMsg)
ON_MESSAGE(MouseButtonDownMsg)
ON_MESSAGE(MovieEndMsg)
ON_MESSAGE(EnterViewMsg)
ON_MESSAGE(TrueTalkTriggerActionMsg)
ON_MESSAGE(MouseDragStartMsg)
ON_MESSAGE(LeaveViewMsg)
ON_MESSAGE(ParrotSpeakMsg)
ON_MESSAGE(NPCPlayTalkingAnimationMsg)
ON_MESSAGE(NPCPlayIdleAnimationMsg)
ON_MESSAGE(FrameMsg)
ON_MESSAGE(MovieFrameMsg)
ON_MESSAGE(PutParrotBackMsg)
ON_MESSAGE(PreEnterViewMsg)
ON_MESSAGE(PanningAwayFromParrotMsg)
ON_MESSAGE(LeaveRoomMsg)
ON_MESSAGE(TrueTalkNotifySpeechStartedMsg)
ON_MESSAGE(TrueTalkNotifySpeechEndedMsg)
END_MESSAGE_MAP()
bool CParrot::_eatingChicken;
bool CParrot::_takeOff;
bool CParrot::_unused;
ParrotState CParrot::_state;
bool CParrot::_coreReplaced;
CParrot::CParrot() : CTrueTalkNPC() {
_unused1 = 0;
_carryParrot = "CarryParrot";
_canDrag = true;
_unused2 = 25;
_lastSpeakTime = 0;
_newXp = 73;
_newXc = 58;
_triedEatChicken = false;
_eatOffsetX = 0;
_panTarget = nullptr;
_assetName = "z454.dlg";
_assetNumber = 0x13880;
}
void CParrot::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_assetNumber, indent);
file->writeQuotedLine(_assetName, indent);
file->writeNumberLine(_unused1, indent);
file->writeNumberLine(_eatingChicken, indent);
file->writeNumberLine(_takeOff, indent);
file->writeNumberLine(_unused, indent);
file->writeQuotedLine(_carryParrot, indent);
file->writeNumberLine(_canDrag, indent);
file->writeNumberLine(_unused2, indent);
file->writeNumberLine(_lastSpeakTime, indent);
file->writeNumberLine(_newXp, indent);
file->writeNumberLine(_newXc, indent);
file->writeNumberLine(_triedEatChicken, indent);
file->writeNumberLine(_eatOffsetX, indent);
file->writeNumberLine(_state, indent);
file->writeNumberLine(_coreReplaced, indent);
CTrueTalkNPC::save(file, indent);
}
void CParrot::load(SimpleFile *file) {
file->readNumber();
_assetNumber = file->readNumber();
_assetName = file->readString();
_unused1 = file->readNumber();
_eatingChicken = file->readNumber();
_takeOff = file->readNumber();
_unused = file->readNumber();
_carryParrot = file->readString();
_canDrag = file->readNumber();
_unused2 = file->readNumber();
_lastSpeakTime = file->readNumber();
_newXp = file->readNumber();
_newXc = file->readNumber();
_triedEatChicken = file->readNumber();
_eatOffsetX = file->readNumber();
_state = (ParrotState)file->readNumber();
_coreReplaced = file->readNumber();
CTrueTalkNPC::load(file);
}
bool CParrot::ActMsg(CActMsg *msg) {
if (msg->_action == "Chicken") {
// Nothing to do
} else if (msg->_action == "CarryParrotLeftView") {
if (!_takeOff)
setEatingChicken(false);
} else if (msg->_action == "StartChickenDrag") {
if (_state == PARROT_IN_CAGE) {
stopMovie();
startTalking(this, 280275, findView());
_triedEatChicken = false;
}
} else if (msg->_action == "EnteringFromTOW" &&
(_state == PARROT_IN_CAGE || _state == PARROT_ESCAPED)) {
if (_takeOff) {
_state = PARROT_ESCAPED;
} else {
setVisible(true);
CTreeItem *cageBar = getRoot()->findByName("CageBar");
detach();
attach(cageBar);
_state = PARROT_IN_CAGE;
CActMsg actMsg1("OpenNow");
actMsg1.execute("ParrotCage");
CActMsg actMsg2("GainParrot");
actMsg2.execute("ParrotLobbyController");
}
}
return true;
}
bool CParrot::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
if (!(_npcFlags & NPCFLAG_TAKE_OFF) && _speechCounter == 0) {
CTrueTalkTriggerActionMsg triggerMsg(280250, 280250, 1);
triggerMsg.execute(this);
}
return true;
}
bool CParrot::MovieEndMsg(CMovieEndMsg *msg) {
if ((_npcFlags & NPCFLAG_TAKE_OFF) && clipExistsByEnd("Take Off", msg->_endFrame)) {
setVisible(false);
moveUnder(findRoom());
stopMovie();
CActMsg actMsg1("LoseParrot");
actMsg1.execute("ParrotLobbyController");
if (_panTarget) {
CActMsg actMsg2("PanAwayFromParrot");
actMsg2.execute(_panTarget);
_panTarget = nullptr;
} else {
CActMsg actMsg2("Shut");
actMsg2.execute("ParrotCage");
}
_npcFlags &= ~NPCFLAG_TAKE_OFF;
_state = PARROT_ESCAPED;
} else if (_npcFlags & NPCFLAG_MOVING) {
if (_npcFlags & NPCFLAG_MOVE_START) {
// Parrot is about to loop
_npcFlags = (_npcFlags & ~NPCFLAG_MOVE_START) | NPCFLAG_MOVE_LOOP;
if (_npcFlags & NPCFLAG_MOVE_LEFT) {
playClip("Walk Left Loop", MOVIE_NOTIFY_OBJECT);
movieEvent(236);
} else {
playClip("Walk Right Loop", MOVIE_NOTIFY_OBJECT);
}
} else if (_npcFlags & NPCFLAG_MOVE_LOOP) {
// In progress movement loop
int xp = _bounds.left + _bounds.width() / 2;
if (_npcFlags & NPCFLAG_MOVE_LEFT) {
if ((xp - _newXc) > 32) {
setPosition(Point(_bounds.left - 40, _bounds.top));
playClip("Walk Left Loop", MOVIE_NOTIFY_OBJECT);
movieEvent(236);
} else {
setPosition(Point(_bounds.left - 10, _bounds.top));
playClip("Walk Left Outro", MOVIE_NOTIFY_OBJECT);
_npcFlags = (_npcFlags & ~NPCFLAG_MOVE_LOOP) | NPCFLAG_MOVE_FINISH;
}
} else {
if ((_newXc - xp) > 32) {
playClip("Walk Right Loop", MOVIE_NOTIFY_OBJECT);
movieEvent(244);
} else {
playClip("Walk Right Outro", MOVIE_NOTIFY_OBJECT);
_npcFlags = (_npcFlags & ~NPCFLAG_MOVE_LOOP) | NPCFLAG_MOVE_FINISH;
}
}
} else if (_npcFlags & NPCFLAG_MOVE_FINISH) {
// Finishing movement
loadFrame(0);
if (_npcFlags & NPCFLAG_MOVE_LEFT)
setPosition(Point(_bounds.left - 30, _bounds.top));
else
setPosition(Point(_bounds.left + 14, _bounds.top));
_npcFlags &= ~(NPCFLAG_MOVING | NPCFLAG_MOVE_FINISH | NPCFLAG_MOVE_LEFT | NPCFLAG_MOVE_RIGHT);
CTrueTalkNPC::MovieEndMsg(msg);
}
} else if (_npcFlags & NPCFLAG_CHICKEN_OUTSIDE_CAGE) {
Point pt = getMousePos();
if (pt.x > 70 || pt.y < 90 || pt.y > 280) {
stopMovie();
loadFrame(0);
_npcFlags &= ~NPCFLAG_CHICKEN_OUTSIDE_CAGE;
}
if (clipExistsByEnd("Walk Left Loop", msg->_endFrame)) {
playClip("Lean Over To Chicken", MOVIE_NOTIFY_OBJECT);
setPosition(Point(_bounds.left - 55, _bounds.top));
_eatOffsetX = (-100 - _bounds.left) / 5;
movieEvent(261);
movieEvent(262);
movieEvent(265);
movieEvent(268);
movieEvent(271);
return true;
} else if (clipExistsByEnd("Lean Over To Chicken", msg->_endFrame)) {
// WORKAROUND: Do what the original obviously intended but got
// wrong.. only flag chicken as eaten if it's still being dragged
CTreeItem *dragItem = getGameManager()->_dragItem;
CCarry *chicken = dynamic_cast<CCarry *>(dragItem);
if (chicken)
playClip("Eat Chicken");
playClip("Eat Chicken 2", MOVIE_NOTIFY_OBJECT);
if (chicken) {
setEatingChicken(true);
CTrueTalkTriggerActionMsg actionMsg;
actionMsg._action = 280266;
actionMsg._param2 = 1;
actionMsg.execute(this);
CActMsg actMsg("Eaten");
actMsg.execute(chicken);
}
_npcFlags &= ~NPCFLAG_CHICKEN_OUTSIDE_CAGE;
return true;
}
}
if (clipExistsByEnd("Eat Chicken 2", msg->_endFrame)) {
// Parrot has finished eating Chicken
setEatingChicken(false);
if (_takeOff) {
// Perch has been taken, so take off
loadMovie(TRANSLATE("z168.avi", "z191.avi"), false);
playClip("Take Off", MOVIE_NOTIFY_OBJECT);
setPosition(Point(20, 10));
_npcFlags |= NPCFLAG_TAKE_OFF;
} else {
// Resetting back to standing
_npcFlags &= ~(NPCFLAG_MOVING | NPCFLAG_MOVE_START | NPCFLAG_MOVE_LOOP
| NPCFLAG_MOVE_FINISH | NPCFLAG_MOVE_LEFT | NPCFLAG_MOVE_RIGHT);
_npcFlags |= NPCFLAG_MOVE_END;
stopMovie();
loadFrame(0);
setPosition(Point(-90, _bounds.top));
}
} else {
return CTrueTalkNPC::MovieEndMsg(msg);
}
return true;
}
bool CParrot::EnterViewMsg(CEnterViewMsg *msg) {
static const char *const NAMES[] = {
"Talking0", "Talking1", "Talking2", "Talking3", "Talking4",
"Talking5", "Talking6", "Talking7", nullptr
};
if (_state == PARROT_IN_CAGE) {
setPosition(Point(_newXp, _bounds.top));
_canDrag = true;
_npcFlags &= ~(NPCFLAG_MOVING | NPCFLAG_MOVE_START | NPCFLAG_MOVE_LOOP
| NPCFLAG_MOVE_FINISH | NPCFLAG_MOVE_LEFT | NPCFLAG_MOVE_RIGHT | NPCFLAG_MOVE_END);
loadFrame(0);
setTalking(this, true, findView());
if (_speechCounter > 0) {
playRandomClip(NAMES, MOVIE_NOTIFY_OBJECT);
} else {
startTalking(this, 280258, findView());
}
petSetArea(PET_CONVERSATION);
_triedEatChicken = false;
_npcFlags |= NPCFLAG_START_IDLING;
}
return true;
}
bool CParrot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) {
if (_state != PARROT_MAILED) {
CViewItem *view = msg->_param2 ? findView() : nullptr;
startTalking(this, msg->_action, view);
}
return true;
}
bool CParrot::MouseDragStartMsg(CMouseDragStartMsg *msg) {
if (_canDrag && _state == PARROT_IN_CAGE && checkPoint(msg->_mousePos, false, true)) {
setVisible(false);
CRoomItem *room = findRoom();
moveUnder(room);
startTalking(this, 280129);
performAction(true);
CCarry *item = dynamic_cast<CCarry *>(getRoot()->findByName(_carryParrot));
if (item) {
item->_canTake = true;
CPassOnDragStartMsg passMsg;
passMsg._mousePos = msg->_mousePos;
passMsg.execute(item);
msg->_dragItem = item;
CActMsg actMsg("LoseParrot");
actMsg.execute("ParrotLobbyController");
return true;
}
}
return false;
}
bool CParrot::LeaveViewMsg(CLeaveViewMsg *msg) {
performAction(true);
_npcFlags &= ~NPCFLAG_START_IDLING;
return true;
}
bool CParrot::ParrotSpeakMsg(CParrotSpeakMsg *msg) {
static const char *const ROOM_NAMES[] = {
"SGTState", "SGTLittleLift", "SecClassLittleLift", "SecClassState",
"Lift", "ServiceElevator", "Dome", "Home", "MoonEmbLobby", nullptr
};
if (!stateGetParrotMet() || _state == PARROT_MAILED || compareViewNameTo("Titania.Node 18.N"))
return true;
// Check for rooms not to speak in
for (const char *const *s = &ROOM_NAMES[0]; *s; ++s) {
if (isEquals(*s))
return true;
}
// Don't have the parrot speak too often
if ((getTicksCount() - _lastSpeakTime) < 20000 || _speechCounter)
return true;
playSound(TRANSLATE("z#475.wav", "z#212.wav"), 50);
if (msg->_target == "Bomb") {
startTalking("PerchedParrot", 280236);
} else if (msg->_target == "Announcements") {
startTalking("PerchedParrot", 280263);
} else if (msg->_target == "Television") {
startTalking("PerchedParrot", 280264);
} else if (msg->_target == "Barbot") {
if (msg->_action == "AskForDrink")
startTalking("PerchedParrot", 280262);
} else if (msg->_target == "SuccUBus") {
if (msg->_action == "TurnOn")
startTalking("PerchedParrot", 80161);
else if (msg->_action == "EnterView")
startTalking("PerchedParrot", 80159);
} else if (msg->_target == "Cellpoints") {
if (getRandomNumber(2) == 0) {
switch (getRandomNumber(2)) {
case 0:
startTalking("PerchedParrot", 80193);
break;
case 1:
startTalking("PerchedParrot", 80197);
break;
case 2:
startTalking("PerchedParrot", 80198);
break;
default:
break;
}
} else if (msg->_action == "DoorBot") {
startTalking("PerchedParrot", 80195);
} else if (msg->_action == "DeskBot") {
startTalking("PerchedParrot", 80194);
} else if (msg->_action == "BarBot") {
startTalking("PerchedParrot", 80191);
} else if (msg->_action == "BellBot") {
startTalking("PerchedParrot", 80192);
} else if (msg->_action == "LiftBot") {
startTalking("PerchedParrot", 80196);
}
}
_lastSpeakTime = getTicksCount();
return true;
}
bool CParrot::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) {
static const char *const NAMES[] = {
"Talking0", "Talking1", "Talking2", "Talking3", "Talking4",
"Talking5", "Talking6", "Talking7", nullptr
};
if (!(_npcFlags & (NPCFLAG_MOVING | NPCFLAG_MOVE_START | NPCFLAG_MOVE_LOOP | NPCFLAG_MOVE_FINISH
| NPCFLAG_MOVE_LEFT | NPCFLAG_MOVE_RIGHT | NPCFLAG_MOVE_END))
&& _visible && _state == PARROT_IN_CAGE) {
if (compareViewNameTo("ParrotLobby.Node 1.N"))
msg->_names = NAMES;
}
return true;
}
bool CParrot::NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg) {
static const char *const NAMES[] = {
"Idle0", "Idle1", "Peck At Feet", "Peck At Feet Left",
"Peck At Feet Right", nullptr
};
if (!(_npcFlags & (NPCFLAG_MOVING | NPCFLAG_MOVE_START | NPCFLAG_MOVE_LOOP | NPCFLAG_MOVE_FINISH
| NPCFLAG_MOVE_LEFT | NPCFLAG_MOVE_RIGHT | NPCFLAG_MOVE_END))
&& _visible && _state == PARROT_IN_CAGE && compareViewNameTo("ParrotLobby.Node 1.N")) {
CGameObject *dragItem = getDraggingObject();
if (!dragItem || dragItem->getName() == "Chicken") {
if (!_coreReplaced || getRandomNumber(3) != 0) {
if (getRandomNumber(1)) {
startTalking(this, 280267, findView());
} else {
msg->_names = NAMES;
}
} else {
int id = -1;
switch (getParrotResponse()) {
case 0:
id = 280107;
break;
case 1:
id = 280106;
break;
case 2:
id = 280115;
break;
case 3:
id = 280114;
break;
case 4:
id = 280113;
break;
case 5:
id = 280112;
break;
case 6:
id = 280111;
break;
case 7:
id = 280110;
break;
case 8:
id = 280109;
break;
case 9:
id = 280108;
break;
case 10:
id = 280105;
break;
case 11:
id = 280000;
break;
default:
break;
}
if (id != -1)
startTalking(this, id, findView());
CActMsg actMsg("FlashCore");
actMsg.execute("PerchCoreHolder");
}
}
}
return true;
}
bool CParrot::FrameMsg(CFrameMsg *msg) {
if (!compareViewNameTo("ParrotLobby.Node 1.N"))
return false;
if (_state != PARROT_IN_CAGE)
return true;
Point pt = getMousePos();
CGameObject *dragObject = getDraggingObject();
int xp = _bounds.left + _bounds.width() / 2;
bool chickenFlag = false;
if ((_npcFlags & NPCFLAG_MOVE_END) && !hasActiveMovie()) {
_newXc = _newXp + _bounds.width() / 2;
int xDiff = ABS(xp - _newXc);
if (xDiff < 64) {
if (_panTarget) {
CActMsg actMsg("PanAwayFromParrot");
actMsg.execute(_panTarget);
_panTarget = nullptr;
}
_npcFlags &= ~(NPCFLAG_MOVING | NPCFLAG_MOVE_START | NPCFLAG_MOVE_LOOP
| NPCFLAG_MOVE_FINISH | NPCFLAG_MOVE_LEFT | NPCFLAG_MOVE_RIGHT | NPCFLAG_MOVE_END);
return true;
}
// WORKAROUND: Prevent panning away from stalling if Parrot was moving
_npcFlags &= ~NPCFLAG_MOVING;
} else {
if (dragObject)
chickenFlag = dragObject && dragObject->isEquals("Chicken");
if (_npcFlags & NPCFLAG_CHICKEN_OUTSIDE_CAGE) {
if (!chickenFlag || pt.x > 70 || pt.y < 90 || pt.y > 280) {
// A start of eating the chicken outside the cage has to be
// aborted because the chicken has been moved out of range
stopMovie();
loadFrame(0);
setPosition(Point(-90, _bounds.top));
_npcFlags &= ~NPCFLAG_CHICKEN_OUTSIDE_CAGE;
}
} else {
if (!chickenFlag)
return false;
}
_newXc = CLIP((int)pt.x, 230, 480);
}
if ((_npcFlags & NPCFLAG_MOVING) || hasActiveMovie())
return true;
if (ABS(_newXc - xp) > 64) {
_npcFlags |= NPCFLAG_MOVING | NPCFLAG_MOVE_START;
if (_newXc >= xp) {
// WORKAROUND: Original did not properly reset the eating chicken
// flag when the player turns away from the cage
setEatingChicken(false);
setPosition(Point(_bounds.left + 30, _bounds.top));
_npcFlags |= NPCFLAG_MOVE_RIGHT;
playClip("Walk Right Intro", MOVIE_NOTIFY_OBJECT);
} else {
_npcFlags |= NPCFLAG_MOVE_LEFT;
playClip("Walk Left Intro", MOVIE_NOTIFY_OBJECT);
}
} else if (chickenFlag && pt.y >= 90 && pt.y <= 280 && !_triedEatChicken) {
CParrotTriesChickenMsg triesMsg;
triesMsg.execute(dragObject);
CTrueTalkTriggerActionMsg triggerMsg;
int &action = triggerMsg._action;
switch (triesMsg._condiment) {
case 1:
action = triesMsg._isHot ? 280034 : 280056;
break;
case 2:
action = triesMsg._isHot ? 280033 : 280055;
break;
case 3:
action = triesMsg._isHot ? 280032 : 280054;
break;
default:
action = triesMsg._isHot ? 280266 : 280053;
break;
}
if (action == 280266) {
if (pt.x < 75) {
// Parrot needs to reach outside the cage
_npcFlags |= NPCFLAG_CHICKEN_OUTSIDE_CAGE;
playClip("Walk Left Intro", MOVIE_STOP_PREVIOUS);
playClip("Walk Left Loop", MOVIE_NOTIFY_OBJECT);
movieEvent(236);
chickenFlag = false;
} else if ((pt.x - xp) > 15) {
_npcFlags |= NPCFLAG_PECKING;
playClip("Peck At Feet Right", MOVIE_NOTIFY_OBJECT);
movieEvent(170);
} else if ((xp - pt.x) > 15) {
_npcFlags |= NPCFLAG_PECKING;
playClip("Peck At Feet Left", MOVIE_NOTIFY_OBJECT);
movieEvent(142);
} else {
_npcFlags |= NPCFLAG_PECKING;
playClip("Peck At Feet", MOVIE_NOTIFY_OBJECT);
movieEvent(157);
}
}
if (chickenFlag) {
triggerMsg._param2 = 1;
triggerMsg.execute(this);
_triedEatChicken = true;
}
}
return true;
}
bool CParrot::MovieFrameMsg(CMovieFrameMsg *msg) {
if (_npcFlags & NPCFLAG_PECKING) {
// Whoopsy, the Parrot got your chicken
CCarry *chicken = dynamic_cast<CCarry *>(findUnder(getRoot(), "Chicken"));
if (chicken) {
CActMsg actMsg("Eaten");
actMsg.execute(chicken);
}
_npcFlags &= ~NPCFLAG_PECKING;
}
switch (msg->_frameNumber) {
case 244:
setPosition(Point(_bounds.left + 45, _bounds.top));
break;
case 261:
case 262:
case 265:
case 268:
case 271:
setPosition(Point(_bounds.left + _eatOffsetX, _bounds.top));
break;
default:
break;
}
return true;
}
bool CParrot::PutParrotBackMsg(CPutParrotBackMsg *msg) {
const char *const NAMES[] = {
"Talking0", "Talking1", "Talking2", "Talking3", "Talking4",
"Talking5", "Talking6", "Talking7", nullptr
};
int xp = CLIP(msg->_value, 230, 480);
setVisible(true);
moveToView();
_state = PARROT_IN_CAGE;
setPosition(Point(xp - _bounds.width() / 2, _bounds.top));
playRandomClip(NAMES, MOVIE_NOTIFY_OBJECT);
CActMsg actMsg("GainParrot");
actMsg.execute("ParrotLobbyController");
return true;
}
bool CParrot::PreEnterViewMsg(CPreEnterViewMsg *msg) {
if (_state == PARROT_IN_CAGE) {
loadMovie(TRANSLATE("z167.avi", "z190.avi"), false);
loadFrame(0);
}
return true;
}
bool CParrot::PanningAwayFromParrotMsg(CPanningAwayFromParrotMsg *msg) {
if (_state != PARROT_IN_CAGE) {
CActMsg actMsg("PanAwayFromParrot");
actMsg.execute(msg->_target);
_panTarget = nullptr;
} else if (_takeOff) {
_panTarget = msg->_target;
loadMovie(TRANSLATE("z168.avi", "z191.avi"), false);
stopMovie();
playClip("Take Off", MOVIE_NOTIFY_OBJECT);
_npcFlags |= NPCFLAG_TAKE_OFF;
} else {
_npcFlags |= NPCFLAG_MOVE_END;
_panTarget = msg->_target;
stopMovie();
}
return true;
}
bool CParrot::LeaveRoomMsg(CLeaveRoomMsg *msg) {
if (_state == PARROT_IN_CAGE)
startTalking(this, 280259);
return true;
}
bool CParrot::TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *msg) {
// WORKAROUND: Fix parrot freezing up if you drag the chicken whilst
// he's still returning to the center from a prior chicken drag
if (_npcFlags & (NPCFLAG_MOVE_LEFT | NPCFLAG_MOVE_RIGHT))
_npcFlags &= ~(NPCFLAG_MOVING | NPCFLAG_MOVE_LEFT | NPCFLAG_MOVE_RIGHT);
return CTrueTalkNPC::TrueTalkNotifySpeechStartedMsg(msg);
}
bool CParrot::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg) {
if (msg->_dialogueId == 80022) {
// WORKAROUND: End of parrot speech after having fixed Titania
unlockMouse();
changeView("Titania.Node 18.N", "");
}
return CTrueTalkNPC::TrueTalkNotifySpeechEndedMsg(msg);
}
void CParrot::setEatingChicken(bool eating) {
_eatingChicken = eating;
CStatusChangeMsg statusMsg;
statusMsg._newStatus = eating ? 0 : 1;
statusMsg.execute("PerchCoreHolder");
}
} // End of namespace Titanic