Initial commit
This commit is contained in:
759
engines/titanic/npcs/parrot.cpp
Normal file
759
engines/titanic/npcs/parrot.cpp
Normal file
@@ -0,0 +1,759 @@
|
||||
/* 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
|
||||
Reference in New Issue
Block a user