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