1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/system.h"
24
25 #include "petka/interfaces/dialog_interface.h"
26 #include "petka/interfaces/main.h"
27 #include "petka/petka.h"
28 #include "petka/objects/object_cursor.h"
29 #include "petka/objects/object_star.h"
30 #include "petka/objects/heroes.h"
31 #include "petka/q_system.h"
32 #include "petka/big_dialogue.h"
33 #include "petka/sound.h"
34 #include "petka/flc.h"
35 #include "petka/q_manager.h"
36
37 namespace Petka {
38
DialogInterface()39 DialogInterface::DialogInterface() {
40 _dialog = g_vm->getBigDialogue();
41 _qsys = g_vm->getQSystem();
42 _state = kIdle;
43 _id = -1;
44 _isUserMsg = false;
45 _afterUserMsg = false;
46 _talker = nullptr;
47 _sender = nullptr;
48 _reaction = nullptr;
49 _firstTime = true;
50 }
51
~DialogInterface()52 DialogInterface::~DialogInterface() {
53 delete _reaction;
54 }
55
start(uint id,QMessageObject * sender)56 void DialogInterface::start(uint id, QMessageObject *sender) {
57 _id = id;
58 _isUserMsg = false;
59 _afterUserMsg = false;
60 _talker = nullptr;
61 _firstTime = true;
62 _state = kIdle;
63 _sender = sender;
64 _soundName.clear();
65 initCursor();
66 next(-2);
67 }
68
initCursor()69 void DialogInterface::initCursor() {
70 QObjectCursor *cursor = _qsys->getCursor();
71
72 _savedCursorId = cursor->_resourceId;
73 _savedCursorActType = cursor->_actionType;
74 _wasCursorAnim = cursor->_animate;
75 _wasCursorShown = cursor->_isShown;
76
77 cursor->show(false);
78 cursor->_animate = true;
79 cursor->_resourceId = 5006;
80 cursor->_actionType = kActionTalk;
81 }
82
restoreCursor()83 void DialogInterface::restoreCursor() {
84 QObjectCursor *cursor = _qsys->getCursor();
85 cursor->_isShown = _wasCursorShown;
86 cursor->_animate = _wasCursorAnim;
87 cursor->_resourceId = _savedCursorId;
88 cursor->_actionType = _savedCursorActType;
89
90 // original bug fix
91 Common::Event ev;
92 ev.type = Common::EVENT_MOUSEMOVE;
93 ev.mouse = g_system->getEventManager()->getMousePos();
94 _qsys->onEvent(ev);
95 }
96
next(int choice)97 void DialogInterface::next(int choice) {
98 if (_id == -1)
99 return;
100
101 if ((choice == -1 && _state == kMenu) || (choice != -1 && _state == kPlaying))
102 return;
103
104 int prevTalkerId = -1;
105 if (choice == -1 && !_afterUserMsg) {
106 _dialog->getSpeechInfo(&prevTalkerId, nullptr, -1);
107 }
108 _afterUserMsg = _isUserMsg;
109
110 _qsys->getCursor()->_isShown = false;
111 if (_isUserMsg)
112 return;
113 if (_firstTime)
114 _firstTime = false;
115 else
116 _dialog->next(choice);
117
118 switch (_dialog->opcode()) {
119 case kOpcodePlay:
120 onPlayOpcode(prevTalkerId);
121 break;
122 case kOpcodeMenu:
123 onMenuOpcode();
124 break;
125 case kOpcodeEnd:
126 onEndOpcode();
127 break;
128 case kOpcodeUserMessage:
129 onUserMsgOpcode();
130 break;
131 default:
132 break;
133 }
134 }
135
sendMsg(uint16 opcode)136 void DialogInterface::sendMsg(uint16 opcode) {
137 if (_talker) {
138 _talker->processMessage(QMessage(_talker->_id, opcode, 0, 0, 0, nullptr, 0));
139 }
140 }
141
onEndOpcode()142 void DialogInterface::onEndOpcode() {
143 g_vm->soundMgr()->removeSound(_soundName);
144 sendMsg(kSaid);
145 _talker = nullptr;
146 _state = kIdle;
147 _id = -1;
148 _qsys->_currInterface->removeTexts();
149 restoreCursor();
150 if (_reaction) {
151 QReaction *reaction = _reaction;
152 _reaction = nullptr;
153 _sender->processReaction(reaction);
154 }
155 _sender = nullptr;
156 }
157
endUserMsg()158 void DialogInterface::endUserMsg() {
159 _isUserMsg = false;
160 initCursor();
161 next(-1);
162 }
163
startUserMsg(uint16 arg)164 void DialogInterface::startUserMsg(uint16 arg) {
165 sendMsg(kSaid);
166 _isUserMsg = true;
167 restoreCursor();
168 _qsys->addMessage(_qsys->getChapay()->_id, kUserMsg, arg);
169 }
170
isActive()171 bool DialogInterface::isActive() {
172 return _state != kIdle;
173 }
174
setSender(QMessageObject * sender)175 void DialogInterface::setSender(QMessageObject *sender) {
176 _sender = sender;
177 }
178
findSound()179 Sound *DialogInterface::findSound() {
180 return g_vm->soundMgr()->findSound(_soundName);
181 }
182
removeSound()183 void DialogInterface::removeSound() {
184 g_vm->soundMgr()->removeSound(_soundName);
185 _soundName.clear();
186 }
187
setReaction(QReaction * reaction)188 void DialogInterface::setReaction(QReaction *reaction) {
189 delete _reaction;
190 _reaction = reaction;
191 }
192
playSound(const Common::String & name)193 void DialogInterface::playSound(const Common::String &name) {
194 removeSound();
195 _soundName = name;
196 Sound *s = g_vm->soundMgr()->addSound(name, Audio::Mixer::kSpeechSoundType);
197 if (s) {
198 FlicDecoder *flc = g_vm->resMgr()->getFlic(_talker->_resourceId);
199 if (flc) {
200 Common::Rect bounds = flc->getBounds();
201 s->setBalance(bounds.left + _talker->_x + bounds.width(), _qsys->_sceneWidth);
202 }
203 s->play(false);
204 }
205 }
206
setPhrase(const Common::U32String * text)207 void DialogInterface::setPhrase(const Common::U32String *text) {
208 uint16 textColor;
209 uint16 outlineColor;
210 if (_talker->_dialogColor == -1) {
211 textColor = g_system->getScreenFormat().RGBToColor(0xA, 0xA, 0xA);
212 outlineColor = 0xFFFF;
213 } else {
214 textColor = _talker->_dialogColor;
215 outlineColor = g_system->getScreenFormat().RGBToColor(0x7F, 0, 0);
216 }
217 _qsys->_currInterface->setTextPhrase(*text, textColor, outlineColor);
218 }
219
onPlayOpcode(int prevTalkerId)220 void DialogInterface::onPlayOpcode(int prevTalkerId) {
221 int currTalkerId;
222 const char *soundName = nullptr;
223 const Common::U32String *text = _dialog->getSpeechInfo(&currTalkerId, &soundName, -1);
224
225 if (prevTalkerId != currTalkerId) {
226 sendMsg(kSaid);
227 }
228
229 _talker = _qsys->findObject(currTalkerId);
230 playSound(g_vm->getSpeechPath() + soundName);
231 setPhrase(text);
232
233 if (prevTalkerId != currTalkerId) {
234 sendMsg(kSay);
235 }
236 _state = kPlaying;
237 }
238
onMenuOpcode()239 void DialogInterface::onMenuOpcode() {
240 removeSound();
241
242 sendMsg(kSaid);
243 _talker = nullptr;
244
245 Common::Array<Common::U32String> choices;
246 _dialog->getMenuChoices(choices);
247 _qsys->_mainInterface->setTextChoice(choices, 0xFFFF, g_system->getScreenFormat().RGBToColor(0xFF, 0, 0));
248
249 _qsys->getCursor()->_isShown = true;
250 _state = kMenu;
251 }
252
onUserMsgOpcode()253 void DialogInterface::onUserMsgOpcode() {
254 _qsys->_currInterface->setTextPhrase(Common::U32String(), 0, 0);
255 removeSound();
256 _talker = nullptr;
257 _state = kPlaying;
258 }
259
fixCursor()260 void DialogInterface::fixCursor() {
261 _isUserMsg = false;
262 _qsys->getCursor()->show(true);
263 _qsys->getStar()->_isActive = true;
264 }
265
266 } // End of namespace Petka
267