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