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 "hdb/hdb.h"
24 #include "hdb/ai.h"
25 #include "hdb/gfx.h"
26 #include "hdb/lua-script.h"
27 #include "hdb/map.h"
28 #include "hdb/sound.h"
29 #include "hdb/window.h"
30 
31 namespace HDB {
32 
33 static const char *cineTypeStr[] = {
34 	"C_NO_COMMAND",
35 	"C_STOPCINE",
36 	"C_LOCKPLAYER",
37 	"C_UNLOCKPLAYER",
38 	"C_SETCAMERA",
39 	"C_MOVECAMERA",
40 	"C_WAIT",
41 	"C_WAITUNTILDONE",
42 	"C_MOVEENTITY",
43 	"C_DIALOG",
44 	"C_ANIMENTITY",
45 	"C_RESETCAMERA",
46 	"C_SETENTITY",
47 	"C_STARTMAP",
48 	"C_MOVEPIC",
49 	"C_MOVEMASKEDPIC",
50 	"C_DRAWPIC",
51 	"C_DRAWMASKEDPIC",
52 	"C_FADEIN",
53 	"C_FADEOUT",
54 	"C_SPAWNENTITY",
55 	"C_PLAYSOUND",
56 	"C_CLEAR_FG",
57 	"C_SET_FG",
58 	"C_SET_BG",
59 	"C_FUNCTION",
60 	"C_ENTITYFACE",
61 	"C_USEENTITY",
62 	"C_REMOVEENTITY",
63 	"C_SETANIMFRAME",
64 	"C_TEXTOUT",
65 	"C_CENTERTEXTOUT",
66 	"C_PLAYVOICE",
67 
68 	"C_ENDLIST"
69 };
70 
processCines()71 void AI::processCines() {
72 	if (!_cineActive)
73 		return;
74 
75 	// Make sure Dialogs are timing out
76 	g_hdb->_window->checkDialogClose(0, 0);
77 
78 	// Make sure Cine Pics are drawing
79 	for (int i = 0; i < _numCineBlitList; i++) {
80 		if (_cineBlitList[i]->masked == false)
81 			_cineBlitList[i]->pic->draw(_cineBlitList[i]->x, _cineBlitList[i]->y);
82 		else
83 			_cineBlitList[i]->pic->drawMasked(_cineBlitList[i]->x, _cineBlitList[i]->y);
84 	}
85 
86 	// Check for Game Pause
87 	if (g_hdb->getPause())
88 		return;
89 
90 	bool bailOut = false;
91 	bool complete = false;
92 
93 	for (uint i = 0; i < _cine.size(); i++) {
94 		debug(3, "processCines: [%d] %s now: %d  start: %d delay: %d", i, cineTypeStr[_cine[i]->cmdType],
95 				g_system->getMillis(), _cine[i]->start, _cine[i]->delay);
96 
97 		switch (_cine[i]->cmdType) {
98 		case C_STOPCINE:
99 			{
100 				char func[64];
101 				memset(func, 0, 64);
102 
103 				if (_cine[i]->title)
104 					strcpy(func, _cine[i]->title);
105 
106 				cineCleanup();
107 				if (func[0])
108 					g_hdb->_lua->callFunction(func, 0);
109 			}
110 			break;
111 		case C_STARTMAP:
112 			{
113 				const char *title = _cine[i]->title;
114 				// free all gfx alloc'ed during cine
115 				cineFreeGfx();
116 				_cineActive = false;
117 				_playerLock = false;
118 				_cameraLock = false;
119 				g_hdb->_window->setInfobarDark(0);
120 				g_hdb->_gfx->setPointerState(1);
121 				_cine.resize(0);
122 				_numCineFreeList = 0;
123 				_numCineBlitList = 0;
124 				// if cine is aborted and an abort function was specified, call it
125 				if (_cineAborted && _cineAbortFunc)
126 					g_hdb->_lua->callFunction(_cineAbortFunc, 0);
127 				g_hdb->changeMap(title);
128 				return;
129 			}
130 			break;
131 		case C_LOCKPLAYER:
132 			_playerLock = true;
133 			complete = true;
134 			if (_player)
135 				stopEntity(_player);
136 			clearWaypoints();
137 			break;
138 		case C_UNLOCKPLAYER:
139 			_playerLock = false;
140 			complete = true;
141 			break;
142 		case C_SETCAMERA:
143 			_cameraX = _cine[i]->x;
144 			_cameraY = _cine[i]->y;
145 			g_hdb->_map->centerMapXY((int)_cameraX + 16, (int)_cameraY + 16);
146 			_cameraLock = true;
147 			complete = true;
148 			break;
149 		case C_RESETCAMERA:
150 			{
151 				_cameraLock = false;
152 				int px, py;
153 				g_hdb->_ai->getPlayerXY(&px, &py);
154 				g_hdb->_map->centerMapXY(px + 16, py + 16);
155 				complete = true;
156 			}
157 			break;
158 		case C_MOVECAMERA:
159 			_cameraLock = true;
160 			if (!(_cine[i]->start)) {
161 				debug(3, "C_MOVECAMERA: [%d] now: x: %f, y: %f, speed: %d", i, _cine[i]->x, _cine[i]->y, _cine[i]->speed);
162 				_cine[i]->xv = (((double)_cine[i]->x) - _cameraX) / (double)_cine[i]->speed;
163 				_cine[i]->yv = (((double)_cine[i]->y) - _cameraY) / (double)_cine[i]->speed;
164 				_cine[i]->start = 1;
165 			}
166 			_cameraX += _cine[i]->xv;
167 			_cameraY += _cine[i]->yv;
168 			debug(3, "C_MOVECAMERA: _cine[%d]->xv: %f, _cine[%d]->yv: %f", i, _cine[i]->xv, i, _cine[i]->yv);
169 			debug(3, "C_MOVECAMERA: abs(_cameraX - _cine[i]->x): %f, abs(_cameraY - _cine[i]->y): %f", fabs(_cameraX - _cine[i]->x), fabs(_cameraY - _cine[i]->y));
170 			if (fabs(_cameraX - _cine[i]->x) <= 1 && fabs(_cameraY - _cine[i]->y) <= 1) {
171 				_cameraX = _cine[i]->x;
172 				_cameraY = _cine[i]->y;
173 				complete = true;
174 			}
175 			g_hdb->_map->centerMapXY((int)_cameraX + 16, (int)_cameraY + 16);
176 			break;
177 		case C_WAIT:
178 			if (!(_cine[i]->start)) {
179 				_cine[i]->start = 1;
180 				_cine[i]->delay = g_system->getMillis() + _cine[i]->delay * 1000;
181 			} else if (_cine[i]->delay < g_system->getMillis())
182 				complete = true;
183 			else
184 				bailOut = true;
185 			break;
186 		case C_WAITUNTILDONE:
187 			if (!i)
188 				complete = true;
189 			else
190 				bailOut = true;
191 
192 			break;
193 		case C_SETENTITY:
194 			_cine[i]->e = locateEntity(_cine[i]->string);
195 			if (_cine[i]->e) {
196 				_cine[i]->e->tileX = (int)_cine[i]->x / kTileWidth;
197 				_cine[i]->e->x = (int)_cine[i]->x;
198 				_cine[i]->e->tileY = (int)_cine[i]->y / kTileHeight;
199 				_cine[i]->e->y = (int)_cine[i]->y;
200 				_cine[i]->e->level = (int)_cine[i]->x2;
201 				debug(2, "Found '%s' in setEntity", _cine[i]->string);
202 			} else
203 				warning("Can't locate '%s' in setEntity", _cine[i]->string);
204 
205 			complete = true;
206 			break;
207 		case C_MOVEENTITY:
208 			if (!_cine[i]->start) {
209 				AIEntity *e = locateEntity(_cine[i]->title);
210 				if (e) {
211 					_cine[i]->e = e;
212 					_cine[i]->e->moveSpeed = _cine[i]->speed;
213 					_cine[i]->e->level = (int)_cine[i]->x2;
214 					setEntityGoal(_cine[i]->e, (int)_cine[i]->x, (int)_cine[i]->y);
215 					_cine[i]->start = 1;
216 				} else
217 					warning("Can't locate '%s' in moveEntity", _cine[i]->title);
218 			} else {
219 				debug(3, "C_MOVEENTITY: %d, %s tileX: %d, goalX: %d tileY %d, goalY: %d", i, AIType2Str(_cine[i]->e->type), _cine[i]->e->tileX, _cine[i]->e->goalX, _cine[i]->e->tileY, _cine[i]->e->goalY);
220 				if (!_cine[i]->e->goalX)
221 					complete = true;
222 			}
223 			break;
224 		case C_ANIMENTITY:
225 			if (!_cine[i]->start) {
226 				AIEntity *e = locateEntity(_cine[i]->title);
227 				if (e) {
228 					_cine[i]->e = e;
229 					e->state = (AIState)_cine[i]->speed;
230 					_cine[i]->start = 1;
231 					if (_cine[i]->end) // Loop ?
232 						complete = true;
233 					e->animFrame = 0;
234 					e->animDelay = e->animCycle;
235 					animEntFrames(e);
236 				} else {
237 					warning("Can't locate '%s' in animEntity", _cine[i]->title);
238 					complete = true;
239 				}
240 			} else {
241 				AIEntity *e = _cine[i]->e;
242 				if (!e->animFrame && e->animDelay == e->animCycle) {
243 					e->state = STATE_STANDDOWN;
244 					e->animFrame = 0;
245 					e->animDelay = e->animCycle;
246 					complete = true;
247 				}
248 			}
249 			break;
250 		case C_SETANIMFRAME:
251 			{
252 				AIEntity *e = locateEntity(_cine[i]->title);
253 				if (e) {
254 					e->state = (AIState)_cine[i]->start;
255 					e->animFrame = _cine[i]->end;
256 					e->animDelay = e->animCycle;
257 					animEntFrames(e);
258 					e->state = STATE_NONE;
259 					complete = true;
260 				}
261 			}
262 			break;
263 		case C_ENTITYFACE:
264 			{
265 				AIEntity *e = locateEntity(_cine[i]->title);
266 
267 				if (e) {
268 					int d = (int)_cine[i]->x;
269 					e->dir = (AIDir)d;
270 					switch (e->dir) {
271 					case DIR_UP:
272 						e->state = STATE_STANDUP;
273 						break;
274 					case DIR_DOWN:
275 						e->state = STATE_STANDDOWN;
276 						break;
277 					case DIR_LEFT:
278 						e->state = STATE_STANDLEFT;
279 						break;
280 					case DIR_RIGHT:
281 						e->state = STATE_STANDRIGHT;
282 						break;
283 					default:
284 						break;
285 					}
286 				} else
287 					warning("Can't find %s to ENTITYFACE", _cine[i]->title);
288 
289 				complete = true;
290 			}
291 			break;
292 		case C_DIALOG:
293 			if (_cine[i]->start) {
294 				g_hdb->_window->openDialog(_cine[i]->title, -1, _cine[i]->string, 0, NULL);
295 				g_hdb->_window->setDialogDelay(_cine[i]->delay);
296 				_cine[i]->start = 0;
297 			} else if (g_hdb->_window->getDialogDelay() < g_hdb->getTimeSlice())
298 				complete = true;
299 			break;
300 		case C_TEXTOUT:
301 			if (!_cine[i]->start) {
302 				g_hdb->_window->textOut(_cine[i]->title, _cine[i]->x, _cine[i]->y, _cine[i]->end);
303 				_cine[i]->start = 1;
304 			} else if (!g_hdb->_window->textOutActive())
305 				complete = true;
306 			break;
307 		case C_CENTERTEXTOUT:
308 			if (!_cine[i]->start) {
309 				g_hdb->_window->centerTextOut(_cine[i]->title, _cine[i]->y, _cine[i]->end);
310 				_cine[i]->start = 1;
311 			} else if (!g_hdb->_window->textOutActive())
312 				complete = true;
313 			break;
314 		case C_DRAWPIC:
315 			{
316 				Picture *p = cineFindInBlitList(_cine[i]->id);
317 				if (p == NULL) {
318 					p = g_hdb->_gfx->loadPic(_cine[i]->string);
319 					cineAddToFreeList(p);
320 					cineAddToBlitList(_cine[i]->id, p, (int)_cine[i]->x, (int)_cine[i]->y, false);
321 				}
322 				_cine[i]->pic = p;
323 				_cine[i]->pic->draw((int)_cine[i]->x, (int)_cine[i]->y);
324 				complete = true;
325 			}
326 			break;
327 		case C_DRAWMASKEDPIC:
328 			{
329 				Picture *p = cineFindInBlitList(_cine[i]->id);
330 				if (p == NULL) {
331 					p = g_hdb->_gfx->loadPic(_cine[i]->string);
332 					cineAddToFreeList(p);
333 					cineAddToBlitList(_cine[i]->id, p, (int)_cine[i]->x, (int)_cine[i]->y, true);
334 				}
335 				_cine[i]->pic = p;
336 				_cine[i]->pic->drawMasked((int)_cine[i]->x, (int)_cine[i]->y);
337 				complete = true;
338 			}
339 			break;
340 
341 		case C_MOVEPIC:
342 			if (!_cine[i]->start) {
343 				Picture *pic = cineFindInBlitList(_cine[i]->id);
344 				if (!pic) {
345 					pic = g_hdb->_gfx->loadPic(_cine[i]->string);
346 					cineAddToFreeList(pic);
347 				} else
348 					cineRemoveFromBlitList(_cine[i]->id);
349 				_cine[i]->pic = pic;
350 				_cine[i]->start = 1;
351 			}
352 
353 			cineRemoveFromBlitList(_cine[i]->id);
354 			_cine[i]->x += _cine[i]->xv;
355 			_cine[i]->y += _cine[i]->yv;
356 			cineAddToBlitList(_cine[i]->id, _cine[i]->pic, (int)_cine[i]->x, (int)_cine[i]->y, false);
357 			if (abs((int)(_cine[i]->x - _cine[i]->x2)) <= 1 && abs((int)(_cine[i]->y - _cine[i]->y2)) <= 1)
358 				complete = true;
359 			break;
360 
361 		case C_MOVEMASKEDPIC:
362 			if (!_cine[i]->start) {
363 				Picture *pic = cineFindInBlitList(_cine[i]->id);
364 				if (!pic) {
365 					pic = g_hdb->_gfx->loadPic(_cine[i]->string);
366 					cineAddToFreeList(pic);
367 				} else
368 					cineRemoveFromBlitList(_cine[i]->id);
369 				_cine[i]->pic = pic;
370 				_cine[i]->start = 1;
371 			}
372 
373 			cineRemoveFromBlitList(_cine[i]->id);
374 			_cine[i]->x += _cine[i]->xv;
375 			_cine[i]->y += _cine[i]->yv;
376 			cineAddToBlitList(_cine[i]->id, _cine[i]->pic, (int)_cine[i]->x, (int)_cine[i]->y, true);
377 			if (abs((int)(_cine[i]->x - _cine[i]->x2)) <= 1 && abs((int)(_cine[i]->y - _cine[i]->y2)) <= 1)
378 				complete = true;
379 			break;
380 
381 		case C_USEENTITY:
382 			for (Common::Array<AIEntity *>::iterator it = _ents->begin(); it != _ents->end(); ++it) {
383 				if (Common::matchString((*it)->entityName, _cine[i]->string, true))
384 					g_hdb->useEntity((*it));
385 			}
386 			for (int k = 0; k < kMaxActions; k++) {
387 				if (Common::matchString(_actions[k].entityName, _cine[i]->string, true)) {
388 					checkActionList(&_dummyPlayer, _actions[k].x1, _actions[k].y1, false);
389 					checkActionList(&_dummyPlayer, _actions[k].x2, _actions[k].y2, false);
390 				}
391 			}
392 			for (int j = 0; j < kMaxAutoActions; j++) {
393 				if (Common::matchString(_autoActions[j].entityName, _cine[i]->string, true) && !_autoActions[j].activated)
394 					checkAutoList(&_dummyPlayer, _autoActions[j].x, _autoActions[j].y);
395 			}
396 			complete = true;
397 			break;
398 		case C_PLAYSOUND:
399 			g_hdb->_sound->playSound((int)_cine[i]->start);
400 			complete = true;
401 			break;
402 		case C_PLAYVOICE:
403 			g_hdb->_sound->playVoice((int)_cine[i]->x, (int)_cine[i]->y);
404 			complete = true;
405 			break;
406 		case C_FADEIN:
407 			if (!_cine[i]->start) {
408 				g_hdb->_gfx->setFade(true, (bool)_cine[i]->end, _cine[i]->speed);
409 				_cine[i]->start = 1;
410 			} else if (!g_hdb->_gfx->isFadeActive())
411 				complete = true;
412 			break;
413 		case C_FADEOUT:
414 			if (!_cine[i]->start) {
415 				g_hdb->_gfx->setFade(false, (bool)_cine[i]->end, _cine[i]->speed);
416 				_cine[i]->start = 1;
417 			} else if (!g_hdb->_gfx->isFadeActive())
418 				complete = true;
419 			break;
420 		case C_SPAWNENTITY:
421 			{
422 				int x2 = (int)_cine[i]->x2;
423 				int y2 = (int)_cine[i]->y2;
424 				spawn((AIType)x2, (AIDir)y2, (int)_cine[i]->x, (int)_cine[i]->y, _cine[i]->title, _cine[i]->string,
425 					_cine[i]->id, (AIDir)_cine[i]->start, (int)_cine[i]->end, (int)_cine[i]->delay, (int)_cine[i]->speed, 1);
426 				complete = true;
427 			}
428 			break;
429 		case C_REMOVEENTITY:
430 			{
431 				AIEntity *e = locateEntity(_cine[i]->string);
432 				if (e)
433 					removeEntity(e);
434 				complete = true;
435 			}
436 			break;
437 		case C_CLEAR_FG:
438 			g_hdb->_map->setMapFGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, -1);
439 			g_hdb->_map->removeFGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
440 			complete = true;
441 			break;
442 		case C_SET_BG:
443 			g_hdb->_map->setMapBGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, (int)_cine[i]->start);
444 			g_hdb->_map->addBGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
445 			complete = true;
446 			break;
447 		case C_SET_FG:
448 			g_hdb->_map->setMapFGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, (int)_cine[i]->start);
449 			g_hdb->_map->addFGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
450 			complete = true;
451 			break;
452 		case C_FUNCTION:
453 			g_hdb->_lua->callFunction(_cine[i]->title, 0);
454 			complete = true;
455 			break;
456 		default:
457 			break;
458 		}
459 
460 		if (bailOut)
461 			return;
462 
463 		if (complete && _cine.size()) {
464 			_cine.remove_at(i);
465 			i--;
466 			complete = false;
467 		}
468 	}
469 }
470 
cineCleanup()471 void AI::cineCleanup() {
472 	cineFreeGfx();
473 	_cineActive = false;
474 	// If aborted and abort function specified, call it
475 	if (_cineAborted && _cineAbortFunc)
476 		g_hdb->_lua->callFunction(_cineAbortFunc, 0);
477 
478 	_cameraLock = false;
479 	_playerLock = false;
480 	g_hdb->_window->setInfobarDark(0);
481 	g_hdb->_gfx->setPointerState(1);
482 
483 	int px, py;
484 	getPlayerXY(&px, &py);
485 	g_hdb->_map->centerMapXY(px + 16, py + 16);
486 }
487 
cineAbort()488 void AI::cineAbort() {
489 	for (uint i = 0; i < _cine.size(); i++) {
490 		if (_cine[i]->cmdType == C_STARTMAP || _cine[i]->cmdType == C_STOPCINE)
491 			_cine[0] = _cine[i];
492 	}
493 
494 	_cine.resize(1);
495 
496 	g_hdb->_window->closeAll();
497 
498 	if (_player)
499 		stopEntity(_player);
500 	_cineAborted = true;
501 }
502 
cineAddToBlitList(const char * id,Picture * pic,int x,int y,bool masked)503 void AI::cineAddToBlitList(const char *id, Picture *pic, int x, int y, bool masked) {
504 	_cineBlitList[_numCineBlitList] = new CineBlit;
505 	_cineBlitList[_numCineBlitList]->id = id;
506 	_cineBlitList[_numCineBlitList]->pic = pic;
507 	_cineBlitList[_numCineBlitList]->x = x;
508 	_cineBlitList[_numCineBlitList]->y = y;
509 	_cineBlitList[_numCineBlitList]->masked = masked;
510 	_numCineBlitList++;
511 }
512 
cineFindInBlitList(const char * name)513 Picture *AI::cineFindInBlitList(const char *name) {
514 	for (int i = 0; i < _numCineBlitList; i++) {
515 		if (Common::matchString(_cineBlitList[i]->id, name, true))
516 			return _cineBlitList[i]->pic;
517 	}
518 	return NULL;
519 }
520 
cineRemoveFromBlitList(const char * name)521 void AI::cineRemoveFromBlitList(const char *name) {
522 	for (int i = 0; i < _numCineBlitList; i++) {
523 		if (Common::matchString(_cineBlitList[i]->id, name, true)) {
524 			delete _cineBlitList[i];
525 			for (; i < _numCineBlitList - 1; i++)
526 				_cineBlitList[i] = _cineBlitList[i + 1];
527 			_numCineBlitList--;
528 			_cineBlitList[_numCineBlitList] = NULL;
529 			return;
530 		}
531 	}
532 }
533 
cineAddToFreeList(Picture * pic)534 void AI::cineAddToFreeList(Picture *pic) {
535 	if (_numCineFreeList >= kMaxCineGfx) {
536 		warning("cineAddToFreeList: Too many gfx in Cinematic!");
537 		return;
538 	}
539 	_cineFreeList[_numCineFreeList] = pic;
540 	_numCineFreeList++;
541 }
542 
cineFreeGfx()543 void AI::cineFreeGfx() {
544 	for (int i = 0; i < _numCineFreeList; i++)
545 		delete _cineFreeList[i];
546 
547 	_numCineFreeList = 0;
548 }
549 
cineStart(bool abortable,const char * abortFunc)550 void AI::cineStart(bool abortable, const char *abortFunc) {
551 	_cineAbortable = abortable;
552 	_cineAborted = false;
553 	_cineAbortFunc = abortFunc;
554 	_numCineBlitList = 0;
555 	_numCineFreeList = 0;
556 	_cineActive = true;
557 	_playerLock = false;
558 	_cameraLock = false;
559 
560 	_cine.clear();
561 }
562 
cineStop(const char * funcNext)563 void AI::cineStop(const char *funcNext) {
564 	CineCommand *cmd = new CineCommand;
565 	cmd->cmdType = C_STOPCINE;
566 	cmd->title = funcNext;
567 	_cine.push_back(cmd);
568 }
569 
cineStartMap(const char * mapName)570 void AI::cineStartMap(const char *mapName) {
571 	CineCommand *cmd = new CineCommand;
572 	cmd->cmdType = C_STARTMAP;
573 	cmd->title = mapName;
574 	_cine.push_back(cmd);
575 }
576 
cineLockPlayer()577 void AI::cineLockPlayer() {
578 	CineCommand *cmd = new CineCommand;
579 	cmd->cmdType = C_LOCKPLAYER;
580 	_cine.push_back(cmd);
581 }
582 
cineUnlockPlayer()583 void AI::cineUnlockPlayer() {
584 	CineCommand *cmd = new CineCommand;
585 	cmd->cmdType = C_UNLOCKPLAYER;
586 	_cine.push_back(cmd);
587 }
588 
cineSetCamera(int x,int y)589 void AI::cineSetCamera(int x, int y) {
590 	CineCommand *cmd = new CineCommand;
591 	cmd->x = x * kTileWidth;
592 	cmd->y = y * kTileHeight;
593 	cmd->cmdType = C_SETCAMERA;
594 	_cine.push_back(cmd);
595 }
596 
cineResetCamera()597 void AI::cineResetCamera() {
598 	CineCommand *cmd = new CineCommand;
599 	cmd->cmdType = C_RESETCAMERA;
600 	_cine.push_back(cmd);
601 }
602 
cineMoveCamera(int x,int y,int speed)603 void AI::cineMoveCamera(int x, int y, int speed) {
604 	CineCommand *cmd = new CineCommand;
605 	cmd->start = 0;
606 	cmd->x = x * kTileWidth;
607 	cmd->y = y * kTileHeight;
608 	cmd->speed = speed;
609 	debug(2, "Setting up C_MOVECAMERA: x: %f, y: %f", cmd->x, cmd->y);
610 	cmd->cmdType = C_MOVECAMERA;
611 	_cine.push_back(cmd);
612 }
613 
cineWait(int seconds)614 void AI::cineWait(int seconds) {
615 	CineCommand *cmd = new CineCommand;
616 	cmd->start = 0;
617 	cmd->cmdType = C_WAIT;
618 	cmd->delay = seconds;
619 	_cine.push_back(cmd);
620 }
621 
cineWaitUntilDone()622 void AI::cineWaitUntilDone() {
623 	CineCommand *cmd = new CineCommand;
624 	cmd->cmdType = C_WAITUNTILDONE;
625 	_cine.push_back(cmd);
626 }
627 
cineSetEntity(const char * entName,int x,int y,int level)628 void AI::cineSetEntity(const char *entName, int x, int y, int level) {
629 	CineCommand *cmd = new CineCommand;
630 	cmd->string = entName;
631 	cmd->x = x * kTileWidth;
632 	cmd->y = y * kTileHeight;
633 	cmd->x2 = level;
634 	cmd->cmdType = C_SETENTITY;
635 	_cine.push_back(cmd);
636 }
637 
cineMoveEntity(const char * entName,int x,int y,int level,int speed)638 void AI::cineMoveEntity(const char *entName, int x, int y, int level, int speed) {
639 	CineCommand *cmd = new CineCommand;
640 	cmd->x = x;
641 	cmd->y = y;
642 	cmd->x2 = level;
643 	cmd->start = 0;
644 	cmd->speed = speed;
645 	cmd->title = entName;
646 	cmd->cmdType = C_MOVEENTITY;
647 	_cine.push_back(cmd);
648 }
649 
cineAnimEntity(const char * entName,AIState state,int loop)650 void AI::cineAnimEntity(const char *entName, AIState state, int loop) {
651 	CineCommand *cmd = new CineCommand;
652 	cmd->start = 0;
653 	cmd->title = entName;
654 	cmd->speed = state;
655 	cmd->end = loop;
656 	cmd->cmdType = C_ANIMENTITY;
657 	_cine.push_back(cmd);
658 }
659 
cineSetAnimFrame(const char * entName,AIState state,int frame)660 void AI::cineSetAnimFrame(const char *entName, AIState state, int frame) {
661 	CineCommand *cmd = new CineCommand;
662 	cmd->start = state;
663 	cmd->title = entName;
664 	cmd->end = frame;
665 	cmd->cmdType = C_SETANIMFRAME;
666 	_cine.push_back(cmd);
667 }
668 
cineEntityFace(const char * luaName,double dir)669 void AI::cineEntityFace(const char *luaName, double dir) {
670 	CineCommand *cmd = new CineCommand;
671 	cmd->title = luaName;
672 	cmd->x = dir;
673 	cmd->cmdType = C_ENTITYFACE;
674 	_cine.push_back(cmd);
675 }
676 
cineSpawnEntity(AIType t,AIDir d,int x,int y,const char * func_init,const char * func_action,const char * func_use,AIDir d2,int level,int value1,int value2)677 void AI::cineSpawnEntity(AIType t, AIDir d, int x, int y, const char *func_init, const char *func_action,
678 				const char *func_use, AIDir d2, int level, int value1, int value2) {
679 	CineCommand *cmd = new CineCommand;
680 	cmd->cmdType = C_SPAWNENTITY;
681 	cmd->x2 = (double)t;
682 	cmd->y2 = (double)d;
683 	cmd->x = (double)x;
684 	cmd->y = (double)y;
685 	cmd->title = func_init;
686 	cmd->string = func_action;
687 	cmd->id = func_use;
688 	cmd->start = (int)d2;
689 	cmd->end = level;
690 	cmd->delay = value1;
691 	cmd->speed = value2;
692 
693 	_cine.push_back(cmd);
694 }
695 
cineRemoveEntity(const char * entName)696 void AI::cineRemoveEntity(const char *entName) {
697 	CineCommand *cmd = new CineCommand;
698 	cmd->string = entName;
699 	cmd->cmdType = C_REMOVEENTITY;
700 	_cine.push_back(cmd);
701 }
702 
cineDialog(const char * title,const char * string,int seconds)703 void AI::cineDialog(const char *title, const char *string, int seconds) {
704 	CineCommand *cmd = new CineCommand;
705 	cmd->title = title;
706 	cmd->string = string;
707 	cmd->delay = seconds;
708 	cmd->start = 1;
709 	if (!title || !string)
710 		warning("cineDialog: Missing Title or Text");
711 	cmd->cmdType = C_DIALOG;
712 	debug(6, "In cineDialog: C_DIALOG created. cmd->start: %d, cmd->title: %s", cmd->start, cmd->title);
713 	_cine.push_back(cmd);
714 }
715 
cineTextOut(const char * text,int x,int y,int timer)716 void AI::cineTextOut(const char *text, int x, int y, int timer) {
717 	CineCommand *cmd = new CineCommand;
718 	cmd->title = text;
719 	cmd->x = x;
720 	cmd->y = y;
721 	cmd->end = timer;
722 	cmd->start = 0;
723 	cmd->cmdType = C_TEXTOUT;
724 	_cine.push_back(cmd);
725 }
726 
cineCenterTextOut(const char * text,int y,int timer)727 void AI::cineCenterTextOut(const char *text, int y, int timer) {
728 	CineCommand *cmd = new CineCommand;
729 	cmd->title = text;
730 	cmd->y = y;
731 	cmd->end = timer;
732 	cmd->start = 0;
733 	cmd->cmdType = C_CENTERTEXTOUT;
734 	_cine.push_back(cmd);
735 }
736 
cineDrawPic(const char * id,const char * pic,int x,int y)737 void AI::cineDrawPic(const char *id, const char *pic, int x, int y) {
738 	if (!pic || !id) {
739 		warning("cineDrawPic: Missing ID or PIC");
740 		return;
741 	}
742 
743 	CineCommand *cmd = new CineCommand;
744 	cmd->x = x;
745 	cmd->y = y;
746 	cmd->string = pic;
747 	cmd->id = id;
748 	cmd->cmdType = C_DRAWPIC;
749 	_cine.push_back(cmd);
750 }
751 
cineDrawMaskedPic(const char * id,const char * pic,int x,int y)752 void AI::cineDrawMaskedPic(const char *id, const char *pic, int x, int y) {
753 	if (!pic || !id) {
754 		warning("cineDrawMaskedPic: Missing ID or PIC");
755 		return;
756 	}
757 
758 	CineCommand *cmd = new CineCommand;
759 	cmd->x = x;
760 	cmd->y = y;
761 	cmd->string = pic;
762 	cmd->id = id;
763 	cmd->cmdType = C_DRAWMASKEDPIC;
764 	_cine.push_back(cmd);
765 }
766 
cineMovePic(const char * id,const char * pic,int x1,int y1,int x2,int y2,int speed)767 void AI::cineMovePic(const char *id, const char *pic, int x1, int y1, int x2, int y2, int speed) {
768 	if (!pic || !id) {
769 		warning("cineMovePic: Missing ID or PIC");
770 		return;
771 	}
772 
773 	CineCommand *cmd = new CineCommand;
774 	cmd->x = x1;
775 	cmd->y = y1;
776 	cmd->x2 = x2;
777 	cmd->y2 = y2;
778 	cmd->speed = speed;
779 	cmd->xv = ((double)(x2-x1)) / (double)speed;
780 	cmd->yv = ((double)(y2-y1)) / (double)speed;
781 	cmd->start = 0;
782 	cmd->string = pic;
783 	cmd->id = id;
784 	cmd->cmdType = C_MOVEPIC;
785 	_cine.push_back(cmd);
786 }
787 
cineMoveMaskedPic(const char * id,const char * pic,int x1,int y1,int x2,int y2,int speed)788 void AI::cineMoveMaskedPic(const char *id, const char *pic, int x1, int y1, int x2, int y2, int speed) {
789 	if (!pic || !id) {
790 		warning("cineMoveMaskedPic: Missing ID or PIC");
791 		return;
792 	}
793 
794 	CineCommand *cmd = new CineCommand;
795 	cmd->x = x1;
796 	cmd->y = y1;
797 	cmd->x2 = x2;
798 	cmd->y2 = y2;
799 	cmd->speed = speed;
800 	cmd->xv = ((double)(x2-x1)) / (double)speed;
801 	cmd->yv = ((double)(y2-y1)) / (double)speed;
802 	cmd->start = 0;
803 	cmd->string = pic;
804 	cmd->id = id;
805 	cmd->cmdType = C_MOVEMASKEDPIC;
806 	_cine.push_back(cmd);
807 }
808 
cineUse(const char * entName)809 void AI::cineUse(const char *entName) {
810 	CineCommand *cmd = new CineCommand;
811 	cmd->string = entName;
812 	cmd->cmdType = C_USEENTITY;
813 	_cine.push_back(cmd);
814 }
815 
cinePlaySound(int index)816 void AI::cinePlaySound(int index) {
817 	CineCommand *cmd = new CineCommand;
818 	cmd->start = index;
819 	cmd->cmdType = C_PLAYSOUND;
820 	_cine.push_back(cmd);
821 }
822 
cinePlayVoice(int index,int actor)823 void AI::cinePlayVoice(int index, int actor) {
824 	CineCommand *cmd = new CineCommand;
825 	cmd->x = index;
826 	cmd->y = actor;
827 	cmd->cmdType = C_PLAYVOICE;
828 	_cine.push_back(cmd);
829 }
830 
cineFadeIn(bool isBlack,int steps)831 void AI::cineFadeIn(bool isBlack, int steps) {
832 	CineCommand *cmd = new CineCommand;
833 	cmd->speed = steps;
834 	cmd->end = (int)isBlack;
835 	cmd->start = 0;
836 	cmd->cmdType = C_FADEIN;
837 	_cine.push_back(cmd);
838 }
839 
cineFadeOut(bool isBlack,int steps)840 void AI::cineFadeOut(bool isBlack, int steps) {
841 	CineCommand *cmd = new CineCommand;
842 	cmd->speed = steps;
843 	cmd->end = (int)isBlack;
844 	cmd->start = 0;
845 	cmd->cmdType = C_FADEOUT;
846 	_cine.push_back(cmd);
847 }
848 
cineClearForeground(int x,int y)849 void AI::cineClearForeground(int x, int y) {
850 	CineCommand *cmd = new CineCommand;
851 	cmd->x = x;
852 	cmd->y = y;
853 	cmd->cmdType = C_CLEAR_FG;
854 	_cine.push_back(cmd);
855 }
856 
cineSetBackground(int x,int y,int index)857 void AI::cineSetBackground(int x, int y, int index) {
858 	CineCommand *cmd = new CineCommand;
859 	cmd->x = x;
860 	cmd->y = y;
861 	cmd->start = index;
862 	cmd->cmdType = C_SET_BG;
863 	_cine.push_back(cmd);
864 }
865 
cineSetForeground(int x,int y,int index)866 void AI::cineSetForeground(int x, int y, int index) {
867 	CineCommand *cmd = new CineCommand;
868 	cmd->x = x;
869 	cmd->y = y;
870 	cmd->start = index;
871 	cmd->cmdType = C_SET_FG;
872 	_cine.push_back(cmd);
873 }
874 
cineFunction(const char * func)875 void AI::cineFunction(const char *func) {
876 	CineCommand *cmd = new CineCommand;
877 	cmd->title = func;
878 	cmd->cmdType = C_FUNCTION;
879 	_cine.push_back(cmd);
880 }
881 
882 } // End of Namespace
883