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 "trecision/anim.h"
24 #include "trecision/dialog.h"
25 #include "trecision/logic.h"
26 #include "trecision/pathfinding3d.h"
27 #include "trecision/scheduler.h"
28 #include "trecision/text.h"
29 #include "trecision/trecision.h"
30 #include "trecision/video.h"
31
32 namespace Trecision {
33
34 #define ATF_WAITTEXT 1
35
AnimTypeManager(TrecisionEngine * vm)36 AnimTypeManager::AnimTypeManager(TrecisionEngine *vm) : _vm(vm) {
37 for (int i = 0; i < 3; ++i) {
38 _animType[i]._curFrame = 1;
39 _animType[i]._lastFrame = 0;
40 _animType[i]._object = 0;
41 _animType[i]._status = 0;
42 _animType[i]._curAnim = nullptr;
43 }
44
45 _oneSpeakDialogCount = 0;
46 }
47
~AnimTypeManager()48 AnimTypeManager::~AnimTypeManager() {
49
50 }
51
executeAtFrameDoit(ATFHandle * h,int doit,uint16 objectId)52 void AnimTypeManager::executeAtFrameDoit(ATFHandle *h, int doit, uint16 objectId) {
53 SAnim *anim = &_vm->_animMgr->_animTab[_vm->_room[_vm->_curRoom]._bkgAnim];
54
55 switch (doit) {
56 case fCLROBJSTATUS:
57 _vm->setObjectVisible(objectId, false);
58 break;
59 case fSETOBJSTATUS:
60 _vm->setObjectVisible(objectId, true);
61 break;
62 case fONETIME:
63 _vm->setObjectAnim(objectId, 0);
64 break;
65 case fCREPACCIO:
66 if (_vm->_room[kRoom2E].hasExtra())
67 _vm->_obj[oCRACK2E]._position = 7;
68 else
69 _vm->_obj[oCRACK2E]._position = 6;
70 break;
71 case fSERPVIA:
72 _vm->_scheduler->doEvent(_vm->_snake52._class, _vm->_snake52._event, _vm->_snake52._priority, _vm->_snake52._u16Param1, _vm->_snake52._u16Param2, _vm->_snake52._u8Param, _vm->_snake52._u32Param);
73 break;
74 case fPIRANHA:
75 _vm->setObjectAnim(oLUCCHETTO53, 0);
76 _vm->setObjectAnim(oGRATAC53, 0);
77 _vm->setObjectAnim(oGRATAA53, 0);
78 _vm->_obj[oLUCCHETTO53]._action = 1240;
79 _vm->_obj[oGRATAC53]._action = 1243;
80 _vm->_obj[oGRATAA53]._action = 1246;
81 _vm->_obj[oLAGO53]._examine = 1237;
82 break;
83 case fMOREAU:
84 _vm->setObjectAnim(oWINDOWB58, 0);
85 _vm->_obj[oWINDOWB58]._action = 1358;
86 break;
87 case fDOOR58:
88 _vm->_scheduler->leftClick(468, 180 + TOP);
89 break;
90 case fHELLEN:
91 _vm->_scheduler->leftClick(336, 263 + TOP);
92 break;
93 case fVALVEON34:
94 if (!(_vm->_dialogMgr->isDialogFinished(616)) && // if the fmv is not done
95 (_vm->isObjectVisible(oTUBOA34)) && // if there's a cut pipe
96 !(_vm->isObjectVisible(oTUBOFT34))) // if there's not tube outside
97 _vm->_animMgr->smkToggleTrackAudio(0, 2, true);
98 break;
99 case fVALVEOFF34:
100 _vm->_animMgr->smkToggleTrackAudio(0, 2, false);
101 break;
102
103 case fCHARACTEROFF:
104 _vm->_flagShowCharacter = false;
105 break;
106 case fCHARACTERON:
107 _vm->_flagShowCharacter = true;
108 break;
109 case fCHARACTERFOREGROUND:
110 _vm->_pathFind->setForcedActorPos(BOX_FOREGROUND);
111 break;
112 case fCHARACTERBACKGROUND:
113 _vm->_pathFind->setForcedActorPos(BOX_BACKGROUND);
114 break;
115 case fCHARACTERNORM:
116 _vm->_pathFind->setForcedActorPos(BOX_NORMAL);
117 break;
118 case fSETEXTRA:
119 _vm->_obj[objectId].setFlagExtra(true);
120 break;
121 case fCLREXTRA:
122 _vm->_obj[objectId].setFlagExtra(false);
123 break;
124
125 case fANIMOFF1:
126 anim->toggleAnimArea(1, false);
127 if (_vm->_curRoom == kRoom11 ||
128 _vm->_curRoom == kRoom1D ||
129 _vm->_curRoom == kRoom14 ||
130 _vm->_curRoom == kRoom22 ||
131 _vm->_curRoom == kRoom48 ||
132 _vm->_curRoom == kRoom4P)
133 _vm->_animMgr->smkToggleTrackAudio(0, 1, false);
134 break;
135 case fANIMOFF2:
136 anim->toggleAnimArea(2, false);
137 if (_vm->_curRoom == kRoom2E)
138 _vm->_animMgr->smkToggleTrackAudio(0, 2, false);
139 break;
140 case fANIMOFF3:
141 anim->toggleAnimArea(3, false);
142 break;
143 case fANIMOFF4:
144 anim->toggleAnimArea(4, false);
145 if (_vm->_curRoom == kRoom28)
146 _vm->_animMgr->smkToggleTrackAudio(0, 1, false);
147 break;
148
149 case fANIMON1:
150 anim->toggleAnimArea(1, true);
151 if (_vm->_curRoom == kRoom14 || _vm->_curRoom == kRoom1D || _vm->_curRoom == kRoom22 || _vm->_curRoom == kRoom48 || _vm->_curRoom == kRoom4P) {
152 _vm->_animMgr->smkToggleTrackAudio(0, 1, true);
153 }
154 break;
155 case fANIMON2:
156 anim->toggleAnimArea(2, true);
157 if (_vm->_curRoom == kRoom2E)
158 _vm->_animMgr->smkToggleTrackAudio(0, 2, true);
159 break;
160 case fANIMON3:
161 anim->toggleAnimArea(3, true);
162 break;
163 case fANIMON4:
164 anim->toggleAnimArea(4, true);
165 break;
166 case fENDDEMO:
167 _vm->demoOver();
168 _vm->quitGame();
169 break;
170 case fSTOP2TXT:
171 h->_status |= ATF_WAITTEXT;
172 // Sets a flag that is always cleared when you finish speaking
173 // if the flag is cleared the anim no longer plays
174 // (to be done in the smacker player)
175 // also the counters in next() stops
176 break;
177 default:
178 break;
179 }
180 }
181
processAtFrame(ATFHandle * h,int type,int atf)182 void AnimTypeManager::processAtFrame(ATFHandle *h, int type, int atf) {
183 const uint16 index = h->_curAnim->_atFrame[atf]._index;
184
185 switch (type) {
186 case ATFTEXT:
187 _vm->_textMgr->characterSayInAction(index);
188 break;
189 case ATFTEXTACT:
190 _vm->_textMgr->characterSayInAction(_vm->_obj[h->_object]._action);
191 break;
192 case ATFTEXTEX:
193 _vm->_textMgr->characterSayInAction(_vm->_obj[h->_object]._examine);
194 break;
195 case ATFCLR:
196 _vm->setObjectVisible(index, false);
197 break;
198 case ATFCLRI:
199 _vm->removeIcon(index);
200 break;
201 case ATFCEX:
202 _vm->_obj[h->_object]._examine = index;
203 break;
204 case ATFCACT:
205 _vm->_obj[h->_object]._action = index;
206 break;
207 case ATFSET:
208 _vm->setObjectVisible(index, true);
209 break;
210 case ATFSETI:
211 _vm->addIcon(index);
212 break;
213 case ATFDO:
214 executeAtFrameDoit(h, index, h->_object);
215 break;
216 case ATFROOM:
217 _vm->changeRoom(index);
218 break;
219 case ATFSETPOS:
220 _vm->_pathFind->setPosition(index);
221 break;
222 case ATFDIALOG:
223 _vm->_dialogMgr->playDialog(index);
224 break;
225 case ATFCOBJANIM:
226 _vm->_obj[h->_object]._anim = index;
227 break;
228 case ATFCOBJBOX:
229 _vm->_obj[h->_object]._nbox = index;
230 break;
231 case ATFCOBJPOS:
232 _vm->_obj[h->_object]._position = index;
233 break;
234 case ATFSETFORE:
235 _vm->_obj[index]._nbox = BOX_FOREGROUND;
236 break;
237 case ATFSETBACK:
238 _vm->_obj[index]._nbox = BOX_BACKGROUND;
239 break;
240 case ATFSWITCH:
241 _vm->setObjectVisible(index, !_vm->isObjectVisible(index));
242 break;
243 case ATFSETROOMT:
244 _vm->_logicMgr->setupAltRoom(index, true);
245 break;
246 case ATFSETROOMF:
247 _vm->_logicMgr->setupAltRoom(index, false);
248 break;
249 case ATFREADBOX:
250 switch (index) {
251 case 1: {
252 const Common::String filename = Common::String::format("%s.3d", _vm->_room[_vm->_curRoom]._baseName);
253 _vm->read3D(filename);
254 _vm->_room[_vm->_curRoom].setExtra(false);
255 }
256 break;
257 case 2: {
258 const Common::String filename = Common::String::format("%s2.3d", _vm->_room[_vm->_curRoom]._baseName);
259 _vm->read3D(filename);
260 _vm->_room[_vm->_curRoom].setExtra(true);
261 if (_vm->_curRoom == kRoom37)
262 _vm->_animMgr->smkToggleTrackAudio(0, 1, true);
263 } break;
264 default:
265 break;
266 }
267 break;
268 case ATFONESPEAK:
269 switch (index) {
270 case 1: // Storekeeper's wife
271 if (_vm->_room[kRoom1D].hasExtra())
272 break;
273
274 // Quotes spoken by the storekeeper's wife while she is in the cellar
275 _vm->_textMgr->someoneSay(307 + _oneSpeakDialogCount, oDONNA1D);
276 if (_oneSpeakDialogCount < 6)
277 ++_oneSpeakDialogCount;
278 break;
279
280 case 2: // Storekeeper
281 // Quote when you enter the liquor store: "Ah, it's you again... look round
282 // if you want, but don't disturb me, I've got a lot to do"
283 _vm->_textMgr->someoneSay(1788, ocNEGOZIANTE1A);
284 break;
285 default:
286 break;
287 }
288 break;
289 case ATFEND:
290 _vm->demoOver();
291 _vm->quitGame();
292 break;
293 default:
294 break;
295 }
296 }
297
init(uint16 an,uint16 obj)298 void AnimTypeManager::init(uint16 an, uint16 obj) {
299 SAnim *anim = &_vm->_animMgr->_animTab[an];
300 ATFHandle *handle = &_animType[kAnimTypeCharacter];
301
302 if (anim->_flag & SMKANIM_BKG)
303 handle = &_animType[kAnimTypeBackground];
304 if (anim->_flag & SMKANIM_ICON)
305 handle = &_animType[kAnimTypeIcon];
306
307 handle->_curAnim = anim;
308 handle->_object = obj ? obj : _vm->_curObj;
309 handle->_curFrame = 0;
310 handle->_lastFrame = -1;
311 handle->_status = 0;
312 }
313
next()314 void AnimTypeManager::next() {
315 for (int i = 0; i < 3; ++i) {
316 if (!(_animType[i]._status & ATF_WAITTEXT) || !_vm->_flagCharacterSpeak)
317 ++_animType[i]._curFrame;
318 }
319 }
320
end(int type)321 void AnimTypeManager::end(int type) {
322 ATFHandle *h = &_animType[type];
323 SAnim *anim = h->_curAnim;
324 h->_curFrame = 0;
325
326 // if this ATFrame has already been handled
327 if (h->_curFrame == h->_lastFrame)
328 return;
329
330 h->_lastFrame = h->_curFrame;
331
332 for (int32 i = 0; i < MAXATFRAME; ++i) {
333 // if it's time to run this AtFrame
334 if (anim->_atFrame[i]._numFrame == 0 && anim->_atFrame[i]._type) {
335 const uint8 area = anim->_atFrame[i]._area;
336 if ( area == 0 ||
337 (area == 1 && anim->isAnimAreaShown(1)) ||
338 (area == 2 && anim->isAnimAreaShown(2)) ||
339 (area == 3 && anim->isAnimAreaShown(3)) ||
340 (area == 4 && anim->isAnimAreaShown(4)))
341 processAtFrame(h, anim->_atFrame[i]._type, i);
342 }
343 }
344
345 h->_curAnim = nullptr;
346 }
347
handler(int type)348 void AnimTypeManager::handler(int type) {
349 ATFHandle *h = &_animType[type];
350 SAnim *anim = h->_curAnim;
351 if (anim == nullptr)
352 return;
353
354 if (h->_curFrame == 0)
355 ++h->_curFrame;
356 // if this ATFrame has already been applied
357 if (h->_curFrame <= h->_lastFrame)
358 return;
359
360 for (int32 i = 0; i < MAXATFRAME; ++i) {
361 // if it's time to run this AtFrame
362 if (anim->_atFrame[i]._numFrame > h->_lastFrame &&
363 anim->_atFrame[i]._numFrame <= h->_curFrame &&
364 anim->_atFrame[i]._numFrame != 0) {
365 const uint8 child = anim->_atFrame[i]._area;
366 if ( child == 0 ||
367 (child == 1 && anim->isAnimAreaShown(1)) ||
368 (child == 2 && anim->isAnimAreaShown(2)) ||
369 (child == 3 && anim->isAnimAreaShown(3)) ||
370 (child == 4 && anim->isAnimAreaShown(4)))
371 processAtFrame(h, anim->_atFrame[i]._type, i);
372 }
373 }
374
375 // set _lastFrame
376 h->_lastFrame = h->_curFrame;
377 }
378
379 } // End of namespace Trecision
380