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 "bladerunner/actor_dialogue_queue.h"
24 
25 #include "bladerunner/bladerunner.h"
26 
27 #include "bladerunner/actor.h"
28 #include "bladerunner/audio_speech.h"
29 #include "bladerunner/savefile.h"
30 #include "bladerunner/scene.h"
31 #include "bladerunner/time.h"
32 
33 #include "bladerunner/script/scene_script.h"
34 
35 namespace BladeRunner {
36 
Entry()37 ActorDialogueQueue::Entry::Entry() {
38 	isNotPause = false;
39 	isPause = false;
40 	actorId = -1;
41 	delayMillis = -1;
42 	sentenceId = -1;
43 	animationMode = -1;
44 }
45 
ActorDialogueQueue(BladeRunnerEngine * vm)46 ActorDialogueQueue::ActorDialogueQueue(BladeRunnerEngine *vm) {
47 	_vm = vm;
48 	clear();
49 }
50 
~ActorDialogueQueue()51 ActorDialogueQueue::~ActorDialogueQueue() {
52 }
53 
add(int actorId,int sentenceId,int animationMode)54 void ActorDialogueQueue::add(int actorId, int sentenceId, int animationMode) {
55 	if (actorId == kActorMcCoy || actorId == kActorVoiceOver) {
56 		animationMode = -1;
57 	}
58 	if (_entries.size() < kMaxEntries) {
59 		Entry entry;
60 		entry.isNotPause = true;
61 		entry.isPause = false;
62 		entry.actorId = actorId;
63 		entry.sentenceId = sentenceId;
64 		entry.animationMode = animationMode;
65 		entry.delayMillis = -1;
66 
67 		_entries.push_back(entry);
68 	}
69 }
70 
addPause(int32 delayMillis)71 void ActorDialogueQueue::addPause(int32 delayMillis) {
72 	if (_entries.size() < kMaxEntries) {
73 		Entry entry;
74 		entry.isNotPause = false;
75 		entry.isPause = true;
76 		entry.actorId = -1;
77 		entry.sentenceId = -1;
78 		entry.animationMode = -1;
79 		entry.delayMillis = delayMillis;
80 
81 		_entries.push_back(entry);
82 	}
83 }
84 
flush(int a1,bool callScript)85 void ActorDialogueQueue::flush(int a1, bool callScript) {
86 	if (_isNotPause && _vm->_audioSpeech->isPlaying()) {
87 		_vm->_audioSpeech->stopSpeech();
88 		if (_animationModePrevious >= 0) {
89 			_vm->_actors[_actorId]->changeAnimationMode(_animationModePrevious, false);
90 			_animationModePrevious = -1;
91 		}
92 		_isNotPause = false;
93 		_actorId = -1;
94 		_sentenceId = -1;
95 		_animationMode = -1;
96 	}
97 	if (_isPause) {
98 		_isPause = false;
99 		_delayMillis = 0;
100 		_timeLast = 0u;
101 	}
102 	clear();
103 	if (callScript) {
104 		_vm->_sceneScript->dialogueQueueFlushed(a1);
105 	}
106 }
107 
108 /**
109 * return true when queue is empty and object is flushed
110 */
isEmpty()111 bool ActorDialogueQueue::isEmpty() {
112 	return _entries.empty() \
113 	        && !_isNotPause \
114 	        && !_isPause \
115 	        && _actorId == -1 \
116 	        && _sentenceId == -1 \
117 	        && _animationMode == -1 \
118 	        && _animationModePrevious == -1 \
119 	        && _delayMillis == 0 \
120 	        && _timeLast == 0u;
121 }
122 
tick()123 void ActorDialogueQueue::tick() {
124 	if (!_vm->_audioSpeech->isPlaying()) {
125 		if (_isPause) {
126 			uint32 time = _vm->_time->current();
127 			uint32 timeDiff = time - _timeLast; // unsigned difference is intentional
128 			_timeLast = time;
129 			_delayMillis = (_delayMillis < 0 || ((uint32)_delayMillis < timeDiff) ) ? 0 : ((uint32)_delayMillis - timeDiff);
130 			if (_delayMillis > 0) {
131 				return;
132 			}
133 			_isPause = false;
134 			_delayMillis = 0;
135 			_timeLast = 0u;
136 			if (_entries.empty()) {
137 				flush(0, true);
138 			}
139 		}
140 		if (_isNotPause) {
141 			if (_animationModePrevious >= 0) {
142 				_vm->_actors[_actorId]->changeAnimationMode(_animationModePrevious, false);
143 				_animationModePrevious = -1;
144 			}
145 			_isNotPause = false;
146 			_actorId = -1;
147 			_sentenceId = -1;
148 			_animationMode = -1;
149 			if (_entries.empty()) {
150 				flush(0, true);
151 			}
152 		}
153 		if (!_entries.empty()) {
154 			Entry firstEntry = _entries.remove_at(0);
155 			if (firstEntry.isNotPause) {
156 				_animationMode = firstEntry.animationMode;
157 				if (_vm->_actors[firstEntry.actorId]->getSetId() != _vm->_scene->getSetId()) {
158 					_animationMode = -1;
159 				}
160 				_vm->_actors[firstEntry.actorId]->speechPlay(firstEntry.sentenceId, false);
161 				_isNotPause = true;
162 				_actorId = firstEntry.actorId;
163 				_sentenceId = firstEntry.sentenceId;
164 				if (_animationMode >= 0) {
165 					_animationModePrevious = _vm->_actors[firstEntry.actorId]->getAnimationMode();
166 					_vm->_actors[firstEntry.actorId]->changeAnimationMode(_animationMode, false);
167 				} else {
168 					_animationModePrevious = -1;
169 				}
170 			} else if (firstEntry.isPause) {
171 				_isPause = true;
172 				_delayMillis = firstEntry.delayMillis;
173 				_timeLast = _vm->_time->current();
174 			}
175 		}
176 	}
177 }
178 
save(SaveFileWriteStream & f)179 void ActorDialogueQueue::save(SaveFileWriteStream &f) {
180 	int count = (int)_entries.size();
181 	f.writeInt(count);
182 	for (int i = 0; i < count; ++i) {
183 		Entry &e = _entries[i];
184 		f.writeBool(e.isNotPause);
185 		f.writeBool(e.isPause);
186 		f.writeInt(e.actorId);
187 		f.writeInt(e.sentenceId);
188 		f.writeInt(e.animationMode);
189 		f.writeInt(e.delayMillis);
190 	}
191 	f.padBytes((kMaxEntries - count) * 24);
192 
193 	f.writeBool(_isNotPause);
194 	f.writeInt(_actorId);
195 	f.writeInt(_sentenceId);
196 	f.writeInt(_animationMode);
197 	f.writeInt(_animationModePrevious);
198 	f.writeBool(_isPause);
199 	f.writeInt(_delayMillis);
200 	// f.write(_timeLast);
201 }
202 
load(SaveFileReadStream & f)203 void ActorDialogueQueue::load(SaveFileReadStream &f) {
204 	_entries.clear();
205 	uint count = f.readInt();
206 	assert(count <= kMaxEntries);
207 	_entries.resize(count);
208 	for (uint i = 0; i < count; ++i) {
209 		Entry &e = _entries[i];
210 		e.isNotPause = f.readBool();
211 		e.isPause = f.readBool();
212 		e.actorId = f.readInt();
213 		e.sentenceId = f.readInt();
214 		e.animationMode = f.readInt();
215 		e.delayMillis = f.readInt();
216 	}
217 
218 	f.skip((kMaxEntries - count) * 24);
219 
220 	_isNotPause = f.readBool();
221 	_actorId = f.readInt();
222 	_sentenceId = f.readInt();
223 	_animationMode = f.readInt();
224 	_animationModePrevious = f.readInt();
225 	_isPause = f.readBool();
226 	_delayMillis = f.readInt();
227 	_timeLast = 0u;
228 }
229 
clear()230 void ActorDialogueQueue::clear() {
231 	_entries.clear();
232 	_isNotPause = false;
233 	_actorId = -1;
234 	_sentenceId = -1;
235 	_animationMode = -1;
236 	_animationModePrevious = -1;
237 	_isPause = false;
238 	_delayMillis = 0;
239 	_timeLast = 0u;
240 }
241 
242 } // End of namespace BladeRunner
243